程序员社区流传一个说法:世界上有两类难题,一类是缓存失效和命名,另一类是时区。而在 YouTube 上,把“时区到底难在哪”讲得最透彻的,是 Computerphile 频道的一条经典视频《The Problem with Time & Timezones》。这条视频没有炫技动画,就是一个白板加一段演示,却常年被程序员反复挖出来重看,长期位居该频道的播放量前列(据频道页面)。它值得读的原因很简单:它讲的不是某个框架的用法,而是几乎所有日历、日程、订单、日志系统都会踩的那颗雷——为什么“存本地时间”是一个看起来无害、实际上必然翻车的决定。本文带你完整重走这条视频的论证路线,再补上视频没来得及展开的几层。
| 项目 | 内容 |
|---|---|
| 英文标题 | The Problem with Time & Timezones |
| 中文标题 | 时间与时区的问题 |
| 频道 | Computerphile |
| 主讲人 | Tom Scott(英国知名科普创作者) |
| 发布时间 | 2017 年(据频道页面) |
| 播放量 | 数百万级,长期位居频道前列(据频道页面,未逐日核对) |
| 链接 | youtube.com/watch?v=-5wpm-gesOY |
先说结论:这条视频的核心论点,七年过去不但没有过时,反而越来越“真”。因为视频里警告的那类事故,今天仍在每个新框架、新数据库、新业务的身上重演——新的开发者换了一茬又一茬,雷还是那颗雷。
Tom Scott 的讲法非常克制。他不堆术语,而是从一个最朴素的场景出发:你写了一个日程应用,用户说“每天早上九点提醒我”。你怎么存这个时间?绝大多数人的第一反应是:存"09:00"这个字符串,或者存一个时间戳。视频用不到二十分钟,把这两个看似合理的答案逐一拆掉。
以英国为例,每年三月末的某个凌晨,时钟会从一点直接跳到两点(进入夏令时);十月末的某个凌晨,时钟又会从两点退回一点(退出夏令时)。这意味着:
视频里最扎心的演示就在这里:一个按“本地时间加一天”做循环日程的程序,跨过拨钟日之后,会议会整体漂移一小时。用户看到的是“我的提醒凭什么变了”,而代码看起来一行都没错。
很多人以为“时区 = UTC+8”这样一组偏移数字。视频明确指出这是幻觉:时区的本质是一整套由各国政府随时可以修改的规则——什么时候进入夏令时、什么时候退出、甚至整个时区划到哪里,都是行政决定,不是物理决定。
最极端的例子是萨摩亚:2011 年 12 月,这个国家为了和澳大利亚、新西兰的贸易伙伴对齐工作日,整条时区从 UTC−11 直接切到 UTC+13,全国日历上整个跳过了 12 月 30 日这一天——前一天是周四,一觉醒来是周六。工程师对“连续性”的一切假设,在行政命令面前不值一提。类似的规则调整,几乎每年都在全球某处发生。
政府改规则,软件怎么办?视频引出了这个体系里真正的英雄:IANA 时区数据库(tz database,俗称 tzdata / Olson 数据库)。这是一份由志愿者和研究者维护的规则表,收录了全球几百个时区的现行规则和历史变更,政府一改规则,这里就跟进更新,然后操作系统、浏览器、编程语言运行时在全球范围内分发更新。
换句话说:你以为你的代码在“算”时区,其实是 tzdata 在“查”时区。你的程序里唯一该做的,是别把规则硬编码进自己的代码,而是随时查最新的规则表。
视频给出的答案分两种情况,这也是它比网上大多数“一句话教程”高明的地方:
第二个结论是这条视频真正的“神来之笔”,也是被最多观众漏掉的一层。它推翻了“存 UTC 就万事大吉”的粗暴口诀。
视频里的每一条主张,背后都有扎实的工程与历史依据:
2026-09-26T08:00:00Z 末尾的"Z"代表祖鲁时间(UTC),这是机器间传输时间戳的标准格式。视频强调的“存 UTC”在工程上的落地形态就是它。证据充分的部分:时区规则可被政府随时修改(tzdb 的更新日志公开可查)、夏令时边界的“不存在/重复”时间问题(任何一本权威时间处理文档都会确认)、“存 UTC + 边缘换算”的行业共识、以及“未来日程必须存当地时间+时区”的结论——这些是跨语言、跨平台的工程共识,没有争议。
被简化或需要补充的部分:
+08:00 是一个数字,Asia/Shanghai 是一整套含历史和夏令时规则的条目。接口设计里混用两者,是比存本地时间更隐蔽的坑。第一条:给数据库立规矩。 所有“时间点”字段一律用 UTC 时间戳(PostgreSQL 用 timestamptz,它内部就是存 UTC),接口传输一律用 ISO 8601 带"Z"的格式,明文禁止存"2026-09-26 09:00:00"这类裸本地字符串。这条规矩写进团队规范,能消掉未来八成的时区事故。
第二条:日历类业务,存“当地时间 + IANA 时区名”。 你要保存的是用户当时指的那个墙上时间,以及他所在时区的完整规则条目。触发和展示时再换算。永远记录用户当时的时区选择,因为用户会搬家、会旅行。
第三条:把边界时间塞进测试集。 每个处理时间的函数,都应该被“不存在的时间”(春令时凌晨)、“重复的时间”(秋令时凌晨)和“萨摩亚跳日”三种输入拷打一遍。测耗时一律用单调时钟。这三个测试用例的成本不到半小时,防住的是半夜被告警叫醒的凌晨。
flowchart TD
A[日程App存了本地时间] --> B[春季拨快<br/>有些时间不存在]
A --> C[秋季拨慢<br/>同一时刻出现两次]
B --> D[只存偏移量并不够]
C --> D
D --> E[政府随时改规则<br/>时区是张会变的表]
E --> F[萨摩亚整日跳过<br/>规则可被整条推翻]
E --> G[IANA时区数据库<br/>全球软件同步更新]
F --> H[解法一<br/>时间点存UTC]
G --> H
G --> I[解法二<br/>未来日程存当地时间加时区]
H --> J[展示层再换算<br/>别硬编码规则]
I --> J
J --> K[例外提醒<br/>生日类业务别换算]
Intl API 如何替代手写偏移)。本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
