I have an array of dates as input in the form "YYYY-mm-dd"=>category_id.0 (category_id counting from 0).
$days =array (
'2014-10-15' => 49,
'2014-10-16' => 49,
'2014-10-17' => 49,
'2014-10-18' => 0,
'2014-10-19' => 0,
'2014-10-20' => 0,
'2014-10-21' => 0,
'2014-10-22' => 0,
'2014-10-23' => 0,
'2014-10-24' => 0,
'2014-10-25' => 0,
'2014-10-26' => 0,
'2014-10-27' => 0,
'2014-10-28' => 0,
'2014-10-29' => 0,
'2014-10-30' => 0,
'2014-10-31' => 0,
'2014-11-01' => 0,
'2014-11-02' => 0,
/* MISSING 2014-11-03 */
'2014-11-04' => 0,
'2014-11-05' => 0,
'2014-11-06' => 0,
'2014-11-07' => 0,
'2014-11-08' => 0,
'2014-11-09' => 0,
'2014-11-10' => 0,
'2014-11-11' => 0,
'2014-11-12' => 0,
'2014-11-13' => 0,
'2014-11-14' => 0,
'2014-11-15' => 0,
'2014-11-16' => 0,
'2014-11-17' => 0,
'2014-11-18' => 0,
'2014-11-19' => 0,
'2014-11-20' => 0,
'2014-11-21' => 0,
'2014-11-22' => 0,
'2014-11-23' => 0,
'2014-11-24' => 0,
'2014-11-25' => 0,
'2014-11-26' => 0,
'2014-11-27' => 0,
'2014-11-28' => 0,
'2014-11-29' => 0,
'2014-11-30' => 0,
'2014-12-01' => 0,
'2014-12-02' => 0,
'2014-12-03' => 0,
'2014-12-04' => 0,
'2014-12-05' => 0,
'2014-12-06' => 0,
'2014-12-07' => 0,
'2014-12-08' => 0,
'2014-12-09' => 0,
'2014-12-10' => 0,
'2014-12-11' => 0,
'2014-12-12' => 0,
'2014-12-13' => 0,
'2014-12-14' => 0,
'2014-12-15' => 0,
'2014-12-16' => 0,
'2014-12-17' => 0,
'2014-12-18' => 0,
'2014-12-19' => 0,
'2014-12-20' => 0,
'2014-12-21' => 0,
'2014-12-22' => 1,
'2014-12-23' => 3,
'2014-12-24' => 3,
'2014-12-25' => 3,
'2014-12-26' => 3,
'2014-12-27' => 3,
'2014-12-28' => 3,
'2014-12-29' => 50,
'2014-12-30' => 50,
'2014-12-31' => 50,
'2015-12-24' => 2,
'2015-12-25' => 2,
);
I want to build an array of range of dates grouped by category_id.
For example, category_id 49
has 3 consecutive days from 15 to 17, so the first range should be:
array('2014-10-15',2014-10-17',49)
.
the category_id 0
start from 2014-10-18
and end to 2014-12-21
HOWEVER due the missing day 2014-11-03
I must split the range in two parts:
array('2014-10-18','2014-11-02',0)
and array('2014-11-04','2014-12-21',0)
The final output is an array of ranges like this:
Array
(
[0] => Array
(
[0] => 2014-10-15
[1] => 2014-10-17
[2] => 49
)
[1] => Array
(
[0] => 2014-10-18
[1] => 2014-11-02
[2] => 0
)
[3] => Array
(
[0] => 2014-11-04
[1] => 2014-12-21
[2] => 0
)
[4] => Array
(
[0] => 2014-12-22
[1] => 2014-12-22
[2] => 1
)
[5] => Array
(
[0] => 2014-12-23
[1] => 2014-12-28
[2] => 3
)
[6] => Array
(
[0] => 2014-12-29
[1] => 2014-12-31
[2] => 50
)
[8] => Array
(
[0] => 2015-12-24
[1] => 2015-12-25
[2] => 2
)
)
Due the possibility of to have holes in days array, I tought that the best way is to get the first day (in temporary order), then add a day for each cycle. Checking the values, I build the range array.
function get_range_from_days($days) {
// check if input is empty
if(count($days) == 0) return array();
// output to fill
$ranges = array();
// order dates keys in order to have the first date in temporary order
ksort($days);
// get first and last day
$firstday = key($days);
end($days);
$lastday = key($days);
// get the type of first day (actually the current day where we looks)
$current_type = $days[$firstday];
// using datetime object for easy step of 1 day
$datetime = new \DateTime($firstday);
$datetime->setTime(9,0,0); // avoid time problems at midnight (it's needed?)
// do the first step outside the while
$datetime->add(new DateInterval('P1D'));
// store old value of day
$oldday = $firstday;
// build the first range
$ranges[] = array($firstday,null,$current_type);
while(($day = $datetime->format('Y-m-d')) <= $lastday) {
// if there are holes, fill it with null
if(!isset($days[$day])) {
$days[$day] = null;
}
// check if type has changed (=>need new range)
if(($days[$day] !== $current_type)) {
$ranges[count($ranges)-1][1] = $oldday;
$ranges[] = array($day,null,$days[$day]);
$current_type = $days[$day];
}
// store previous day
$oldday = $day;
// next day
$datetime->add(new DateInterval('P1D'));
}
// complete the last range
$ranges[count($ranges)-1][1] = $lastday;
// remove range of holes
foreach($ranges as $k=>$range) {
if(is_null($range[2])) {
unset($ranges[$k]);
}
}
return $ranges;
}
Any improvements? This looks not so nice.