dourunlao1642 2017-02-24 11:10
浏览 35
已采纳

在php中查找序列化日期的连续时间段

I have the following array with dates in php:

Array ( 
  [0] => '2017-02-22'
  [1] => '2017-02-23'
  [2] => '2017-04-03'
  [3] => '2017-04-04'
  [4] => '2017-04-05'
  [5] => '2017-04-06'
)

Is there a way to find the continuous date periods included within the array?

For example for the above array the expected result would be:

2017-02-22 to 2017-02-23

and

2017-04-03 to 2017-04-06.

Thanks for your help!

  • 写回答

1条回答 默认 最新

  • drslez4322 2017-03-02 07:16
    关注

    There will be many ways to perform this task. Some that are harder to read than others. I'll list a few. I recommend using the first method for efficiency, and perhaps the third method for easy of output modification.

    I have modified the sample data in the $dates array to show that it accommodates month changes, and stand-alone dates.

    All of the following methods will assume that the dates are already sorted in ascending ordered. If not, then sort() will work on Y-m-d formatted dates; otherwise usort() will be neccessary.

    My methods will take an array of dates like this:

    $dates=[
      '2017-02-28',
      '2017-03-01',
      '2017-04-03',
      '2017-04-04',
      '2017-04-06',
      '2017-04-08',
      '2017-04-09',
      '2017-04-10'
    ];
    

    And output this:

    array (
      0 => '2017-02-28 to 2017-03-01',
      1 => '2017-04-03 to 2017-04-04',
      2 => '2017-04-06 to 2017-04-06',
      3 => '2017-04-08 to 2017-04-10',
    )
    

    Method #1: Single Foreach Loop (Demo)

    foreach($dates as $date){
        if(!isset($start_date)){
            $start_date=$date;  // temporarily store new start date
        }elseif($date==date("Y-m-d",strtotime("$start_date +1 day")) || (isset($end_date) && $date==date("Y-m-d",strtotime("$end_date +1 day")))){
            $end_date=$date;    // temporarily store new or overwrite existing end date
        }else{
            $result[]="$start_date to ".(!isset($end_date)?$start_date:$end_date);  // current date is not in group, move temporary dates to result array
            $start_date=$date;  // overwrite previous start date
            unset($end_date);  // destroy previous end date
        }
    }
    $result[]="$start_date to ".(!isset($end_date)?$start_date:$end_date);  // move temporary dates to result array
    var_export($result);
    

    Method #2: Nested While Loops (Demo)

    $copy=$dates;  // make a copy in case $dates is to be used again later
    while($copy){  // iterate until the array is empty
        while(!isset($range) || current($copy)==date("Y-m-d",strtotime(substr($range,-10)." +1 day"))){  // iterate while date is new or consecutive
            $range=(!isset($range)?'':substr($range,0,10).' to ').array_shift($copy);  // temporarily store / overwrite the range data
        }
        $result[]=(strlen($range)==10?"$range to $range":$range);  // permanently store range data
        unset($range);  // destroy range string, for next iteration
    }
    var_export($result);
    

    Method #3: Two Foreach Loops (Demo)

    foreach($dates as $date){
        if(!isset($grouped)){  // first group
            $i=0;  // first group, index is zero
        }elseif($date!=date("Y-m-d",strtotime("$date_checker +1 day"))){  // if non-consecutive
            ++$i;  // next group, index is incremented
        }
        $grouped[$i][]=$date_checker=$date;  // store date as temporary date checker and into appropriate group
    }
    
    foreach($grouped as $group){
        $result[]=current($group)." to ".end($group);
    }
    var_export($result);
    

    Or from the $grouped array in Method 3, you could simply alter the output structure to contain "range strings" as keys with subarrays holding the individual dates as elements using this:

    foreach($grouped as $group){
        $result[current($group)." to ".end($group)]=$group;
    }
    

    Alternative Output:

    array (
      '2017-02-28 to 2017-03-01' => 
      array (
        0 => '2017-02-28',
        1 => '2017-03-01',
      ),
      '2017-04-03 to 2017-04-04' => 
      array (
        0 => '2017-04-03',
        1 => '2017-04-04',
      ),
      '2017-04-06 to 2017-04-06' => 
      array (
        0 => '2017-04-06',
      ),
      '2017-04-08 to 2017-04-10' => 
      array (
        0 => '2017-04-08',
        1 => '2017-04-09',
        2 => '2017-04-10',
      ),
    )
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?