How to check collision/overlapping of time periods

Viewed 146

I want to create a function that will check if there would be any conflict merging array $blocks into array $schedule:

$schedule = [
   'monday' => ['11:00-14:00'],
   'tuesday' => ['10:30-12:00', '14:30-17:30'],
   ...,
];

I would like the function to accept array $blocks and return bool. So let's say I have this $blocks:

$blocks = [
   'monday' => ['8:00-10:00', '15:00-16:00'],
   'tuesday' => ['12:00-13:00']
]

In this case, the function would return true since there is no conflict in merging $blocks into $schedule.

However, as soon as the function detects any conflict it should return false. For example:

$blocks = [
   'monday' => ['8:00-10:00', '15:00-16:00'],
   'tuesday' => ['11:00-12:30'],
   'wednesday', => [...],
   ...,
]

So there's no need for $blocks to be iterated further. Since there is already a conflict between $blocks['tuesday'][0] and $schedule['tuesday'][0].

I need help on how to check both time period of string if it collides/overlaps. Any help would be much appreciated. :)

1 Answers

For every weekday in $blocks, iterate through its times and convert the start and end time into a number which can be compared. For each of those pairs, iterate through every matching $schedule weekday pair of times and compare them to see if they overlap:

<?php

$schedule = [
   'monday' => ['11:00-14:00'],
   'tuesday' => ['10:30-12:00', '14:30-17:30'],
];

$blocks = [
   'monday' => ['8:00-10:00', '15:00-16:00'],
   'tuesday' => ['11:00-12:00']
];

function check_blocks( $schedule, $blocks ) {
    foreach ( $blocks as $weekday => $block_times ) {
        foreach ( $block_times as $block_t ) {
            list( $block_t_start, $block_t_end ) = explode( '-', preg_replace( '/:/', '.', $block_t ) ); // e.g. 14.30, 17.30

            foreach ( $schedule[$weekday] as $schedule_t ) {
                list( $schedule_t_start, $schedule_t_end ) = explode( '-', preg_replace( '/:/', '.', $schedule_t ) ); // e.g. 14.30, 17.30

                if (
                    // Schedule time starts between block time start and end
                    $schedule_t_start >= $block_t_start && $schedule_t_end <= $block_t_end
                        ||
                    // Schedule time starts before block time and ends after block end (i.e. completely overlaps block time)
                    $schedule_t_start <= $block_t_start && $schedule_t_end >= $block_t_end
                        ||
                    // Block time starts or ends between schedule time start and end
                    $block_t_start >= $schedule_t_start && $block_t_end <= $schedule_t_end
                        ||
                    // Block time starts before schedule time start and ends after schedule time end (i.e. completely overlaps schedule time)
                    $block_t_start <= $schedule_t_start && $block_t_end >= $schedule_t_end
                ) {
                    return TRUE;
                }
            }
        }
    }

    return FALSE;
}

$r = check_blocks( $schedule, $blocks );

var_dump($r); // TRUE
Related