Ruby DateTime调用change(offset:)时时区偏移结果不一致问题
结果差异原因
出现这个问题的核心是你误用了ActiveSupport::TimeWithZone#change方法的offset参数,该方法本身不是为跨时区偏移转换设计的,具体逻辑如下:
- 基础前提:新加坡时区(SGT)全年固定为UTC+08:00,没有夏令时调整。执行
"2022-05-09".in_time_zone('Singapore')时,底层存储的UTC基准时间为2022-05-08 16:00:00 UTC;执行"2022-05-08".in_time_zone('Singapore')时,底层存储的UTC基准时间为2022-05-07 16:00:00 UTC。 change(offset:)的内部实现不会修改上述UTC基准时间,仅直接覆写时间实例上的偏移字段,且存在设计缺陷:它不会校验传入的偏移值和当前绑定的时区规则是否匹配,构造新时间对象时会 fallback 到Ruby进程所在系统的本地时区规则,直接受本地时区的夏令时切换逻辑影响。- 两个日期返回偏移不一致,是因为你的运行环境本地时区采用了夏令时规则(典型如西欧时区,冬令时偏移为+00:00,夏令时偏移为+01:00),
change方法执行时没有正确应用你传入的+00:00偏移,反而自动匹配了本地时区在对应日期的生效偏移:5月9日的时间命中了本地时区夏令时的+01:00偏移,5月8日的时间匹配到了你传入的+00:00偏移,最终出现了同逻辑不同日期结果不一致的现象。
正确实现方式
不要使用change(offset:)做时区偏移转换,要获取指定偏移的时间,直接调用标准时区转换方法即可:
# 获取对应UTC(+00:00)时间的正确写法 "2022-05-09".in_time_zone('Singapore').utc # 等价写法 "2022-05-09".in_time_zone('Singapore').in_time_zone('Etc/UTC')
内容的提问来源于stack exchange,提问作者Saravanan
相关产品推荐
相关产品推荐

