Home > Software engineering >  remove times from special times and show as slot in php
remove times from special times and show as slot in php

Time:07-04

hey i have to creating booking system by php/laravel

i take work times from listings like below

08:00 to 13:00
16:00 to 21:00

i want to remove special hour from times and show as slot to user for example i want to remove 09:30 to 11:00 and 17:00: to 18:00 from the time.

so i want to show this times to user

08:00 to 09:30
11:00 to 13:00
16:00 to 17:00
18:00 to 21:00
$maintimes = [
    [
      'start' => '08:00',
      'end' => '13:00'
    ],
    [
      'start' => '16:00',
      'end' => '21:00'
    ],
];

// times to remove from $startTime and $endTime
$removes => [
    [
      'start' => '09:30',
      'end' => '11:00'
    ],
    [
      'start' => '17:00',
      'end' => '18:00'
    ]
];


// output must be like this
$output = [
    [
      'start' => '08:00',
      'end' => '09:30'
    ],
    [
      'start' => '11:00',
      'end' => '13:00'
    ],
    [
      'start' => '16:00',
      'end' => '17:00'
    ],
    [
      'start' => '18:00',
      'end' => '21:00'
    ],
];



/* 

logic:

Suppose. Working time starts from 08:00 to 13:00. Then from 13:00 to 16:00 it is rest time. And then again from the site 16:00 to 21:00 working time.

Therefore, some people take turns during the periods when it is time to work

 */

i research for this problem but i cant find any solution to fix this

CodePudding user response:

  • Sort the removes array according to end in an ascending manner. Note that no 2 subarrays can have the same end value as it doesn't make sense for the splits.

  • Create valid ranges to be dealt with to include valid start times and end times.

  • Previous one's end time is new ones start time and so on and so forth for the ranges to respect the gaps provided.

  • For splitting, if only 13:00 or 16:00 falls within the range, split them, else use the range as is. If any range's start time is above 16:00, include a new range 16:00-start_time only once to accommodate the gap.

Snippet:

<?php

function getMinutes($t){
    $t = explode(":", $t);
    return intval($t[0]) * 60   intval($t[1]);
}

function getSplits($removes, $startTime, $endTime, $breakStart, $breakEnd){
    if($startTime === $endTime) return [];
    
    usort($removes, function($r1, $r2){
        return getMinutes($r1['end']) <=> getMinutes($r2['end']);
    });
    
    $ranges = [];
    foreach($removes as $r){
        $ranges[] = [$startTime, $r['start']];
        $startTime = $r['end'];
    }
    $ranges[] = [$startTime, $endTime]; // include the last range as well
    
    $breakStartMinutes = getMinutes($breakStart);
    $breakEndMinutes = getMinutes($breakEnd);
    
    $splits = [];
    
    foreach($ranges as $rr){
        $break_split = false;
        
        $startMinutes = getMinutes($rr[0]);
        $endMinutes   = getMinutes($rr[1]);
        
        if($breakStartMinutes > $startMinutes && $breakStartMinutes < $endMinutes){
            $break_split = true;
            $splits[] = [$rr[0], $breakStart];
        }
        
        if($breakEndMinutes > $startMinutes && $breakEndMinutes < $endMinutes){
            $break_split = true;
            $breakEndMinutes = 1441; // since we need to consume this only once
            $splits[] = [$breakEnd, $rr[1]];
        }else if($breakEndMinutes < $startMinutes){
            $splits[] = [$breakEnd, $rr[0]];
            $breakEndMinutes = 1441; // since we need to consume this only once
        }
        
        if($break_split === false){
            $splits[] = $rr;
        }
    }
    
    return $splits;
}

print_r(getSplits($removes, '08:00', '21:00', '13:00', '16:00'));

Online Demo

  • Related