进入DST夏令时后mktime()返回值异常增加1小时问题咨询
问题原因总结
mktime的转换逻辑本身就默认会适配当前系统时区的DST(夏令时)规则,你观察到的现象符合标准实现,并非异常。
首先明确
mktime的标准行为:
它的输入参数struct tm是本地时间格式,返回值time_t是从1970-01-01 00:00:00 UTC开始的秒数。转换过程中如果struct tm的tm_isdst字段值为-1(默认未手动指定的状态),mktime会自动根据系统时区规则判断输入的时间点是否处于DST生效期,自动调整偏移量计算正确的UTC时间戳。再看你的时区配置规则:
你/etc/TZ的内容LMT0:00LMT-1:00,M8.5.1/10,M12.5.1/10是标准的POSIX时区格式,含义是:- 标准时间时区为LMT,与UTC时间一致
- 夏令时生效时,本地时间比标准时间快1小时
- DST生效时间为每年8月的第5个星期一10点,结束时间为每年12月的第5个星期一10点
你测试用的2021年8月30日正好是8月的第5个星期一,10点整恰好是DST的触发节点。
结合测试场景推导现象:
RTC硬件时钟本身没有时区、DST概念,只会按物理秒数走时。你提前把RTC同步到09:59:30,30秒后RTC走到10:00:00,此时rtc_tm2time拿到的ptm->tm_hour就是10。
此时mktime判断该时间点已经满足DST生效条件,而按照DST规则,触发夏令时的瞬间,本地时间会从09:59:59直接跳转到11:00:00,不存在10:00:00这个合法的本地时间点。mktime处理这个不存在的时间时会自动修正为夏令时生效后的时间,因此计算出的time_t会额外加上1小时的DST偏移。
后续你调用localtime把time_t转回本地时间时,localtime同样会应用DST规则,最终得到的小时数就是11,和你观察到的输出完全一致。
内容的提问来源于stack exchange,提问作者Mr.nerd3345678

