日期时间:将一个月分成 10 天的时间段

datetime: split a month 10-day periods

我发送了一个较早的日期,它 returns 我从较早的日期到今天之间的时间缩短了数十天。

Example with 14/01/2016

我需要的结果完全如下:

这是我的代码:

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 的宠儿 class,它很好地解决了这类问题。 在这里,您将开始日期作为 DATETIME 对象提供给函数,函数返回一堆列表标签。

在循环中,startDay 首先被修改为增加 10 天以进行跳跃,然后增加 1 天以避免重叠。 如果您想要最后一行包含从上一个开始日到今天的(少于十天)时间段,您可以添加类似以下内容:

$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 );

根据您的 keys/values 架构,结果数组为:

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,即 [ 中的 11 =15=]数组)。这是解决 31 天 异常的快速方法。

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