在编程界流传着一个共识级的“恐怖故事”:如果你觉得自己能力强到可以手写时间处理逻辑,那说明你还没被时间坑过。日历应用里消失的一天、跨国会议里错乱的时刻、凌晨三点突然翻车的定时任务——十有八九都是时间和时区惹的祸。
今天要深读的这期视频,是这个领域公认的“传道之作”:Computerphile 频道的《The Problem with Time & Timezones》(时间与时区的问题),主讲人是英国科技圈名嘴 Tom Scott。这期视频发布于2013年,十几年过去依然被程序员们反复挖出来安利,在 Reddit 的 r/programming 和无数新人培训材料里常年出镜——可以说是一代程序员的时间观启蒙课。
它解决的是一个看似简单、实则极深的问题:为什么全世界最好的程序员,联手也造不出一个完美的时间处理函数? 答案不在数学,而在政治和人性。这期视频把答案讲得透彻又好玩,最后给出的三条“保命建议”,值得写在每一个工程团队的规范里。
| 项目 | 内容 |
|---|---|
| 视频标题 | The Problem with Time & Timezones |
| 频道 | Computerphile(计算机科普名频道,订阅量百万级) |
| 主讲 | Tom Scott(英国科普作者/工程师) |
| 发布时间 | 2013年 |
| 时长 | 约20分钟 |
| 播放量 | 约200万级(常青经典,历年累计,未实时核验) |
| 核心主题 | 为什么时间是编程中最难处理的抽象,以及工程上的正确姿势 |
视频的开场非常“Tom Scott”——他没有上来讲概念,而是从自己的一次行程说起:接了一场外地演讲的邀约,查火车时刻、对会议时间、算出发点,这套动作人类做起来毫不费力。但只要你试着把这个过程写进日程软件,让程序在全球任意两个城市之间自动完成“几点出发、几点到场”,立刻就会撞上一堵墙。
(延伸分析)这个开场其实暗藏了一个计算机科学的深刻观察:我们日常接触的抽象大多是“规整”的——文件系统有统一的接口,TCP 有严谨的协议规范,唯独时间,这个天天挂在每个人嘴边的东西,绑定的是地理、历史和立法。规整的东西机器擅长,不规整的东西机器就傻。Tom Scott 用最生活化的例子,一脚踹开了这期视频的主题:不是程序员蠢,是时间这个抽象本身就是漏的。
这是全片最核心、被引用最多的论点:时区不是科学家定义的,是政府定义的,而政府会随时改变主意。 Tom Scott 强调,任何一个时区规则——夏令时的起止日期、与 UTC 的偏移量、甚至整个国家换一个时区——都可能因为一纸政令在几周内生效。你的代码里写的每一条“固定规则”,都可能在某个凌晨被现实作废。
(延伸)现实远比视频里的举例更魔幻:2011年底,萨摩亚为了加强与主要贸易伙伴的联系,决定跨过国际日期变更线,全国直接跳过了12月30日这一天——日历上这天根本不存在;更早的年代,荷兰曾长期使用比格林尼治快约20分钟的“阿姆斯特丹时间”;印度用的是 +5:30 这种半小时时区,澳大利亚中部甚至有 +9:15 的四十五分钟偏移。每一次“看似不合理”的规则背后都是一段历史。中国全国统一使用北京时间(UTC+8),地理上却横跨多个时区——对写代码的人来说,这意味着“中国的用户”时区判断出奇地简单,而“美国的用户”能让你把光阴活活算错半天。
视频给出的第一条工程建议,后来成了全行业的共识:存储一律用 UTC 时间戳,本地时区只发生在“展示”那一层。Tom Scott 强调,如果你在数据库里存“2026-09-15 14:30:00”这种带本地时间的字符串,恭喜你,这个数据已经烂了——因为它丢失了“这是哪个时区的时间”这一关键信息,将来无论怎么解析都是猜。
(延伸)这个原则在主流数据库和语言里早有体现:PostgreSQL 的 timestamptz 类型本质上就是把输入归一成 UTC 再存;Java 的 Date 对象内部也只是一个毫秒数。顺带提醒一个容易被忽略的远期风险——2038问题:还在用32位有符号整数的 time_t,将在2038年1月19日溢出归零。64位服务器基本免疫了,但大量还在服役的嵌入式设备、老旧网元、工控模块,都值得在今天查一遍。时间债,是会在七年后连本带息讨回来的。
如果说时区偏移只是麻烦,夏令时(DST)就是灾难级的存在。视频里 Tom Scott 用英国冬令时/夏令时做例子:一年两次,全英国在凌晨把时钟拨动一小时。对程序来说这意味着:秋天的那一小时会在本地时间上出现两次——凌晨的一点半真实地存在了两遍,日志顺序、任务调度、计费记录全都能被它搅乱;春天则相反,有一段本地时间根本不存在。更坑的是,南北半球夏令时方向相反,赤道附近不少国家干脆不实行。
(延伸)这个坑在不同语言生态里留下了大量“伤疤”:Java 旧的 Date/Calendar API 混乱到业界忍无可忍,Java 8 终于引入了全新的 java.time(JSR-310),它的设计脱胎于 Joda-Time 库,作者 Stephen Colebourne 亲自操刀重构;JavaScript 的 Date 连“月份从0开始”这种反人类设计都保留了三十年,社区库 moment.js 已于2020年宣布进入维护模式,接棒的下一代标准 Temporal 提案在 TC39 磨了多年仍在推进。一门语言的时间 API 质量,几乎可以当成工程品位的试金石。
视频里另一个重要科普:你的手机、电脑、服务器之所以“知道”每个国家当前的时区规则,靠的是 IANA 维护的时区数据库(tz database,又称 Olsen database)。它由志愿者社区维护,各国规则一变,就发新版本,再经由操作系统更新、手机推送分发到全世界。Tom Scott 特别点出了危险场景:政府宣布时区变更到正式生效可能只有几周,如果你的设备没及时更新 tzdata,日程就会集体错乱。
(延伸)由此可以推出一条朴素但常被违反的纪律:永远不要在代码里硬编码时区规则。“印度是 +5:30”、“美国东部夏令时是 -4”这类硬编码,本质上是把你自己的知识和 tzdata 的一次快照焊死在了一起,政府一改规则就集体翻车。正确姿势是引用系统时区标识(如 Asia/Shanghai),让底层数据库的更新自然流经你的系统。服务器的 tzdata 包,应该像安全补丁一样纳入例行升级管理——它不是普通依赖,它是“现实世界规则的驱动程序”。
视频收尾,Tom Scott 给出了那条被无数博客转述的“保命三原则”,大意是:第一,如果业务上可以不处理时区,那就别处理;第二,必须处理时,交给成熟的系统库和时区数据库,永远别自己发明;第三,存储用 UTC,展示才转本地。没有花哨的框架,没有炫技的算法,就这么朴素的三句话——因为时间处理这个领域, complexity 不在你这边,而在现实世界那一边。
(延伸)落到今天各语言的标准姿势:Java 用 java.time,Python 3.9+ 内置 zoneinfo(PEP 615),Go 用 time.LoadLocation,前端等 Temporal 落地期间用 date-fns 这类库兜底;服务间传时间,统一用 ISO 8601 格式的 UTC 字符串(如 2026-09-15T06:30:00Z),末尾那个 Z 就是全世界的通用暗号。接口契约里把这一个小字符写清楚,能省掉未来无数个深夜的电话会议。
flowchart TD
T["编程中的时间问题"] --> A["存储层"]
T --> B["计算层"]
T --> C["展示层"]
A --> A1["只存UTC时间戳"]
A --> A2["禁存本地时间字符串"]
B --> B1["比较与调度先归一"]
B --> B2["提防夏令时重与缺"]
C --> C1["最后一步才转本地"]
C --> C2["只用系统时区库"]
B2 --> D["IANA时区数据库"]
C2 --> D
D --> E["政府随时改规则"]
E --> F["设备靠更新续命"]
F --> G["硬编码规则必翻车"]
第一,给你的项目做一次“时间审计”。 检查三件事:数据库时间字段是不是 timestamptz 或等价的 UTC 存储?服务间接口是不是 ISO 8601 带明确的 UTC 标识?有没有任何一处代码硬编码了“+8”或“+5:30”?三问有一个答不上来,就值得排期修复——这类债平时不响,一响就是在跨年、跨夏令时切换的凌晨。
第二,把“拨钟测试”写进测试用例。 把系统时间拨到夏令时切换边界、年末最后一天、闰年2月29日再跑一遍核心逻辑。日历、计费、调度类系统尤其要这么做。真实世界里,国内外不少大厂都吃过“那天根本不存在”或“那天出现了两次”的亏。
第三,通信同行请把视角拉到“同步”层面。 这期视频讲的是“读时间”的坑,而通信行业还要管“对时间”:网管系统告警时间戳建议全网统一 UTC 落库,跨国排障时才不会各说各话;NTP/PTP 同步体系里,闰秒是真实发生过的事故源——2012年6月30日的闰秒曾让多家知名互联网站集体故障,Google 因此长期采用“闰秒平滑”(leap smear)方案把这一秒摊进全天;而 5G TDD 基站对空口同步有微秒量级的硬要求,时间哪是一行代码,是一张网的地基。
第四,老设备别忘查 2038。 32位时间戳溢出问题对服务器已是过去时,对仍在服役的嵌入式模块、老旧网元、工控盒子却是进行时。列个清单,比2037年集体救火便宜得多。
zoneinfo 的设计文档,顺带理解系统 tzdata 的接入方式时间代码你永远写不对——但你可以站在 tzdata 和标准库的肩膀上,把“错”留给全世界的志愿者去修正。
注:视频播放量、时长等页面数据为撰写时的通行说法,以 YouTube 页面实时数据为准。
本文由「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 等场景全覆盖。
