如何基于夜间起止时间计算停车过夜时长(PHP/Laravel)
解决停车过夜天数计算的Carbon逻辑问题
原代码的核心逻辑存在缺陷:通过总停留时长减去两端非夜间时段时长再除以夜间总时长的方式,未正确处理跨天的夜间区间(如23:00至次日6:00),也未准确统计中间完整的夜间时段,导致计算结果偏差。
以下是修正后的实现代码,基于Laravel 9 + PHP 8.1的Carbon组件编写:
use Carbon\Carbon; public function getNightsSpent(Carbon $dateCheckin, Carbon $dateCheckout, string $nightStart = '23:00:00', string $nightEnd = '06:00:00') { $nightStart = Carbon::parse($nightStart); $nightEnd = Carbon::parse($nightEnd); // 计算夜间时段总时长(处理跨天情况) $nightDuration = $nightStart->diffInMinutes($nightEnd, false); if ($nightDuration < 0) { $nightDuration += 1440; // 跨天时段,加上24小时的分钟数 } $totalNightMinutes = 0; $currentDate = $dateCheckin->copy()->startOfDay(); // 遍历入住到退房的每一天,计算每个夜间时段的重叠时长 while ($currentDate->lessThanOrEqualTo($dateCheckout->startOfDay())) { $currentNightStart = $currentDate->copy()->setTimeFrom($nightStart); // 处理跨天的夜间结束时间(如23:00的次日6:00) $currentNightEnd = $nightEnd->greaterThan($nightStart) ? $currentDate->copy()->setTimeFrom($nightEnd) : $currentDate->copy()->addDay()->setTimeFrom($nightEnd); // 计算实际停留时间与当前夜间时段的交集 $overlapStart = max($dateCheckin, $currentNightStart); $overlapEnd = min($dateCheckout, $currentNightEnd); if ($overlapStart->lessThan($overlapEnd)) { $totalNightMinutes += $overlapStart->diffInMinutes($overlapEnd); } $currentDate->addDay(); } // 总夜间停留时长 / 夜间时段标准时长 = 过夜天数 return $totalNightMinutes / $nightDuration; }
代码逻辑说明
- 夜间时长处理:自动识别跨天的夜间区间(如23:00至次日6:00),计算出正确的夜间总时长(7小时=420分钟)。
- 时段遍历:逐个处理入住到退房之间的每一天,构建对应日期的夜间时段(跨天时段自动延伸至次日)。
- 交集计算:统计实际停留时间与每个夜间时段的重叠时长,累加所有有效重叠分钟数。
- 结果计算:用总夜间停留分钟数除以夜间标准时长,得到准确的过夜天数。
测试示例
- 原测试用例:
$checkin = Carbon::parse('2022-08-25 17:23:22'); $checkout = Carbon::parse('2022-08-27 10:35:18'); echo $this->getNightsSpent($checkin, $checkout); // 输出2.0,符合预期 - 入住改为2022-08-20的场景:
覆盖7个完整夜间时段,结果为7.0,修正了原代码8.8的错误计算。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

