Поиск промежутков времени исключающие интервалы перерывов в работе

Имеется массив, в котором 'source' это начало и конец рабочего промежутка времени. И 'intervals' интервалы с перерывами на отдых.

[
    'source' => [
        'start' => '8:00'
        'end' => '12:00'
    ]
    'intervals' => [
        0 => [
            'from' => '08:30'
            'to' => '08:45'
        ]
        1 => [
            'from' => '09:30'
            'to' => '09:45'
        ]
        2 => [
            'from' => '11:00'
            'to' => '11:15'
        ]
    ]
]

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

Прошу помощи с алгоритмом, выше упомянутый массив получил своим алгоритмом, а тут не понимаю даже с чего начать.

Попытался применить связный список blister/linkedlist.

    $i = 0;
    /** @var LLNode $item */
    foreach ($list as $item){

        $i++;
        if ($i == 1){
            $result['found'][] = "{$start} - {$item->value->from}";
        }

        if ($item->prev){
            $result['found'][] = "{$item->prev->value->to} - {$item->value->from}";
        }

        if ($i === $list->length){
            $result['found'][] = "{$list->tail->value->to} - {$end}";
        }
    }

На выходе получаю:

[
    'source' => [
        'start' => '8:00'
        'end' => '12:00'
    ]
    'intervals' => [
        0 => '08:30 - 08:45'
        1 => '09:30 - 09:45'
        2 => '11:00 - 11:15'
    ]
    'found' => [
        0 => '8:00 - 08:30'
        1 => '09:45 - 11:00'
        2 => '11:15 - 12:00'
    ]
]

Не могу понять почему один интервал пропущен... Понимаю что в результате отрезков времени должно быть больше чем количество интервалов...


Ответы (1 шт):

Автор решения: MBo

Если у вас нет пересечений и всё отсортировано по времени, то достаточно следующего:

Записать в начало первого рабочего интервала source start

Пройти по массиву перерывов. from заканчивает текущий рабочий интервал, записываете его в выходной массив, to начинает новый рабочий интервал.

В конце завершаете последний рабочий интервал source end

На PHP не пойму, как ваш массив использовать в онлайн-компиляторах, так что пример на Python:

src = ['8:00', '12:00']
intervals = [['08:30','08:45'],['09:30','09:45'],['11:00','11:15']]
res = []
begin = src[0]
for item in intervals:
    res.append([begin, item[0]])
    begin = item[1]
res.append([begin, src[1]])
print(res)

[['8:00', '08:30'], ['08:45', '09:30'], ['09:45', '11:00'], ['11:15', '12:00']]
→ Ссылка