我有 Y-m-d 格式的日期数组,可以是相隔一天的十个设定日期的任意组合。
例如这是可能的全套:
[
'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',
]
(实际打印的内容更像是“Friday, Jan. 2…”,但我们将坚持使用简单的日期字符串)
我想将其压缩,以便如果有连续三天或更多天,这些就成为一个范围,例如上面的示例将变为:
[
'2011-01-02 to 2011-01-04',
'2011-01-08',
]
最终会变成:
[
'Sunday, Jan. 2 - Tuesday, Jan. 4',
'Saturday Jan. 8',
]
有没有办法循环检查时差,创建范围的开始时间和结束时间,然后收集掉队者?
有点快速回答,对于缺乏实现感到抱歉,但假设您使用的是 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>";
}
输出:
Thu 30 Dec
Sat 1 Jan to Mon 3 Jan
Thu 6 Jan to Fri 7 Jan
Mon 10 Jan