Check consecutive dates in a set and return as a range

I have an array of Ymd dates, which can be any combination of ten given dates, divided by one day.

eg. Here is the complete set:

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

Arrays created from this set can be any combination of dates - all of them, one of them, several consecutive, all in a row, etc.

I am currently printing them since they are returning. For example, here is a possible result:

2011-01-02

2011-01-03

2011-01-04

2011-01-08

(what is actually printed is more like "Friday, January 2 ...", but we will stick to a simple date string)

I would like to condense it so that if there are three or more consecutive days, they become a range, for example, the above example will become the following:

2011-01-02 - 2011-01-04

2011-01-08

which will eventually become the following:

Sunday, January 2 - Tuesday, January 4

Saturday January 8th

Is there a way to scroll and check the time difference, create a start time and an end time for the range (s), and then collect the apostates?

+6
source share
1 answer

A bit of a quick answer, so sorry for the lack of implementation, but assuming you are using 5.3, and the dates are ordered in chronological order, you can convert each date to a DateTime object (if they haven't already), and then iterate over the array using DateTime::diff() to generate a DateInterval object that you could use to compare the current date in iteration with the last. You can group your consecutive dates into sub-matrices and use shift() and pop() to get the first and last days in this auxiliary array.

EDIT

I thought about that. The following is a rather crude and ready-made implementation, but it should work:

 // 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>"; } 

Outputs:

 Thu 30 Dec Sat 1 Jan to Mon 3 Jan Thu 6 Jan to Fri 7 Jan Mon 10 Jan 
+10
source

Source: https://habr.com/ru/post/903542/


All Articles