Laravel6结合Carbon实现跨日期夜班的当日考勤记录查询
问题场景
- 业务使用
attendance表存储考勤记录,表中start_at、end_at字段为datetime类型,所有时间以UTC格式存储 - 项目使用
php-carbon处理时间逻辑,约束条件:不允许修改表设计,不允许更改两个时间字段的类型 - 需要实现当日考勤记录筛选功能,必须兼容用户时区转换(前端按用户所在时区展示时间,全流程通过Carbon处理时区逻辑)
现存Bug
原有逻辑仅匹配start_at日期和当前日期一致的记录,无法适配跨天夜班场景:
示例:用户夜班开始时间为2022-07-08 23:00 UTC,结束时间为2022-07-09 09:00 UTC,7月9日用户查询当日考勤时,原有逻辑用
carbon::today()/carbon::now()直接匹配start_at日期,会因为start_at日期是7月8日导致查询不到该条记录。
原有问题代码:
public function today_Attendance($user_id, $shift_id) { $todays_attendance = \App\EmployeeWorkSchedule::where('work_schedule_time_id', $shift_id) ->where('user_id', $user_id) ->whereDate('start_at', carbon::now()) ->first(); return $todays_attendance; }
修复方案
核心查询逻辑覆盖两类属于当日的考勤记录:
- 用户时区下当日0点之后开始的考勤(常规白班/当日开始的班次)
- 用户时区下前一天开始、但结束时间晚于当日0点的考勤(跨天夜班)
所有时间边界先按用户所在时区计算,再转换为UTC格式和数据库存储值匹配,避免时区偏移导致的日期计算错误。
修复后代码:
public function today_Attendance($user_id, $shift_id) { // 替换为项目中实际获取用户时区的逻辑 $userTimezone = auth()->user()->timezone; // 计算用户时区下当日的UTC起止时间 $todayStartInUserTz = Carbon::now($userTimezone)->startOfDay(); $todayStartUtc = $todayStartInUserTz->copy()->setTimezone('UTC'); $todayEndUtc = $todayStartInUserTz->copy()->endOfDay()->setTimezone('UTC'); // 计算跨天班次的查询起始边界(常规夜班时长不会超过24小时,取前一天0点即可覆盖) $yesterdayStartUtc = $todayStartInUserTz->copy()->subDay()->startOfDay()->setTimezone('UTC'); $todays_attendance = \App\EmployeeWorkSchedule::where('work_schedule_time_id', $shift_id) ->where('user_id', $user_id) ->where(function ($query) use ($todayStartUtc, $todayEndUtc, $yesterdayStartUtc) { // 匹配当日开始的班次 $query->whereBetween('start_at', [$todayStartUtc, $todayEndUtc]) // 匹配前一天开始、跨天到当日的夜班 ->orWhere(function ($subQuery) use ($todayStartUtc, $yesterdayStartUtc) { $subQuery->whereBetween('start_at', [$yesterdayStartUtc, $todayStartUtc]) ->where('end_at', '>=', $todayStartUtc); }); }) ->first(); return $todays_attendance; }
注意事项
- 禁止直接使用数据库层面的
whereDate做日期匹配,该方法会按数据库存储的UTC时间计算日期,和用户所在时区的自然日存在时差,会导致查询结果偏移 - 跨天查询边界取前一天0点作为起点,可覆盖所有常规时长的夜班场景,如果业务存在连续超过24小时的班次,可根据实际业务调整往前追溯的时间范围
内容的提问来源于stack exchange,提问作者Haider Ali Khan
相关产品推荐
相关产品推荐

