[
0 => [
'start' => '01.01.2017',
'end' => '06.01.2017'
],
1 => [
'start' => '21.01.2017',
'end' => '30.01.2017'
],
2 => [
'start' => '10.01.2017',
'end' => '20.01.2017'
],
3 => [
'start' => '05.01.2017',
'end' => '16.01.2017'
],
4 => [
'start' => '15.01.2017',
'end' => '20.01.2017'
],
]
[
0 => [
// для будущего объединения в один период
0 => [
'start' => '01.01.2017',
'end' => '06.01.2017'
],
1 => [
'start' => '10.01.2017',
'end' => '20.01.2017'
],
2 => [
'start' => '05.01.2017',
'end' => '16.01.2017'
],
3 => [
'start' => '15.01.2017',
'end' => '20.01.2017'
]
]
// период который не пересекается
1 => [
0 => [
'start' => '21.01.2017',
'end' => '30.01.2017'
]
]
]
$intervals =
[['start' => '2017-01-01', 'end' => '2017-01-06'],
['start' => '2017-01-21', 'end' => '2017-01-30'],
['start' => '2017-01-10', 'end' => '2017-01-20'],
['start' => '2017-01-05', 'end' => '2017-01-16'],
['start' => '2017-01-15', 'end' => '2017-01-20']];
function is_intersect($int1, $int2) {
return ($int2['end'] >= $int1['start'] && $int1['end'] >= $int2['start']);
}
function combine($int1, $int2) {
if (!isset($int1['subintervals'])) {
$int1['subintervals'] = [$int1];
}
if (!isset($int2['subintervals'])) {
$int2['subintervals'] = [$int2];
}
return array('start' => min($int1['start'], $int2['start']), 'end' => max($int1['end'], $int2['end']),
'subintervals' => array_merge($int1['subintervals'], $int2['subintervals']));
}
function combine_intersected($intervals) {
$result = [];
$noIntersects = true;
foreach ($intervals as $int1) {
$combined = false;
foreach ($result as &$int2) {
if (is_intersect($int1, $int2)) {
$int2 = combine($int1, $int2);
$noIntersects = false;
$combined = true;
break;
}
}
if (!$combined) {
$result[] = $int1;
}
}
if ($noIntersects) {
return false;
}
return $result;
}
while ($ints = combine_intersected($intervals)) {
$intervals = $ints;
}
Array (
[0] => Array (
[start] => 2017-01-01
[end] => 2017-01-20
[subintervals] => Array (
[0] => Array (
[start] => 2017-01-10
[end] => 2017-01-20
)
[1] => Array (
[start] => 2017-01-15
[end] => 2017-01-20
)
[2] => Array (
[start] => 2017-01-05
[end] => 2017-01-16
)
[3] => Array (
[start] => 2017-01-01
[end] => 2017-01-06
)
)
)
[1] => Array (
[start] => 2017-01-21
[end] => 2017-01-30
)
)
отсортировать массив по start
текКонец := −∞ // или, например, ⌀ или 0000-01-01
текИндекс := −1
для v : массив
если v.start > текКонец
текИндекс += 1
результат[текИндекс].приклеить(v)
текКонец := макс(текКонец, v.end)
отсортировать массив по start
текКонец := −∞ // или, например, ⌀ или 0000-01-01
текИндекс := −1
для v : массив
если v.start > текКонец
текИндекс += 1
результат[текИндекс] := v
иначе
результат[текИндекс] := объединить(результат[текИндекс], v)
текКонец := макс(текКонец, v.end)
function isOverlapped($dateRange1, $dateRange2)
{
return (
$dateRange1['start'] >= $dateRange2['start']
&& $dateRange1['start'] <= $dateRange2['end']
||
$dateRange1['end'] >= $dateRange2['start']
&& $dateRange1['end'] <= $dateRange2['end']
);
}