You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP脚本无法正确识别多预订时段及非整点预订的可用时段问题

问题:查询指定时间范围内排除已预订时段后的可用固定时长时段

原PHP脚本存在以下问题:

  • 仅能正确处理第一个已预订时段,无法识别后续的预订时段
  • 无法检测非整点预订时段(如12:10)与可用时段的冲突

示例场景:
时间范围为9:00-15:00,已预订时段为11:10-12:10、14:00-15:00,预期返回可用60分钟时段:9:00、10:00、12:10


原脚本代码

$start_time = '2022-10-21 09:00:00';  //开始时间字符串
$end_time = '2022-10-21 15:00:00';  //结束时间字符串
$booked = ['2022-10-21 12:00:00','2022-10-21 13:00:00']; //已预订时段数组(两两配对)
$start = DateTime::createFromFormat('Y-m-d H:i:s',$start_time); //创建DateTime对象
$end = DateTime::createFromFormat('Y-m-d H:i:s',$end_time);  //创建DateTime对象
$time1 = $start;
$count = 0;  //可用时段数量
$out = array();   //可用时段数组 
for($i = $start; $i<$end;)  //循环遍历时间范围
{
    $avoid = false; 
    $t1 = date_timestamp_get($i);
    $t2 = $t1+(60*60);

    for($k=0;$k<sizeof($booked);$k+=2)  //检查已预订时段
    {
        $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;   //标记为已预订
    }
    $slots =[ $i->format('H:i'),$i->modify("+60 minutes")->format('H:i')];
    if(!$avoid && $i<$end)  //若未预订且在时间范围内
    {
        $count++;  
        array_push($out,$slots);  //添加到可用时段数组
    }
}
var_dump($out);   //输出结果

解决方案

1. 合并重叠/连续的预订时段

使用mergeBookings函数将重叠或连续的预订时段合并,避免重复检查,简化冲突判断逻辑:

function mergeBookings($ranges)
{
    $retVal = [];
    // 按开始时间对预订时段排序
    usort($ranges, function ($a, $b) {
        return strcmp($a['start'], $b['start']);
    });

    $currentRange = [];
    foreach ($ranges as $range) {
        // 跳过无效的时段(开始时间晚于等于结束时间)
        if ($range['start'] >= $range['end']) {
            continue;
        }
        // 初始化第一个时段
        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;
}

2. 修正主逻辑脚本

修改主脚本解决冲突检测问题,同时支持自定义时段时长:

$start_time = '2022-10-21 09:00:00';
$end_time = '2022-10-21 15:00:00';
// 改用结构化数组存储预订时段,每个元素包含start和end
$booked = [
    ['start' => '2022-10-21 11:10:00', 'end' => '2022-10-21 12:10:00'],
    ['start' => '2022-10-21 14:00:00', 'end' => '2022-10-21 15:00:00']
];

$slotDuration = 60; // 自定义时段时长(分钟)
$start = DateTime::createFromFormat('Y-m-d H:i:s', $start_time);
$end = DateTime::createFromFormat('Y-m-d H:i:s', $end_time);
$availableSlots = [];

// 合并重叠预订时段
$mergedBooked = mergeBookings($booked);

// 遍历生成所有可能的时段
$currentSlotStart = clone $start;
while ($currentSlotStart->getTimestamp() + ($slotDuration * 60) <= $end->getTimestamp()) {
    $currentSlotEndTimestamp = $currentSlotStart->getTimestamp() + ($slotDuration * 60);
    $isAvailable = true;

    // 检查当前时段是否与任何预订时段冲突
    foreach ($mergedBooked as $booking) {
        $bookingStart = DateTime::createFromFormat('Y-m-d H:i:s', $booking['start'])->getTimestamp();
        $bookingEnd = DateTime::createFromFormat('Y-m-d H:i:s', $booking['end'])->getTimestamp();
        
        // 冲突判断:只要当前时段与预订时段有重叠,就标记为不可用
        if (!(($currentSlotEndTimestamp <= $bookingStart) || ($currentSlotStart->getTimestamp() >= $bookingEnd))) {
            $isAvailable = false;
            break;
        }
    }

    if ($isAvailable) {
        $availableSlots[] = $currentSlotStart->format('H:i');
    }

    // 推进到下一个时段
    $currentSlotStart->modify("+{$slotDuration} minutes");
}

var_dump($availableSlots);

关键改动说明

  • 预订时段改用结构化数组,避免原一维数组两两配对的歧义
  • 添加mergeBookings函数合并重叠时段,优化检查效率
  • 修正冲突检测逻辑:不再要求可用时段完全包含在预订时段内,只要有重叠就排除
  • 支持自定义时段时长(如设置为45即可生成45分钟间隔的时段)

内容的提问来源于stack exchange,提问作者lStoilov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 00:37:18