У меня есть массивы дат формата 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
(то, что на самом деле напечатано, больше похоже на «Пятница, 2 января …», но мы будем придерживаться простой строки даты)
Я хотел бы сконденсировать его так, чтобы, если есть три или более последовательных дня, они становятся диапазоном, например, приведенный выше пример стал бы следующим:
2011-01-02 – 2011-01-04
2011-01-08
который в конечном итоге станет:
Воскресенье, 2 января – вторник, 4 января
Суббота 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