I4.08.3historical timezone rule changes设计

历史时区规则本身会随政治决定变化,跨年份的时间换算不能假设规则不变

别名: tz database · IANA 时区 · 时区规则变更 · timezone politics

概念解释

某座城市「现在比 UTC 快几小时、哪一天拨钟」,不是地理常数,是法令。历史时区规则会变:今年不实行夏令时的地方,十年前可能实行;偏移本身也会被议会改掉。把 2010 年的一个本地钟面,用 2026 年的规则表去换算,得到的瞬间会是错的。跨年份的换算必须带着那一年当时有效的规则,不能假设一张表用一辈子。

机制

规则表(IANA 时区数据库一类)把每个区的历史切成一段段:从哪一天起偏移是多少、要不要夏令时、夏令时从哪一天到哪一天。换算一个过去的本地钟面,要先找到它落在哪一段,再用那一段的偏移。用「当前段」去解历史钟面,等于改写了当时墙上的格。未来的重复事件更脆:法令可能在事件发生前才公布,展开时用的表和发生时用的表可能不是同一张。

客户端、服务器、数据库若各抱一张不同版本的表,同一条记录会算出三个瞬间。错误看起来像「时区搞错了」,其实是表的政治版本不一致。表还需要更新通道:国家宣布取消夏令时,产品若还在用旧表,会在法令生效那天把所有本地钟面算错。

边界

只处理「现在起往后几小时」的相对时间,不踩历史段,规则变更影响不到。时刻已经以绝对瞬间存下来的过去事件,不再依赖规则表去还原「它是什么瞬间」——表只还影响「把它画成哪一座钟」。真正受伤的是:当时只记下了本地钟面和区名、没记下瞬间的数据,以及还没发生、仍按钟面规则展开的系列。测试环境若用一张冻死的表,测不出法令变更,会把生产上的换算错误当成偶发。

怎么落地

  • 换算任何跨年的本地钟面时,用该日期所属的历史段,不要用「当前偏移」。
  • 运行中的服务要能更新规则表,并在更新后对尚未发生的重复事件重新展开,而不是沿用旧瞬间。
  • 客户端、服务器、批处理使用同一版本的表;版本写进可观测性,便于对上「算错的那一天是不是刚发布了新法令」。
  • 验证:拿一个已知法令变更的区(曾经改过是否实行夏令时,或改过标准偏移),把变更前的本地钟面分别用「当时的段」和「今天的段」换算,两个瞬间应能被故意算成不同。更新表之后,尚未发生的系列应重算;已经以瞬间存档的历史事件,瞬间不得被表更新改写。

延伸

  • 同组I4.08.1 时间应以绝对标准时间存储,仅在呈现时转换为本地时区 · I4.08.2 跨夏令时边界的重复性事件需要重新计算本地时刻而非固定偏移 · I4.08.4 用户切换所在时区后,已保存的过去记录不应随之改变显示的绝对时间点
  • 相邻I4.05 时区 · S2.01 日期与时间格式
  • 站内检索tz database · IANA timezone · historical offset

同组卡片

快捷操作

分享

分享当前页面

ios_share

https://hci.top/zh/handbook/I4.08.3