如何检测时间段碰撞重叠,实现PHP日程合并冲突校验函数
PHP 日程块合并冲突校验实现方案
核心判断逻辑
两个时间段[startA, endA)和[startB, endB)不重叠的充要条件为:endA <= startB || endB <= startA,只要不满足该条件即可判定为重叠。
注:按照需求示例,端点重合(比如一个时间段为10:30-12:00,另一个为12:00-13:00)不算冲突,完全符合上述判断逻辑。
判断时将HH:MM格式的时间拆分为小时和分钟,换算为当日总分钟数做数值比较即可,无需处理复杂的时间戳逻辑,性能开销更低。
完整实现代码
// 已有日程,可根据实际需求调整为函数参数、类属性等 $schedule = [ 'monday' => ['11:00-14:00'], 'tuesday' => ['10:30-12:00', '14:30-17:30'], // 其余星期日程按需补充 ]; /** * 校验待合并日程块和已有日程是否存在冲突 * @param array $blocks 待合并日程块 * @return bool 无冲突返回true,有冲突直接返回false */ function checkScheduleConflict(array $blocks): bool { global $schedule; // 若$schedule不作为全局变量,可直接调整函数参数为checkScheduleConflict(array $blocks, array $schedule),删除本行即可 // 辅助方法:将HH:MM格式时间转换为当日分钟数 $timeToMinutes = function (string $time): int { [$hour, $minute] = explode(':', $time); return (int)$hour * 60 + (int)$minute; }; // 遍历待合并日程的星期维度 foreach ($blocks as $weekday => $blockTimes) { // 对应星期无已有日程,直接跳过校验 if (!isset($schedule[$weekday])) { continue; } $existTimes = $schedule[$weekday]; // 遍历当前星期下所有待校验时间段 foreach ($blockTimes as $blockTime) { [$blockStartStr, $blockEndStr] = explode('-', $blockTime); $blockStart = $timeToMinutes($blockStartStr); $blockEnd = $timeToMinutes($blockEndStr); // 和已有时间段逐一比对 foreach ($existTimes as $existTime) { [$existStartStr, $existEndStr] = explode('-', $existTime); $existStart = $timeToMinutes($existStartStr); $existEnd = $timeToMinutes($existEndStr); // 判定重叠:不满足「待校验块在已有块前结束」或「待校验块在已有块后开始」即为冲突 if (!($blockEnd <= $existStart || $blockStart >= $existEnd)) { return false; } } } } // 所有校验通过,无冲突 return true; }
测试验证
// 测试用例1:无冲突,返回true $blocks1 = [ 'monday' => ['8:00-10:00', '15:00-16:00'], 'tuesday' => ['12:00-13:00'] ]; var_dump(checkScheduleConflict($blocks1)); // 输出 bool(true) // 测试用例2:存在冲突,返回false $blocks2 = [ 'monday' => ['8:00-10:00', '15:00-16:00'], 'tuesday' => ['11:00-12:30'] ]; var_dump(checkScheduleConflict($blocks2)); // 输出 bool(false)
内容的提问来源于stack exchange,提问作者jade
相关产品推荐
相关产品推荐

