Set one:
Set two:
Usage : $output = mergeRanges($input);
This method is originally designed to merge any kind on numeric ranges, timestamps included and supports any kind of overlaps. It takes an array of objects in input, containing "from" and "to" keys which is customizable.
/**
* @param $ranges
* @param string $keyFrom
* @param string $keyTo
*
* @return array
*/
function mergeRanges($ranges, $keyFrom = 'from', $keyTo = 'to')
{
// Split from / to values.
$arrayFrom = [];
$arrayTo = [];
foreach ($ranges as $date)
{
$arrayFrom[] = $date->$keyFrom;
$arrayTo[] = $date->$keyTo;
}
// Sort ASC.
natsort($arrayFrom);
natsort($arrayTo);
$ranges = [];
// Iterate over start dates.
foreach ($arrayFrom as $indexFrom => $from)
{
// Get previous entry.
$previousEntry = end($ranges);
// Find associated default "to" value to "from" one.
$to = $arrayTo[$indexFrom];
// If we have a previous entry and "to" is greater than
// current "from" value.
if (isset($previousEntry->to) && $from < $previousEntry->to + 1)
{
// Do nothing if this range is completely covered
// by the previous one.
if ($to > $previousEntry->to)
{
// We just change te "to" value of previous range,
// so we don't create a new entry.
$previousEntry->to = $to;
}
}
else
{
// Create a new range entry.
$ranges[] = (object) [
$keyFrom => $from,
$keyTo => $to,
];
}
}
return $ranges;
}
Example :
$input = [
// One day.
(object) [
'title' => 'One day.',
'from' => 1560816000,
'to' => 1560902399,
],
// Same day, inner period
(object) [
'title' => 'Same day, inner period',
'from' => 1560816000 + 1000,
'to' => 1560902399 - 1000,
],
// Just before midnight
(object) [
'title' => 'Just before midnight',
'from' => 1560816000 - 1000,
'to' => 1560816000 + 1000,
],
// Just after midnight
(object) [
'title' => 'Just after midnight',
'from' => 1560902399 - 1000,
'to' => 1560902399 + 1000,
],
// Other period before
(object) [
'title' => 'Other period before',
'from' => 1560902399 - 100000,
'to' => 1560902399 - 100000 + 5000,
],
// Other period after
(object) [
'title' => 'Other period after',
'from' => 1560816000 + 100000,
'to' => 1560902399 + 100000 + 5000,
],
];
Result :
Array
(
[0] => Array
(
[from] => 2019-06-17 22:13:19
[to] => 2019-06-17 23:36:39
)
[1] => Array
(
[from] => 2019-06-18 01:43:20
[to] => 2019-06-19 02:16:39
)
[2] => Array
(
[from] => 2019-06-19 05:46:40
[to] => 2019-06-20 07:09:59
)
)