时间标准与历法:TAI、闰秒与儒略日
时间或许是软件工程中最难以捉摸且复杂的变量。虽然表面上看起来很简单,但我们衡量时间的方式是原子物理学、天体力学和历史遗产之间微妙平衡的结果。
在本指南中,我们将揭开时间衡量的层层面纱,从原子级精确的 TAI 到天文追踪的儒略日,最后到 IANA 时区数据库的实际复杂性。
1. 基础:TAI(国际原子时)
现代计时的核心是 TAI (Temps Atomique International)。
什么是 TAI?
TAI 是一个高精度的原子时间尺度,基于分布在全球的 400 多个原子钟(主要是铯原子钟)的综合输出。与我们在日常生活中使用的时钟不同,TAI 不会加速或减速;它是对 SI 秒的连续、单调增加的计数。
为什么不直接使用 TAI?
虽然 TAI 非常稳定,但它并未“锚定”于地球的自转。如果我们仅依赖 TAI,数千年后“正午”最终会漂移到深夜,因为地球自转正在逐渐减慢且略有不规律。
2. 天体桥梁:UTC 与闰秒
为了让我们的时钟与太阳同步,我们使用 UTC(协调世界时)。
UTC-TAI 偏差
UTC 基于 TAI,但保持与 UT1(基于地球实际自转的时间尺度)的偏差在 0.9 秒以内。为了维持这种同步,我们偶尔会插入(或理论上删除)一个闰秒。
截至本文撰写时,UTC = TAI - 37 秒。这意味着原子钟比我们的民用时钟“快”37 秒。
闰秒的争议
闰秒是分布式系统的噩梦。如果两台服务器处理闰秒的方式不同(例如,一台“平滑”这一秒,而另一台“重复”第 60 秒),可能会导致大规模的竞态条件和数据损坏。由于这些技术挑战,国际上正在努力到 2035 年逐步取消闰秒。
3. 天文学家的时间:儒略日系统
对于长期历史计算和天文观测,标准的格里高利历(公历)由于其月份长度不一和闰年规则而显得过于碎片化。
儒略日数 (JD)
儒略日数是自公元前 4713 年 1 月 1 日“儒略周期”开始以来的连续天数计数。它旨在为历史上的任何日期提供一个单一、明确的参考。
- JD 2,460,000.5 大致对应现代时间。
- 小数点后的“.5”是因为儒略日在历史上从正午 (UT) 开始,而不是午夜,以便天文学家在不更改日期的情况下完成整夜的观测。
简化儒略日 (MJD)
简化儒略日由史密松天体物理台于 1957 年引入。其定义为: $$MJD = JD - 2,400,000.5$$ MJD 从午夜开始,并使用较小的数字,使其更便于现代计算机存储和 GPS 系统。
4. 实际时间:IANA 与 Olson 数据库
对于软件开发人员来说,最大的挑战不是原子物理学,而是人类政治。
IANA 时区数据库
也称为 Olson 数据库,IANA 数据库是所有历史和当前时区规则的权威集合。它不仅存储偏移量(如 +08:00),还存储特定区域(如 America/New_York)在标准时间和夏令时之间切换的规则。
为什么名称很重要
您应该始终将时区标识符存储为字符串(例如 Europe/Paris),而不是固定的偏移量。如果政府决定在明年更改夏令时开始日期,您的系统将自动适应,因为它链接到区域的规则集,而不是一个静态数字。
5. 计算遗产:POSIX 时间(Unix 时间)
Unix 时间(或 POSIX 时间)被定义为自 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)以来的秒数。
闰秒的“谎言”
Unix 时间处理闰秒的方式很独特:它忽略它们。当闰秒发生时,Unix 时钟实际上会暂停或重复一秒以保持与 UTC 同步。这意味着 Unix 时间并不是流逝秒数的完美计数(与 TAI 不同),这就是为什么高频交易和科学系统通常在内部使用 TAI 的原因。
结论
时间是一个多维度的构造。在您的下一个项目中,请记住这些经验法则:
- 使用 TAI 进行精确的持续时间测量或两个事件之间间隔的测量。
- 使用 UTC (Unix 时间) 处理大多数常规日志和数据存储。
- 使用 IANA 标识符 处理面向用户的本地时间。
- 使用儒略日 如果您正在构建用于天文学或深度历史分析的软件。
通过了解管理我们时钟的标准,您可以构建健壮、可预测且具有历史准确性的系统。