Исключить диапазоны даты / времени из массива диапазонов даты / времени с перекрытием

Надеюсь, у тебя все хорошо !!

Я как бы застрял с этим: то, что я делал, работает только тогда, когда нет перекрытия, и в любом случае я не уверен, что это правильный подход.

Поэтому моя текущая реализация — объединять все время (start_time и end_time как разные записи в этом массиве), сортировать их и удалять дубликаты, если таковые имеются.

Затем я зацикливаюсь на этом списке и проверяю для каждого, находятся ли они в пределах $ times, а не в пределах ограничений.

Все те, которые проходят это условие, добавляются в другой список. Затем, наконец, я переберу этот список «2 элемента за раз» и создам окончательный массив временных диапазонов.

коды: https://3v4l.org/2elDs (Laravel, используя Collection и Carbon, поэтому не будет там бегать)

Образец без наложения даты / времени:

$times = [
[
'start_time' => '2017-06-26 00:00:00',
'end_time' => '2017-06-26 05:00:00',
],
[
'start_time' => '2017-06-26 13:00:00',
'end_time' => '2017-06-26 18:00:00',
]
];

$timesToExclude= [
[
'start_time' => '2017-06-26 04:00:00',
'end_time' => '2017-06-26 04:30:00',
],
[
'start_time' => '2017-06-26 07:00:00',
'end_time' => '2017-06-26 10:00:00',
],
[
'start_time' => '2017-06-26 15:00:00',
'end_time' => '2017-06-26 16:00:00',
]
];

Результат к:

    $result = [
[
"start_time" => "2017-06-26 00:00:00",
"end_time"   => "2017-06-26 04:00:00"], [
"start_time" => "2017-06-26 04:30:00",
"end_time"   => "2017-06-26 05:00:00"],
[
"start_time" => "2017-06-26 13:00:00",
"end_time"   => "2017-06-26 15:00:00"],
[
"start_time" => "2017-06-26 16:00:00",
"end_time"   => "2017-06-26 18:00:00"]
]

Образец с перекрытием даты / времени

    $times = [
[
'start_time' => '2017-06-26 00:00:00',
'end_time'   => '2017-06-26 10:00:00',
],
[
'start_time' => '2017-06-26 05:00:00',
'end_time'   => '2017-06-26 20:00:00',
]
];

$timesToExclude= [
[
'start_time' => '2017-06-26 04:00:00',
'end_time'   => '2017-06-26 04:30:00',
],
[
'start_time' => '2017-06-26 07:00:00',
'end_time'   => '2017-06-26 09:00:00',
],
[
'start_time' => '2017-06-26 15:00:00',
'end_time'   => '2017-06-26 16:00:00',
]
];

Должно привести к:

$result = [
[
"start_time" => "2017-06-26 00:00:00",
"end_time"   => "2017-06-26 04:00:00"], [
"start_time" => "2017-06-26 04:30:00",
"end_time"   => "2017-06-26 05:00:00"],
[
"start_time" => "2017-06-26 05:00:00",
"end_time"   => "2017-06-26 07:00:00"],
[
"start_time" => "2017-06-26 09:00:00",
"end_time"   => "2017-06-26 10:00:00"],
[
"start_time" => "2017-06-26 10:00:00",
"end_time"   => "2017-06-26 15:00:00"],
[
"start_time" => "2017-06-26 16:00:00",
"end_time"   => "2017-06-26 20:00:00"]
]

Кто-нибудь знает правильный алгоритм / псевдо, чтобы иметь дело с этим?

0

Решение

Создать общий список пар {time; flag}где флаг time_start, time_end, restriction_start or restriction_end,

Сортировать этот список по времени. В случае связи используйте флаг в качестве вторичного ключа (например, restr_start должен идти после time_end).

Делать $Active=0, $Exclude=0

Пройдите через отсортированный список.

Когда вы встречаете time_start, значение приращения $Active {1}

Когда вы встречаете time_end, уменьшение значения $Active {2}

