Search code examples
phplaraveldatetimestampphp-carbon

Laravel Carbon - get interval slots with buffer duration


I need to get time slots interval with buffer time between slots and without invalid time intervals.

I have this variables:

$serviceDuration = 40; // 40 minutes slots duration
$serviceBufferDuration = 5; // 5 minutes buffer time between slots
$invalidTimeIntervals = ['10:40 - 11:00', '12:10 - 12:30']; // invalid time intervals
$startWorking = "09:00";
$endWorking =  "13:30";

And I want a response like this:

[
   "09:00 - 09:40",
   "09:45 - 10:25",
   "11:00 - 11:40", // this starts at 11:00 because has invalid time interval from 10:40 to 11:00
   "11:45 - 11:55",
   "12:30 - 13:10" // this starts at 12:30 because has invalid time interval from 12:10 to 12:30
];

Time slots example

Thank you!


Solution

  • I'm just trying to get your response but it may be short.

    use Carbon\Carbon;
    
    $start_time = Carbon::parse($startWorking);
    $end_time = Carbon::parse($endWorking);
    
    $times = [];
    
    $loop = true;
    while($loop) {
    
        foreach ($invalidTimeIntervals as $interval) {
            $invalidTime = explode(' - ', $interval);
            $invalidTime[0] = Carbon::parse($invalidTime[0]);
            $invalidTime[1] = Carbon::parse($invalidTime[1]);
    
            $slot_time = $start_time->copy()->addMinutes($serviceDuration);
    
            if ($start_time->lessThan($invalidTime[0])
                && ( $slot_time->greaterThan($invalidTime[1])
                    || $slot_time->between($invalidTime[0], $invalidTime[1])
                )
            ) {
                $start_time = Carbon::parse($invalidTime[1]);
            }
        }
    
        $slot_time = $start_time->copy()->addMinutes($serviceDuration);
    
        if ($slot_time->lessThanOrEqualTo($end_time)) {
            $times[] =  $start_time->format('H:i').' - '. $slot_time->format('H:i');
            $start_time = $slot_time->addMinutes($serviceBufferDuration);
            continue;
        }
    
        $loop = false;
    }
    
    return $times;
    

    Output

    [
        "09:00 - 09:40",
        "09:45 - 10:25",
        "11:00 - 11:40",
        "12:30 - 13:10"
    ]