重叠判断应写为!($a_start > $b_end || $a_end
直接用时间戳做比较是最稳妥的起点,但很多人卡在“怎么比才不漏、不重、不跨日错判”——关键不在转换,而在逻辑表达式是否覆盖全部重叠情形。
PHP中用
strtotime()转时间戳后怎么写重叠判断别用
if ($a_start > $b_end || $a_end 然后取反,这种写法边界易出错。正确姿势是直接套用数学定义:两个区间 [A, B] 和 [Y, Z] 重叠 ⇔ A ≤ Z AND Y ≤ B。
- 把用户请求的开始/结束时间、已有记录的开始/结束时间,全部用
strtotime()转成整数时间戳- 代入公式:
$requestedStart- 注意:这个条件天然支持跨日(比如 23:00–01:00)、首尾相接(20:00–21:00 和 21:00–22:00)等场景,且返回 true 表示冲突
- 如果数据库里存的是分离的日期+时间字段,先拼成字符串再转:
strtotime($date . ' ' . $time),否则时区或格式差异会导致结果偏差Laravel Eloquent 查询中避免手动拼条件
在控制器里用 PHP 做完判断只是第一步;真正在数据库层拦截重复预约,必须把重叠逻辑下推到 SQL。否则并发高时仍可能写入冲突数据。
- 确保模型字段是
starts_at和ends_at(类型为DATETIME),而不是分开的 date/time 四字段- 查询写法应为:
where('starts_at', 'where('ends_at', '>=', $requestedStart)- 不要用
orWhere拼三个条件,那会漏掉“新预约完全包住旧预约”的情况,且难以加索引- 给
(starts_at, ends_at)加联合索引,能显著提升这类范围查询性能PostgreSQL 用户可以直接用
OVERLAPS如果你用的是 PostgreSQL,不用自己推导逻辑,数据库原生支持更清晰的表达。
- SQL 写法:
(starts_at, COALESCE(ends_at, '9999-12-31')) OVERLAPS (?, ?),其中 ? 是用户传入的starts_at和ends_atOVERLAPS默认把区间当作左闭右开还是闭区间?答案是:它等价于starts_at starts_at_of_other,即包含端点接触(21:00–22:00 和 22:00–23:00 判定为重叠)- 注意
ends_at可能为 NULL(表示“无限期”),要用COALESCE统一兜底,否则OVERLAPS对 NULL 行为不可控最容易被忽略的是时区一致性:所有时间戳生成、数据库存储、查询传参,必须统一在同一个时区(推荐用 UTC 存储,应用层按需转换显示)。哪怕只差一小时,跨夏令时的预约就可能被错误放行或误拒。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!












