PHP:数据库存储营业时间及跨天营业状态判断问题
解决商家跨天营业时间的两个核心问题
我之前做本地生活服务项目时,刚好碰到过完全一样的问题——跨天营业时间(比如20:00到次日02:00)用Carbon判断总是误判凌晨时段为打烊,而且日期归属也容易乱。折腾了好几个测试用例后,总结出两套靠谱的解决方案,分享给你:
一、实时判定当前营业状态
核心思路是区分正常时段和跨天时段,分别处理判断逻辑,而不是统一给所有时段加一天(那样会把正常当天的时段搞乱)。
假设你的商家营业时间存在open_time(比如"20:00")和close_time(比如"02:00")字段,用Carbon实现的代码逻辑如下:
use Carbon\Carbon; // 获取当前时间 $now = Carbon::now(); // 从数据库取出商家的营业时间,这里假设$business是商家模型实例 $openTime = Carbon::parse($business->open_time); $closeTime = Carbon::parse($business->close_time); $isOpen = false; if ($closeTime->gt($openTime)) { // 情况1:正常当天时段(比如09:00-18:00),直接判断当前时间是否在区间内 $isOpen = $now->between($openTime, $closeTime); } else { // 情况2:跨天时段(比如20:00-02:00),拆分为两个区间判断 $todayEnd = Carbon::today()->endOfDay(); // 当天23:59:59 $tomorrowStart = Carbon::tomorrow()->startOfDay(); // 次日00:00:00 // 当前时间要么在【当天开门时间到当天结束】,要么在【次日开始到关门时间】 $isOpen = $now->between($openTime, $todayEnd) || $now->between($tomorrowStart, $closeTime); } // 最终$isOpen就是当前营业状态(true=营业中,false=打烊)
这个逻辑的关键是只对结束时间早于开始时间的跨天场景做特殊处理,完全兼容正常时段的判断,不会出现误判。
二、判断需更新的星期/日期归属
跨天时段的另一个问题是:次日凌晨的时段到底属于哪一天的营业时间?比如周五20:00到周六02:00,周六凌晨1点的营业应该归属到周五的记录里。
下面的代码可以帮你找到正确的目标日期(用于更新对应星期的营业数据):
use Carbon\Carbon; $now = Carbon::now(); $targetDay = $now->copy(); // 默认当前日期为目标日期 // 假设商家按星期存储营业时间,比如每个星期几对应一组时段 $dailyHours = $business->weeklyHours->where('day_of_week', $targetDay->dayOfWeekIso); foreach ($dailyHours as $hour) { $open = Carbon::parse($hour->open_time); $close = Carbon::parse($hour->close_time); // 如果当前时间在次日凌晨,且该时段是跨天的,就把目标日期往前推一天 if ($close->lt($open) && $now->between(Carbon::today(), $close)) { $targetDay->subDay(); break; } } // 现在$targetDay就是需要更新的正确星期/日期
额外优化建议
如果你的业务场景允许,也可以考虑把跨天时段拆分成两条记录:比如把20:00-02:00拆成「当天20:00-23:59」和「次日00:00-02:00」,分别对应当天和次日的营业时间。这样判断逻辑会更简单,但需要处理存储和展示的一致性(比如后台编辑时要合并显示跨天时段)。
内容的提问来源于stack exchange,提问作者Zach Handley
相关产品推荐
相关产品推荐

