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

PHP/Laravel预约系统:剔除特殊时段生成可预约时间槽方法

PHP/Laravel 预约系统可用时段拆分实现

核心需求

从给定的基础工作时段中,剔除指定的不可预约/已占用时段,拆分得到所有连续的可用时间区间,示例输入输出如下:

  • 基础工作时段
08:00 to 13:00
16:00 to 21:00
  • 待剔除不可预约时段:09:30 to 11:00、17:00 to 18:00
  • 预期输出可用时段
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'],
];

// 待剔除的不可预约时段
$removes = [
    ['start' => '09:30', 'end' => '11:00'],
    ['start' => '17:00', 'end' => '18:00']
];

实现逻辑

直接用时间字符串比较容易出现边界判断误差,统一转成当日0点起算的分钟数做数值计算,处理完成后再转回HH:MM格式即可,核心步骤如下:

  • 遍历每个基础工作时段,先筛选出所有和当前工作时段有重叠的不可预约时段,按开始时间从小到大排序
  • 用指针标记当前可用区间的起点,初始值为工作时段的开始时间
  • 逐个遍历重叠的不可预约时段:如果指针位置在不可预约时段起点之前,说明指针到不可预约时段起点之间是可用区间,存入结果;再把指针移动到不可预约时段的终点
  • 所有不可预约时段遍历完成后,如果指针位置还在工作时段结束时间之前,把指针到工作时段终点的最后一段区间存入结果

完整实现代码

/**
 * 从基础工作时段中剔除不可预约时段,返回可用时间槽
 * @param array $maintimes 基础工作时段集合,格式:[['start'=>'HH:MM','end'=>'HH:MM'], ...]
 * @param array $removes 待剔除不可预约时段集合,格式同$maintimes
 * @return array 可用时间槽集合
 */
function getAvailableSlots(array $maintimes, array $removes): array
{
    // HH:MM格式转当日0点起算的分钟数
    $toMinutes = function(string $time): int {
        [$h, $m] = explode(':', $time);
        return (int)$h * 60 + (int)$m;
    };
    // 分钟数转回HH:MM格式
    $toTime = fn(int $min): string => sprintf('%02d:%02d', intdiv($min, 60), $min % 60);

    $available = [];
    foreach ($maintimes as $slot) {
        $slotStart = $toMinutes($slot['start']);
        $slotEnd = $toMinutes($slot['end']);
        $cursor = $slotStart;

        // 筛选和当前工作时段重叠的剔除时段,按开始时间升序排列
        $overlaps = array_filter($removes, function($r) use ($slotStart, $slotEnd, $toMinutes) {
            $rStart = $toMinutes($r['start']);
            $rEnd = $toMinutes($r['end']);
            return $rStart < $slotEnd && $rEnd > $slotStart;
        });
        usort($overlaps, fn($a, $b) => $toMinutes($a['start']) <=> $toMinutes($b['start']));

        foreach ($overlaps as $block) {
            $bStart = max($toMinutes($block['start']), $slotStart);
            $bEnd = min($toMinutes($block['end']), $slotEnd);

            if ($cursor < $bStart) {
                $available[] = ['start' => $toTime($cursor), 'end' => $toTime($bStart)];
            }
            $cursor = max($cursor, $bEnd);
        }

        // 补全最后一段可用区间
        if ($cursor < $slotEnd) {
            $available[] = ['start' => $toTime($cursor), 'end' => $toTime($slotEnd)];
        }
    }
    return $available;
}

// 调用示例
$output = getAvailableSlots($maintimes, $removes);

边界兼容说明

该实现自动覆盖以下特殊场景,不需要额外添加判断逻辑:

  • 不可预约时段部分超出工作时段边界(比如不可预约时段是07:00-09:00,工作时段是08:00-13:00,会自动截断到工作时段范围内计算)
  • 多个不可预约时段连续/重叠
  • 不可预约时段完全覆盖某一段工作时段
  • 不可预约时段完全落在工作时段外(会自动过滤不处理)

传入示例数据运行后,$output返回结果和预期完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:36:23