datetime:将一个月分成10天


datetime: split a month 10-day periods

我发送了一个较早的日期,它会返回从较早日期到今天的时间段,这些时间段缩短了几十天。

2016年1月14日示例

我需要结果如下:

  • 2016年1月11日至2016年1日20日
  • 2016年1月21日至2016年1日31日
  • 2016年2月1日至2016年2月份10日
  • 2016年2月11日至2016年2月份20日
  • 2016年2月21日至2016年2月份29日
  • 2016年3月1日至2016年3月份10日
  • 2016年3月11日至2016年3月份20日
  • 2016年3月21日至2016年3月份31日
  • 2016年4月1日至2016年4月份10日
  • 2016年4月11日至2016年4日20日

这里是我的代码:

function date_interval($startTime = false){
    if( ! $startTime){
        return array();
    } else {
    if(date('d',$startTime) < 10){
        $actual = mktime(0, 0, 0, date('m',$startTime), 1, date('Y',$startTime));
    } elseif(date('d',$startTime) < 20){
        $actual = mktime(0, 0, 0, date('m',$startTime), 10, date('Y',$startTime));
    } else {
        $actual = mktime(0, 0, 0, date('m',$startTime), 20, date('Y',$startTime));
    }
    if(date('d',time()) < 10) {
        $target = mktime(0, 0, 0, date('m',time()), 10, date('Y',time()));
    } elseif(date('d',time()) < 20) {
        $target = mktime(0, 0, 0, date('m',time()), 20, date('Y',time()));
    } else {
        $target = mktime(0, 0, 0, date('m',time())+1, 1, date('Y',time()));
    }

    $current = $actual;
    $last = $actual;
    while($current < $target) {
        if(date('d',$current) < 10){
            $current = mktime(0, 0, 0, date('m',$current), 10, date('Y',$current));
        } elseif(date('d',$current) < 20){
            $current = mktime(0, 0, 0, date('m',$current), 20, date('Y',$current)); 
        } else {
            $current = mktime(0, 0, 0, date('m',$current)+1, 1, date('Y',$current));
        } 
        $dateTime[date("Y-m-d", $last) .'~'. date("Y-m-d", $current)] = date('d M Y',$last) . ' - ' . date('d M Y',$current));
        $last = $current;
        }
    }
    return $dateTime;
}

Datetime是php中的宠儿类,它很好地解决了这类问题。在这里,您将startdate作为DATETIME对象提供给函数,函数会抛出一堆列表标记。

在循环中,startDay首先通过增加10天来进行跳跃,然后增加一天来避免重叠。如果你想要最后一行,从上次开始到今天的时间段(不到十天),你可以添加这样的内容:

$return .= '<li>From '.$startDay->format('d M Y').' to '.$today->format('d M Y').'</li>';

环路后

function date_interval(DATETIME $startDay = NULL)
{
      if( NULL == $startDay){ 
        return array(); }
      $return = '';
      $today = new DATETIME('now');
      while(  $today->diff( $startDay )->format('%a%') > 10  )
      {
          $return .= '<li>From '.$startDay->format('d M Y').' to ';
          $startDay->modify('+10 days');
          $return .= $startDay->format('d M Y').'</li>
          ';
          $startDay->modify('+1 day');
      }
      return $return;
}

我修改了上述更通用的解决方案,以实现您所描述的:

    <?php
function date_interval(DATETIME $startDay = NULL)
{
      if( NULL == $startDay){ 
        return array(); }
      $return = '';
      $today = new DATETIME('now');
      $startMonth = new DateTime('first day of '.$startDay->format('M Y') );
      $firstRun = TRUE;
      while(  $today > $startDay )
      {
          $return .= '<li>From '.$startDay->format('d M Y').' to ';
          if( $firstRun == TRUE ){
            if( (int)$startDay->format('d') > 10 )
              $startMonth->modify('+10 days');
            if( (int)$startDay->format('d') > 20 )  
              $startMonth->modify('+10 days');
            $startDay = $startMonth;
            $firstRun = FALSE;
          }
          $lastOfMonth = new DateTime('last day of '.$startDay->format('M Y') );
          if( $lastOfMonth->diff( $startDay )->format('%a%') > 10 )
            $startDay->modify('+9 days');
          else
            $startDay = $lastOfMonth;
          $return .= $startDay->format('d M Y').'</li>
          ';
          $startDay->modify('+1 day');
      }
      return $return;
}
echo date_interval( date_create_from_format('Y-m-d','2016-01-21') )."'n";
?>

使用DateTime:查看此函数

function date_interval( $start = Null )
{
    if( !$start ) return array();
    $cur    = new DateTime( sprintf( '%s-%02d', $start->format('Y-m'), [1,11,21,21][ floor(($start->format('j')-1)/10) ] ) );
    $end    = new DateTime();
    $retval = [];
    while( $cur <= $end )
    {
        $key = $cur->format( 'Y-m-d~' );
        $val = $cur->format( 'd M Y - ' );
        if( $cur->format( 'j' ) > 20 ) $cur->modify( 'last day of this month' );
        else                           $cur->modify( '+ 9 days' );
        $retval[ $key.$cur->format( 'Y-m-d' ) ] = $val.$cur->format( 'd M Y' );
        $cur->modify( '+ 1 days' );
    }
    return $retval;
}

这样称呼它:

$startDate = '14/01/2016';
$array = date_interval( DateTime::createFromFormat( 'd/m/Y', $startDate ) );
print_r( $array );

根据您的键/值模式,得到的数组是:

Array
(
    [2016-01-11~2016-01-20] => 11 Jan 2016 - 20 Jan 2016
    [2016-01-21~2016-01-31] => 21 Jan 2016 - 31 Jan 2016
    [2016-02-01~2016-02-10] => 01 Feb 2016 - 10 Feb 2016
    [2016-02-11~2016-02-20] => 11 Feb 2016 - 20 Feb 2016
    [2016-02-21~2016-02-29] => 21 Feb 2016 - 29 Feb 2016
    [2016-03-01~2016-03-10] => 01 Mar 2016 - 10 Mar 2016
    [2016-03-11~2016-03-20] => 11 Mar 2016 - 20 Mar 2016
    [2016-03-21~2016-03-31] => 21 Mar 2016 - 31 Mar 2016
    [2016-04-01~2016-04-10] => 01 Apr 2016 - 10 Apr 2016
    [2016-04-11~2016-04-20] => 11 Apr 2016 - 20 Apr 2016
    [2016-04-21~2016-04-30] => 21 Apr 2016 - 30 Apr 2016
)

我们只对一个日期($cur)进行操作,该日期最初是根据传递的参数创建的;我们使用数组[1,11,21,21]设置月份的日期,并通过原始日期的四舍五入除以10来选择键(在您的示例中,(14-1)/10=1.3,四舍五五入为1,即[1,11,21,21]数组中的11)。这是解决第31天异常的快速方法。

然后我们执行一个循环,直到$cur日期大于今天日期:我们创建键和值的起始部分,我们修改$cur添加它九天或选择上个月的日期,我们创建返回数组的完整键和值。在每个循环结束时,我们将$cur增加1天。