闰秒说明:UTC 如何与地球自转保持一致
闰秒是插入到 UTC 中的一秒调整,用来让原子钟时间与日益变慢的地球自转保持一致。它曾让大型系统崩溃,并计划在 2035 年前废除。本指南讲解它是什么、Unix 时间如何处理它(大多是忽略),以及系统为保持安全所采用的实用模式。
一分钟看懂闰秒
闰秒是偶尔添加到 UTC 的额外一秒,用来把时钟时间保持在 UT1 的 0.9 秒以内 —— UT1 是由地球实际自转定义的时间。原子钟以完全稳定的速率走动,但地球并不以完全稳定的速率自转,于是两者渐行渐远,必须重新同步。自 1972 年以来共有 27 次这样的插入,最后一次在 2016-12-31,而世界各计量机构已投票决定在 2035 年前废除它们。关键在于:Unix 时间完全忽略闰秒。下表显示主要时间标度之间的关系。
| 时间标度 | 基于 | 闰秒? | 备注 |
|---|---|---|---|
| TAI | 原子钟(SI 秒) | 从不 | 连续 —— 自 2017 年起领先 UTC 37 秒 |
| UT1 | 地球自转(天文) | — | UTC 保持接近的太阳时 |
| UTC | TAI,向 UT1 微调 | 是(至 ~2035) | 全球民用时间 |
| Unix 时间 | UTC,但每天 86,400 秒 | 忽略 | 应用代码所用 |
什么是闰秒?
闰秒是添加到 UTC 的额外一秒,用来把它保持在 UT1 的 0.9 秒以内 —— UT1 是基于地球自转的天文时间。地球自转并不规则,并在长时间尺度上略微变慢,于是原子的 UTC 和自转的 UT1 渐行渐远,必须重新对齐。
- 1972 年至最后一次(2017-01-01)之间共插入 27 次正闰秒
- 从未发生过负闰秒,但若地球加速,理论上是可能的
- IERS 的 Bulletin C 至少提前六个月公告即将到来的闰秒
- 插入在 UTC 一天的最末尾(23:59:60),通常在 6 月 30 日或 12 月 31 日
为什么会有闰秒
UTC 于 1972 年被重新定义为一种混合体:SI 秒(原子),通过偶尔插入闰秒而保持在 UT1(天文)的几分之一秒以内。目标是让时钟时间与太阳时大致对齐,而不必固守任一纯粹体系。
- TAI:国际原子时,一种没有闰秒的纯 SI 秒计数(当前领先 UTC 37 秒)
- UT1:自转时间,基于地球姿态观测
- UTC:混合体 —— 原子的滴答,周期性地向 UT1 靠拢
- 若没有闰秒,UTC 与太阳每世纪会偏离约 1 分钟
闰秒与 Unix 时间
POSIX Unix 时间被定义为忽略闰秒:每个 Unix 日恰好是 86,400 秒。当闰秒发生时,不同系统处理方式各异 —— 没有一个会把 Unix 时间戳额外加一秒。这就是为什么 Unix/POSIX 时间戳跟随 UTC,却不是自 1970 年以来流逝的真实物理秒数的计数。
- 严格 POSIX:秒号重复 —— 23:59:59 出现两次,二者映射到同一个 Unix 时间戳
- 2012 年前的 Linux 内核:实现严格 POSIX;浮现许多 bug(Java、MySQL、Hadoop 挂起)
- 现代 Linux 内核:通过 clock_settime() 应用调整;某些实现在一个窗口内做平滑
- 平滑:把额外一秒分摊到数小时或一天,使任何一秒都不会被重复
Leap smearing(闰秒平滑)
大多数大型公共 NTP 服务不再把闰秒原样传给客户端。它们做平滑:把额外一秒分摊到一个窗口,使客户端时钟在窗口期间比 UTC 走得极其略快(负闰秒则略慢)。结果是没有任何客户端会看到 23:59:60 —— 代价是短暂偏离严格的 UTC。
| 提供方 | 平滑窗口 | 备注 |
|---|---|---|
| 24 小时,以 UTC 午夜为中心 | 约 11.6 µs/s 调整 | |
| AWS | 24 小时 | Amazon Time Sync Service |
| Meta(Facebook) | 17 小时 | — |
| Microsoft | 24 小时 | 自 2018 年起 |
- 平滑意味着客户端挂钟在平滑窗口期间偏离严格的 UTC —— 用于应用没问题,但不适合高精度计时
会有负闰秒吗?
迄今为止每一次闰秒都是正的 —— 增加一秒。但自约 2020 年起,地球转得比过去大半个世纪都略快,短暂地把曾经只是理论的负闰秒前景抬了出来:移除一秒,使 23:59:58 之后直接是 00:00:00。那将是史上首次,而许多能处理重复一秒的系统,仍会错误处理被跳过的一秒。近期研究表明,极地融冰正在减缓这种加速,可能把任何负闰秒推迟到 2029 年左右 —— 到那时 2035 年的废除或许已让它变得无关紧要。
2035 年的废除
国际计量大会(CGPM)于 2022 年 11 月(第 4 号决议)投票决定,最迟在 2035 年前从 UTC 中取消闰秒。该计划用一个大得多的容差取代 ±0.9 秒的 UT1 容差,实际上让 UTC 在数十年间偏离太阳时。
- 2022-11:CGPM 第 4 号决议 —— 在 2035 年或之前增大 UT1−UTC 的最大差值
- 2023-11:ITU-R WRC-23 正式认可该计量决定
- 废除后,UTC 将成为一个以固定偏移与 TAI 绑定的纯原子时间标度
- 各实现有到 2035 年的时间来逐步淘汰处理闰秒的代码路径
相关参考
FAQ
- 至今有过多少次闰秒?
- 1972 年至 2017-01-01 之间,UTC 共插入了 27 次正闰秒。此后再无。从未发生过负闰秒。
- UTC 和 TAI 有什么区别?
- TAI 是没有闰秒的连续原子时间;UTC 是经闰秒调整、以保持在地球自转 0.9 秒以内的 TAI。自 2017 年起,TAI 恰好领先 UTC 37 秒。
- 会有负闰秒吗?
- 有可能,但从未发生。自约 2020 年起地球转得略快,原则上可能需要移除一秒而非增加一秒。计划于 2035 年废除闰秒,可能使这个问题变得无关紧要。
- 2035 年后 Unix 时间戳会包含闰秒吗?
- 不会。Unix 时间从未计入闰秒,今后也不会。废除之后,UTC 自身停止添加闰秒,于是 Unix 时间与 UTC 将直接保持一致。
- 为什么 Reddit 和 Cloudflare 在闰秒当天崩溃?
- Linux 内核和 Java 库存在会在出现 23:59:60 时触发的 bug —— 通常是死循环、锁竞争,或某些代码路径中因“负秒”导致的 NaN 运算。
- 当前 TAI−UTC 偏差是多少?
- 37 秒。即 27 次闰秒(自 1972 年)加上定义 UTC 时设定的 10 秒初始偏移。