如何解决跨夏令时的日期差计算问题(用于排班班次判断函数)
问题根源
原函数通过strtotime转时间戳后计算秒数差,再除以86400(一天的秒数)得到天数差。但夏令时切换当天的实际时长并非24小时(比如美国2023年3月12日夏令时启动,当天仅23小时),这会导致秒数差除以86400后出现小数,经floor处理后会错误地少算/多算天数,最终导致班次判断出错。
修复方案
改用PHP的DateTime类及其diff方法计算自然日历天数差,该方法直接按日历日期统计天数,完全不受夏令时的小时波动影响。
修改后的函数代码:
public static function getShift($date, $startDate, $sequence) { // 按指定格式创建DateTime对象,避免时区自动解析的干扰 $dateObj = DateTime::createFromFormat('m/d/Y', $date); $startDateObj = DateTime::createFromFormat('m/d/Y', $startDate); // 计算两个日期的自然天数差 $interval = $dateObj->diff($startDateObj); $daysDiff = $interval->days; $sequenceArray = explode(',', $sequence); $key = $daysDiff % count($sequenceArray); return $sequenceArray[$key]; }
关键说明
DateTime::createFromFormat严格按传入的m/d/Y格式解析日期,避免了默认时区解析带来的偏差diff方法返回的DateInterval对象的days属性,是两个日期之间的真实日历天数差,和夏令时导致的小时变化无关- 简化了取模逻辑:原代码的
($daysDiff % count(...)) +1再减1属于冗余操作,直接用$daysDiff % count(...)即可拿到正确的数组索引
调用示例保持不变:
$shift = ShiftHelper::getShift($date, '3/14/2023', '1,2,3,4');
内容的提问来源于stack exchange,提问作者SiriusPhil
相关产品推荐
相关产品推荐

