检查集合中的连续日期并返回范围

Ker*_*rri 6 php date

我有日期Ymd格式的数组,可以是相隔一天的十个设定日期的任意组合.

这是全套:

2011-01-01,2011-01-02,2011-01-03,2011-01-04,2011-01-05,2011-01-06,2011-01-07,2011-01-08,2011- 01-09,2011-01-10

从该集创建的数组可以是日期的任意组合 - 所有数组,其中一个,一些连续,全部连续等.

我现在把它们打印得很漂亮.例如,这是一个可能的结果:

2011-01-02

2011-01-03

2011-01-04

2011-01-08

(实际打印的内容更像是"1月2日星期五......",但我们会坚持使用简单的日期字符串)

我想压缩它,以便如果连续三天或更多天,那些就成了一个范围,例如上面的例子会变成:

2011-01-02至2011-01-04

2011-01-08

最终会成为:

1月2日星期日 - 1月4日星期二

1月8日星期六

有没有办法循环并检查时差,创建范围的开始时间和结束时间,然后收集落后者?

Dar*_*ght 13

快速回答的一点很抱歉没有实现,但假设您使用5.3并且按时间顺序排序日期,您可以将每个日期转换为DateTime对象(如果它们尚未),然后使用DateTime::diff()生成迭代数组一个DateInterval对象,您可以用它来比较迭代中的当前日期和最后一个日期.你可以组你连续日期为子阵列和使用shift(),并pop()获得第一天和最后一天在该子阵列.

编辑

我想到了这一点.接下来是非常粗略和准备好的实现,但它应该工作:

// assuming a chronologically
// ordered array of DateTime objects 

$dates = array(
    new DateTime('2010-12-30'), 
    new DateTime('2011-01-01'), 
    new DateTime('2011-01-02'), 
    new DateTime('2011-01-03'), 
    new DateTime('2011-01-06'), 
    new DateTime('2011-01-07'), 
    new DateTime('2011-01-10'),
);

// process the array

$lastDate = null;
$ranges = array();
$currentRange = array();

foreach ($dates as $date) {    

    if (null === $lastDate) {
        $currentRange[] = $date;
    } else {

        // get the DateInterval object
        $interval = $date->diff($lastDate);

        // DateInterval has properties for 
        // days, weeks. months etc. You should 
        // implement some more robust conditions here to 
        // make sure all you're not getting false matches
        // for diffs like a month and a day, a year and 
        // a day and so on...

        if ($interval->days === 1) {
            // add this date to the current range
            $currentRange[] = $date;    
        } else {
            // store the old range and start anew
            $ranges[] = $currentRange;
            $currentRange = array($date);
        }
    }

    // end of iteration... 
    // this date is now the last date     
    $lastDate = $date;
}

// messy... 
$ranges[] = $currentRange;

// print dates

foreach ($ranges as $range) {

    // there'll always be one array element, so 
    // shift that off and create a string from the date object 
    $startDate = array_shift($range);
    $str = sprintf('%s', $startDate->format('D j M'));

    // if there are still elements in $range
    // then this is a range. pop off the last 
    // element, do the same as above and concatenate
    if (count($range)) {
        $endDate = array_pop($range);
        $str .= sprintf(' to %s', $endDate->format('D j M'));
    }

    echo "<p>$str</p>";
}
Run Code Online (Sandbox Code Playgroud)

输出:

Thu 30 Dec
Sat 1 Jan to Mon 3 Jan
Thu 6 Jan to Fri 7 Jan
Mon 10 Jan
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!几周前我已经更新到5.3,专门用于所有新的漂亮的DateTime能力.我会研究并给出一个镜头并报告回来. (2认同)