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

时间:2017-02-24 11:10:10

标签: php arrays date

我在php中有以下日期数组:

ReadConsoleInput

有没有办法找到数组中包含的连续日期?

例如,对于上面的数组,预期结果将是:

2017-02-22至2017-02-23

2017-04-03到2017-04-06。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

执行此任务的方法有很多种。有些比其他人更难阅读。我列出了一些。我建议使用第一种方法来提高效率,也许是第三种方法,以便于输出修改。

我修改了$dates数组中的示例数据,以显示它适应月份更改和独立日期。

以下所有方法都假定日期已按升序排序。如果没有,那么sort()将适用于Y-m-d格式的日期;否则usort()将是必要的。

我的方法将采用如下的一系列日期:

$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'
];

并输出:

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',
)

方法#1:单个Foreach循环(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);

方法#2:嵌套循环(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);

方法#3:两个Foreach循环(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);

或者从方法3中的$grouped数组中,您可以简单地改变输出结构以包含"范围字符串"作为具有子单元格的键,使用以下各项将日期作为元素:

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

替代产出:

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',
  ),
)