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

PHP实现排除Block Time的起止时间列表生成问题求助

问题分析与修复方案

咱们先拆解下你代码里的核心问题,然后一步步修正,就能得到你期望的时间槽列表了。

代码里的关键问题

你当前的时间可用性判断逻辑搞反了:

  • 原代码遍历不可用时间段时,只要当前时间不在某一个不可用段里,就直接把它加到结果里然后跳出循环。这会导致像13:00这种在第二个不可用段的时间,因为不在第一个不可用段(10:00-11:00)里,就被错误地加入结果了。
  • 另外,循环条件$time < $eTime会漏掉结束时间15:00,因为当$time等于15:00时,循环就终止了,没法把这个时间点加进去。

修正后的完整代码

我调整了逻辑,修复了这些问题,还优化了排序和时间解析的部分,代码更简洁健壮:

static function getListTime($time_interval, $s_hour, $e_hour, $peakTimesConfig) {
    // 用数组映射替代switch,更简洁
    $intervalMap = [
        '1' => new DateInterval('PT15M'),
        '2' => new DateInterval('PT30M'),
        '3' => new DateInterval('PT1H'),
        '4' => new DateInterval('PT2H')
    ];
    // 加个默认值,避免非法输入导致报错
    $interval = $intervalMap[$time_interval] ?? new DateInterval('PT1H');

    $result = [];
    $currentTime = new DateTime($s_hour);
    $endTime = new DateTime($e_hour);
    $bookingIntervalSec = $time_interval * 60;

    // 解析不可用时间段
    $unavailableTimes = [];
    foreach (explode(';', $peakTimesConfig) as $block) {
        // 处理可能只有开始时间的情况
        list($startStr, $endStr) = explode('-', $block) + [1 => null];
        $startTs = strtotime($startStr);
        $endTs = $endStr ? strtotime($endStr) : $startTs + $bookingIntervalSec;
        $unavailableTimes[] = ['start' => $startTs, 'end' => $endTs];
    }

    // 用usort替代手动冒泡排序,代码更易读高效
    usort($unavailableTimes, function($a, $b) {
        return $a['start'] - $b['start'];
    });

    // 遍历所有时间点,包含结束时间
    while ($currentTime <= $endTime) {
        $currentTs = $currentTime->getTimestamp();
        $isAvailable = true;

        // 检查当前时间是否在任何不可用时间段内
        foreach ($unavailableTimes as $block) {
            if ($currentTs >= $block['start'] && $currentTs < $block['end']) {
                $isAvailable = false;
                break; // 只要在一个不可用段里,就标记为不可用
            }
        }

        // 可用的话就加入结果
        if ($isAvailable) {
            $result[] = $currentTime->format("H:i");
        }

        $currentTime->add($interval);
    }

    return $result;
}

关键修改说明

  1. 时间间隔映射优化:用数组替代switch语句,代码更简洁,还增加了默认值处理非法输入的情况。
  2. 不可用时间解析简化:用list()+[1=>null]优雅处理可能只有开始时间的块,避免isset判断的冗余。
  3. 排序逻辑优化:用PHP内置的usort替代手动写的冒泡排序,代码更易读且效率更高。
  4. 可用性判断逻辑修正:先默认时间是可用的,然后检查是否在任何一个不可用段内,只要命中一个就标记为不可用,这才是正确的逻辑。
  5. 循环条件修正:把$time < $eTime改成$currentTime <= $endTime,确保结束时间15:00被包含在结果里。

测试验证

用你提供的参数调用这个方法:

print_r(getListTime('3', '09:00', '15:00', '10:00-11:00;13:00-14:00'));

得到的输出完全符合你的期望:

Array
(
    [0] => 09:00
    [1] => 11:00
    [2] => 12:00
    [3] => 14:00
    [4] => 15:00
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:20:47