Unix 时间、POSIX 时间、epoch 时间戳:简短回答
在日常代码中,这三个术语指的是同一个数字:自 1970-01-01 00:00:00 UTC 起的秒数。区别在于它们的来历。「Unix 时间」是从早期 Unix 和 C 库继承下来的惯例。「POSIX 时间」是把同一计数写成正式标准(IEEE Std 1003.1),它把每天固定为正好 86,400 秒。「epoch 时间戳」是三者中最通用的——「epoch」只是一个固定的参考时刻,虽然它几乎总是指 1970 年的 Unix epoch,但其他系统(NTP、GPS、Windows)从不同的 epoch 起算。下表把每个术语对应到其标准以及它如何处理闰秒。
| 术语 | 计的是 | 由谁定义 | 闰秒 | 备注 |
|---|---|---|---|---|
| Unix 时间 | 自 1970-01-01 00:00:00 UTC 起的秒数 | 惯例(Unix / C 库) | 忽略 | 开发者日常使用的名称 |
| POSIX 时间 | 按固定公式自 epoch 起的秒数 | IEEE Std 1003.1 §4.16 | 忽略——每天正好 86,400 秒 | Unix 时间的正式规范版本 |
| epoch 时间戳 | 自固定 epoch(通常是 Unix epoch)起的计数 | 通用术语——epoch 各不相同 | 取决于 epoch/系统 | 「epoch」是参考时刻,并不总是 1970 年 |
| epoch 毫秒 | 自 1970-01-01 UTC 起的毫秒 | 同一 epoch,更细的单位 | 忽略 | 如今为 13 位;JavaScript 和 Java 的默认值 |
什么是 epoch 时间戳?
epoch 时间戳是从一个称为 epoch 的固定参考时刻起测量的数字计数。在开发者的日常用法中,epoch 时间戳通常指 Unix 时间戳:自 1970 年 1 月 1 日 00:00:00 UTC 起的秒数。值为 0 表示正好是 Unix epoch。正值在 1970 年之后;负值在之前。起关键作用的词是「epoch」——它命名起始时刻,其余只是从那里开始计数。关于朴素定义以及时间戳 0 的含义,请参阅《epoch 时间详解》;本文聚焦于这三个相互竞争的名称如何关联。
Unix 时间 vs POSIX 时间:标准怎么说
Unix 时间和 POSIX 时间指的是同一计数,但只有 POSIX 时间是正式规范化的。IEEE Std 1003.1——POSIX 标准——用一条把 UTC 日历日期转换为单个整数的明确公式定义了「Seconds Since the Epoch」。该公式的决定性性质是把每天视为正好 86,400 秒(60 × 60 × 24)。这是有意的简化:它忽略闰秒,以天文精度换取一个便于计算、排序和存储的值。「Unix 时间」是同一量的口语名称,早于该标准;当你需要精确定义时,引用的是「POSIX 时间」。
- POSIX 公式:一个 UTC 日期映射为一个整数,每天固定为 86,400 秒
- 结果:Unix/POSIX 时间戳跟随 UTC,但从不计入插入的闰秒
- time_t 是承载它的 C 类型——历史上为有符号 32 位,如今通常为有符号 64 位
- 同一时刻 → 在任何符合标准的系统上都是相同的值,无论时区或区域设置
Unix 时间和 POSIX 时间真的会有差别吗?
对几乎所有软件而言,不会——它们是同一个数字,你可以混用这两个术语。差别只在民用时间与物理的边界处显现。由于两者都忽略闰秒,Unix/POSIX 时间戳并不是自 1970 年起经过的 SI 秒的真实计数:它不包含自 1972 年以来插入 UTC 的 27 个闰秒。(TAI 是连续的原子时间标度,自 2017 年起恰好领先 UTC 37 秒。)在闰秒前后,POSIX 时钟会重复或跳过一秒,以使一天保持正好 86,400 秒。大型平台用 leap smearing(闰秒平滑)来避免这种不连续——把多出的一秒分摊到一整天,使任何时间戳都不会含糊。如果你在做高精度计时、跨闰秒排程,或与 GPS 或 TAI 比较,那正是「Unix」与「POSIX」不再只是学术之处,闰秒模型开始重要。
你会遇到的其他 epoch
「epoch 时间戳」之所以表示「Unix 时间戳」,只是出于惯例。epoch 只是时钟开始计数的那个时刻,而若干广泛使用的系统从不同的 epoch 起算。当一个值用 Unix epoch 解码不出 2020 年代的合理日期时,原因往往是另一个 epoch。
- Unix / POSIX epoch — 1970-01-01 UTC;秒(或 ms/µs)。几乎处处的默认值
- NTP epoch — 1900-01-01 UTC;由网络时间协议(RFC 5905)使用
- GPS epoch — 1980-01-06;GPS 时间没有闰秒,因此已领先 UTC 漂移(截至 2026 年为 18 秒)
- Windows FILETIME — 1601-01-01 UTC,以 100 纳秒为间隔计数
- JavaScript / Java — 是 Unix epoch 但以毫秒为单位,这正是这些值为 13 位的原因
为什么自 1970 年起的时间戳成为标准
Unix epoch 对早期 Unix 系统很实用,随着 Unix 理念扩散到 C 库、Linux、数据库、Web 服务器和编程语言,它成了惯例。单个数字时间戳比本地化的日期字符串更易于排序、比较、传输和存储。当 C 库继而 POSIX 把该计数标准化后,1970 年就在整个生态中固定下来——这正是为什么在一个平台上生成的值能在任何其他平台上被一模一样地解码。
epoch 时间戳示例
几个已知值能让定义更容易记住。
- 0 = 1970-01-01 00:00:00 UTC
- 1 = 1970-01-01 00:00:01 UTC
- 86400 = 1970-01-02 00:00:00 UTC
- 1700000000 = 2023-11-14 22:13:20 UTC
- 1767225600 = 2026-01-01 00:00:00 UTC
相关文章
FAQ
- epoch 时间和 Unix 时间一样吗?
- 在开发者的常见用法中,是的。epoch 时间通常指 Unix 时间:自 1970-01-01 00:00:00 UTC 起经过的秒数。
- Unix 时间的定义是什么?
- Unix 时间定义为自 1970-01-01 00:00:00 UTC 起的秒数,且不计闰秒。
- 什么是 POSIX 时间?
- POSIX 时间是 Unix 时间的正式规范版本。IEEE Std 1003.1("Seconds Since the Epoch")给出一条精确公式,计自 1970-01-01 00:00:00 UTC 起的秒数,并把每天视为正好 86,400 秒。
- 为什么 POSIX 时间忽略闰秒?
- 这是设计使然。POSIX 公式把一天固定为正好 86,400 秒,使该值便于计算与存储。其结果是 Unix/POSIX 时间戳跟随 UTC,但不表示插入其中的闰秒。
- POSIX 时间戳是否带时区信息?
- 否。POSIX 时间戳表示一个时刻。只有在把该时刻格式化为可读日期时才会套用时区。
- epoch 时间戳在 Windows、Linux 和 macOS 上一样吗?
- Unix epoch(1970-01-01 00:00:00 UTC)在现代平台和语言中是一致的,因此同一时刻在任何地方都得到相同的 Unix 时间戳。Windows 内部使用自己的 FILETIME epoch(1601 年),但标准的 Unix 和 POSIX 时间戳使用 1970 年。