PHP中带夏令时(DST)处理的昨日时间及24小时时间差问题
PHP DateTime夏令时处理与时间区间问题解析
嘿,我来帮你拆解这个时间处理的问题,一步步来:
为什么now减yesterday的时间戳差不是86400?
核心原因是new DateTime('yesterday')生成的是昨天同一时钟时刻,而非当前时间往前推24小时的时间。举个实际场景:在夏令时结束的次日(比如11月6日),前一天(11月5日)的时钟会在凌晨2点拨回1点,相当于那天多了1小时。如果当前是11月6日10:30,yesterday就是11月5日10:30,这两个时间点之间实际间隔是25小时30分钟,时间戳差自然远大于86400秒——你得到的93572秒就是跨夏令时变更+分秒差异导致的结果。
sub(new DateInterval('P1D'))如何处理夏令时?
PHP里DateInterval的P1D代表1个日历日,不是固定24小时。调用sub(P1D)时,系统会直接把日期减1,保留当前的时分秒,完全按照日历逻辑处理,不管实际经过的时长:
- 夏令时开始日(比如3月第二个周日,时钟从2点跳至3点):若当前是3月13日3:15,
sub(P1D)会得到3月12日3:15,实际间隔是23小时15分钟(因为跳过了2点到3点的1小时)。 - 夏令时结束日(比如11月第一个周日,时钟从2点拨回1点):若当前是11月6日2:45,
sub(P1D)会得到11月5日2:45,实际间隔是25小时45分钟(因为那天多了1小时的重复时段)。
如果你的需求是精确往前推24小时(不受日历和夏令时影响),别用P1D,改用PT24H(代表24小时时长):
// 写法1:用DateInterval $c = (new DateTime())->sub(new DateInterval('PT24H'))->getTimestamp(); // 写法2:更简洁的modify语法 $c = (new DateTime())->modify('-24 hours')->getTimestamp();
这样得到的时间戳和当前时间的差一定是86400秒,完全精准。
夏令时变更时,凌晨4点的定时任务会怎样?
分两种夏令时场景看:
夏令时开始(时钟拨快,跳过时段):
比如凌晨2点直接跳到3点,这个时段内的时间(如2:30)是不存在的,但凌晨4点在跳过时段之后,是一个有效的唯一时间点,定时任务会正常触发,不会有问题。夏令时结束(时钟拨慢,重复时段):
比如凌晨2点会出现两次(第一次是夏令时的2点,拨回1点后又到一次2点),但凌晨4点在重复时段之后,同样是唯一的有效时间,任务只会执行一次,不会重复。
只有当任务设置在被跳过或重复的时段(比如凌晨2点)时,才会出现异常:
- 跳过时段:系统通常会把任务调整到跳过之后的第一个有效时间(如3点)执行,或直接跳过该次任务(取决于定时工具的实现)。
- 重复时段:部分工具会执行两次任务,部分只会执行其中一次,用UTC时间存储任务触发点可以避免这个问题。
内容的提问来源于stack exchange,提问作者Aipo
相关产品推荐
相关产品推荐