Когда вы встречаете restriction_start, значение приращения $Exclude {3}

Когда вы встречаете restriction_end, уменьшение значения $Exclude {4}

Открытый выходной интервал в следующих случаях:
{1}: $Active становится 1 и $Exclude = 0
{4}: $Exclude becomes 0 а также $Active ненулевой

Закройте выходной интервал в следующих случаях:
{2} $Active становится 0 и $Exclude = 0
{3} $Exclude becomes 1 а также $Active ненулевой

пример: (не знаю точный синтаксис php для сложных условий)

 case $TimeStart:
$active = $active + 1;
if ($active=1) and ($exclude=0)
$range['start_time'] = $mergedTime['time'];
break;
....
case $RestrictionEnd:
$exclude = $exclude - 1;
if ($exclude=0) and ($active > 0)
$range['start_time'] = $mergedTime['time'];
break;
0

Другие решения

функция excludeOverlaping ($ disonabilities, $ plages) {

    if(count($disponibilities) == 0)
return $disponibilities;
if(count($plages) == 0)
return $disponibilities;

usort($disponibilities, function($a, $b)
{
return strtotime($a->startDate) - strtotime($b->startDate);
});
usort($plages, function($a, $b)
{
return strtotime($a->startDate) - strtotime($b->startDate);
});

for($i = 0; $i < count($disponibilities); $i++){
for($j=0;$j<count($plages);$j++){
$dispo = $disponibilities[$i];
if(isset($dispo->exclude)){
break;
}
$plage = $plages[$j];
if(strtotime($dispo->startDate)>=strtotime($plage->startDate) && strtotime($dispo->endDate)<=strtotime($plage->endDate)){
$disponibilities[$i]->exclude = true;

}else if( strtotime($dispo->startDate)<strtotime($plage->startDate) && strtotime($dispo->endDate) <= strtotime($plage->endDate) && strtotime($dispo->endDate) > strtotime($plage->startDate)){
$disponibilities[$i]->endDate = $plage->startDate;
}else if( strtotime($dispo->startDate)>=strtotime($plage->startDate)  && strtotime($dispo->startDate)<=strtotime($plage->endDate) && strtotime($dispo->endDate) > strtotime($plage->endDate)){
$disponibilities[$i]->startDate = $plage->endDate;
}else if( strtotime($dispo->startDate)<strtotime($plage->startDate) &&  strtotime($dispo->endDate) > strtotime($plage->endDate) ){
echo "[[[4]]]\n";
$tmp = new stdClass();
$tmp->startDate = $dispo->startDate;
$tmp->endDate = $plage->startDate;
$tmp2 = new stdClass();
$tmp2->startDate = $plage->endDate;
$tmp2->endDate = $dispo->endDate;
$disponibilities[$i]->exclude = true;
array_push($disponibilities,$tmp);
array_push($disponibilities,$tmp2);

}
}
}
for($i=0;$i<count($disponibilities);$i++){
if(isset($disponibilities[$i]->exclude)){
array_splice($disponibilities,$i,1);
$i--;
}
}
var_dump($disponibilities);

}

$times = array();
$restrictions = array();
$obj = new stdClass();
$obj->startDate = '2017-06-26 00:00:00';
$obj->endDate =  '2017-06-26 07:00:00';
array_push($times,$obj);
$obj = new stdClass();
$obj->startDate = '2017-06-26 00:00:00';
$obj->endDate = '2017-06-26 24:00:00';
array_push($times,$obj);$obj = new stdClass();
$obj->startDate =  '2017-06-26 04:00:00';
$obj->endDate = '2017-06-26 06:00:00';
array_push($restrictions,$obj);$obj = new stdClass();
$obj->startDate = '2017-06-26 00:00:00' ;
$obj->endDate = '2017-06-26 01:00:00';
array_push($restrictions,$obj);excludeOverlaping($times,$restrictions);
0

По вопросам рекламы [email protected]