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; }
关键修改说明
- 时间间隔映射优化:用数组替代switch语句,代码更简洁,还增加了默认值处理非法输入的情况。
- 不可用时间解析简化:用
list()+[1=>null]优雅处理可能只有开始时间的块,避免isset判断的冗余。 - 排序逻辑优化:用PHP内置的
usort替代手动写的冒泡排序,代码更易读且效率更高。 - 可用性判断逻辑修正:先默认时间是可用的,然后检查是否在任何一个不可用段内,只要命中一个就标记为不可用,这才是正确的逻辑。
- 循环条件修正:把
$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
相关产品推荐
相关产品推荐

