显示时间范围内的可用时段,考虑到已预订的时段

lSt*_*lov 5 php datetime

此脚本会检查某个时间范围内是否有 60 分钟的空档,同时考虑到已预订的空档。它适用于第一个已预订的时段,但不考虑第二个时段。另外,如果我将第一个预订时段更改为 12:10,它也不会检测到它。

基本上,想法是在范围和已预订的时段之间是否有 60 分钟的时段来显示它。

例如,如果我们有一个范围9:00to15:00并且我们有两个预订的时段从11:1014:00,返回可用时段9:00, 10:00 and 12:10

$start_time = '2022-10-21 09:00:00';  //start time as string
$end_time = '2022-10-21 15:00:00';  //end time as string
$booked = ['2022-10-21 12:00:00','2022-10-21 13:00:00']; //booked slots as arrays
$start = DateTime::createFromFormat('Y-m-d H:i:s',$start_time); //create date time objects
$end = DateTime::createFromFormat('Y-m-d H:i:s',$end_time);  //create date time objects
$time1 = $start;
$count = 0;  //number of slots
$out = array();   //array of slots 
for($i = $start; $i<$end;)  //for loop 
{
    $avoid = false; 
    $t1 = date_timestamp_get($i);
    $t2 = $t1+(60*60);

    for($k=0;$k<sizeof($booked);$k+=2)  //if booked hour
    {
        $st = DateTime::createFromFormat('Y-m-d H:i:s',$booked[$k]);
        $en = DateTime::createFromFormat('Y-m-d H:i:s',$booked[$k+1]);
          
        if( $t1 >= date_timestamp_get($st) && $t2 <= date_timestamp_get($en)  )
        $avoid = true;   //yes. booked
    }
    $slots =[ $i->format('H:i'),$i->modify("+60 minutes")->format('H:i')];
    if(!$avoid && $i<$end)  //if not booked and less than end time
    {
        $count++;  
        array_push($out,$slots);  //add slot to array
    }
}
var_dump($out);   //array out
Run Code Online (Sandbox Code Playgroud)

这是沙箱的链接 https://onlinephp.io/c/b0b77

附加信息

假设我们有一个从 开始的空闲时间范围10:00 until 13:00。脚本应返回的是10:00, 11:00, 以及12:00如果时间段是 则作为可能性60 min

如果时隙是45 min. 例如,它应该返回10:0010:4511:3012:15

因此,可能的变体应该从第一个可能的选项开始,随着时隙的增加而增加 ( 45, 60, or whatever time slot is set)

该插槽不能从10:12, 10:44, or another custom time

解决方案

下面的两个解决方案均按Salman A预期Jim工作。只需使用一点不同的方法即可。

重叠预订- 提供更新

如果您按照Salman A我们的建议有重叠的预订,则必须首先将它们合并,然后仅发送唯一的间隔。我用那个函数做到了

function mergeBookings($ranges)
{
    $retVal = [];
    //sort date ranges by begin time
    usort($ranges, function ($a, $b) {
        return strcmp($a['start'], $b['start']);
    });

    $currentRange = [];
    foreach ($ranges as $range) {
        // bypass invalid value
        if ($range['start'] >= $range['end']) {
            continue;
        }
        //fill in the first element
        if (empty($currentRange)) {
            $currentRange = $range;
            continue;
        }

        if ($currentRange['end'] < $range['start']) {
            $retVal[] = $currentRange;
            $currentRange = $range;
        } elseif ($currentRange['end'] < $range['end']) {
            $currentRange ['end'] = $range['end'];
        }
    }

    if ($currentRange) {
        $retVal[] = $currentRange;
    }

    return $retVal;
}
Run Code Online (Sandbox Code Playgroud)

然后只需在将 $booked 数组发送到脚本之前使用该函数即可。像这样

$booked = mergeBookings($booked);
Run Code Online (Sandbox Code Playgroud)

Sal*_*n A 2

如果预订日期已排序,则可以通过简单的嵌套循环来完成此操作。注意数据中的模式;一行的结束日期和下一行的开始日期形成一个可用范围,您可以在其中创建槽:

$start_time =                                        '2022-10-21 09:00:00';
$booked = array(
    array('start' => '2022-10-21 11:10:00', 'end' => '2022-10-21 12:10:00'),
    array('start' => '2022-10-21 14:00:00', 'end' => '2022-10-21 15:00:00')
);
$end_time =          '2022-10-21 15:00:00';
$slot_size = 60;
// data must be sorted by date
usort($booked, function($a, $b) {
    return DateTime::createFromFormat('Y-m-d H:i:s', $a['start']) <=> DateTime::createFromFormat('Y-m-d H:i:s', $b['start']);
});
$interval = new DateInterval('PT' . $slot_size . 'M');
$result = array();
for ($i = 0, $j = count($booked); $i <= $j; $i++) {
    // loop count + 1 times
    // first and last iterations are special
    $range_start = $i === 0 ? DateTime::createFromFormat('Y-m-d H:i:s', $start_time) : DateTime::createFromFormat('Y-m-d H:i:s', $booked[$i - 1]['end']);
    $range_end = $i < $j ? DateTime::createFromFormat('Y-m-d H:i:s', $booked[$i]['start']) : DateTime::createFromFormat('Y-m-d H:i:s', $end_time);
    $t1 = (clone $range_start);
    $t2 = (clone $range_start)->add($interval);
    while ($t2 <= $range_end) {
        $result[] = array('start' => $t1->format('Y-m-d H:i:s'), 'end' => $t2->format('Y-m-d H:i:s'));
        $t1->add($interval);
        $t2->add($interval);
    }
}
var_dump($result);
Run Code Online (Sandbox Code Playgroud)