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

PHP计算可用预约时段代码遇非15分钟整时间结果错误如何解决

问题根因

原代码的已预约时段排除逻辑存在缺陷:仅会移除完全被已预约区间包裹的15分钟时段,当已预约结束/开始时间不是15分钟整数倍时,和预约区间存在部分重叠的可用时段会被误保留。
例如测试用例中15:30-16:10的已预约,16:00-16:15的时段和预约重叠了10分钟,但不符合时段开始≥预约开始 且 时段结束≤预约结束的条件,因此未被移除,最终返回错误的可用时段。

修复方法

将排除逻辑替换为通用的时间区间重叠判断:只要15分钟时段和任意已预约区间存在重叠,就从可用时段中移除。
重叠判断的核心逻辑为:时段开始时间 < 预约结束时间 且 时段结束时间 > 预约开始时间,覆盖所有部分重叠、完全包含的场景。

优化后完整代码
<?php
$businessHours = [
    ['09:00:00', '13:00:00'],
    ['14:00:00', '18:00:00'] // 1小时午休
];

$appointments = [
    ['10:00:00', '10:30:00'], // 格式为[开始时间, 结束时间]
    ['15:30:00', '16:10:00']
];

$interval = 15 * 60; // 预约间隔,可根据服务时长动态调整
$result = [];

// 先生成所有营业时间段内的间隔时段
foreach ($businessHours as $businessHour) {
    $periodStart = strtotime($businessHour[0]);
    $periodEnd = strtotime($businessHour[1]);
    $current = $periodStart;
    while ($current < $periodEnd) {
        $slotEnd = $current + $interval;
        // 避免跨营业时段的无效slot
        if ($slotEnd > $periodEnd) break;
        $result[] = [
            'start' => $current,
            'end' => $slotEnd,
            'start_str' => date('H:i:s', $current),
            'end_str' => date('H:i:s', $slotEnd)
        ];
        $current = $slotEnd;
    }
}

// 排除和已有预约重叠的时段
foreach ($appointments as $appointment) {
    $aptStart = strtotime($appointment[0]);
    $aptEnd = strtotime($appointment[1]);
    foreach ($result as $k => $slot) {
        // 时间重叠判断,覆盖所有重叠场景
        if ($slot['start'] < $aptEnd && $slot['end'] > $aptStart) {
            unset($result[$k]);
        }
    }
}

// 输出时可按需取字符串格式
print_r(array_column($result, 'start_str', 'end_str'));
?>
额外优化点
  • 提前将所有时间转换为时间戳存储,避免循环中重复调用strtotime转换字符串,性能更高
  • 新增了跨营业时段的slot过滤逻辑,避免出现超过营业结束时间的无效时段
  • 同时保留时间戳和格式化字符串,后续业务使用更灵活

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 11:15:05