什么是 Unix 时间戳?完整指南
什么是 Unix 时间戳?
Unix 时间戳(也称为 POSIX 时间或 Epoch 时间)是一种跟踪时间的系统,它计算自 Unix epoch——1970 年 1 月 1 日 00:00:00 UTC——以来经过的秒数,不包含闰秒。
与因时区而异的人类可读日期(如 "July 19, 2026, 3:30 PM EST")不同,Unix 时间戳是一个单独的整数,在地球上的任何地方都代表同一个时刻。例如,时间戳 1785292800 对应一个特定的瞬间,无论你是在纽约、伦敦还是东京。
Unix 时间戳是现代计算中时间处理的支柱。操作系统、编程语言、数据库和文件系统在底层都依赖这种简单的整数表示。
Unix epoch:为什么是 1970 年 1 月 1 日?
选择 1970 年 1 月 1 日作为 "epoch"(起始点)并非随意之举。这一决定源于几个实际考虑:
- 早期 Unix 开发:Unix 操作系统诞生于 20 世纪 60 年代末和 70 年代初的贝尔实验室。到 70 年代初时间系统被标准化时,1970 年 1 月 1 日是一个干净、近期的参考点。
- 简单性:早期 Unix 系统上的时间以 32 位有符号整数按秒存储。使用较近的日期可以最大限度地扩大面向未来的可表示范围。
- 先例:epoch 在第一个 POSIX 标准中被正式确定,使其成为所有 Unix 衍生系统的通用参照。
早期的类 Unix 系统曾使用过不同的 epoch 日期,但 1970 年 epoch 最终胜出,并从此成为所有符合 POSIX 标准的系统的标准。
时间戳值是如何运作的
核心思想很简单:
- 时间戳
0恰好表示 1970 年 1 月 1 日 00:00:00 UTC - 时间戳
86400(60 × 60 × 24)表示 1970 年 1 月 2 日 00:00:00 UTC - 时间戳
-3600表示 1969 年 12 月 31 日 23:00:00 UTC(负数时间戳表示 epoch 之前的日期)
公式很简单:
timestamp = seconds since 1970-01-01 00:00:00 UTC
毫秒级时间戳
许多现代系统,尤其是 JavaScript 和 Web API,使用毫秒而不是秒。毫秒级时间戳只是将秒级值乘以 1000:
- JavaScript
Date.now()返回毫秒 - Python
time.time()返回带毫秒小数部分的浮点秒数
在转换之前,务必确认系统使用哪种分辨率,因为混用可能导致日期相差数十年。
2038 年问题
2038 年问题(也称为 "Unix 千年虫" 或 "Y2K38")是一个影响以 32 位有符号整数存储时间戳的系统的日期表示问题。
32 位有符号整数可以容纳约 -21 亿到 +21 亿之间的值。可表示的最大 Unix 时间戳是 2147483647,对应:
- 2038 年 1 月 19 日 03:14:07 UTC
一秒钟后,该值会溢出为 -2147483648,表示 1901 年 12 月 13 日——导致系统将当前时间解释为 20 世纪初的日期。
哪些系统会受影响?
- 采用 32 位处理器的嵌入式设备和 IoT 硬件
- 较旧的嵌入式 Linux 内核
- 使用 32 位整数时间列的旧版数据库
- 以 32 位整数存储时间的文件系统和二进制格式
解决方案
现代系统大多已过渡到使用 64 位整数 进行时间存储。64 位有符号整数可以表示从现在起约 2920 亿年 之后的时间——对任何实际用途来说都几乎是无限的。
- 64 位硬件上的大多数现代 Linux 发行版已经安全
- Linux 内核多年来一直在 64 位系统上使用 64 位 time_t
- 内核 5.6+ 为 32 位架构引入了 64 位 time_t 支持
- Python、Go 和 Java 等编程语言在内部使用 64 位整数
如果你维护嵌入式系统或旧版软件,今天就检查一下你的 time_t 大小是值得的。
UTC 及其与 Unix 时间戳的关系
Unix 时间戳本质上是与时区无关的——它们始终指向 UTC。
什么是 UTC?
协调世界时(UTC)是全球用于调节时钟和时间的主要时间标准。它取代了格林尼治标准时间(GMT)成为国际标准,并由原子钟维护。
为什么 UTC 对 Unix 时间戳很重要
- Unix 时间戳以 UTC 定义,因此一个时间戳在全球代表同一个时刻
- 将 Unix 时间戳转换为本地时间纯粹是显示层的事
- 时间戳本身不存储任何时区信息,这使得系统简单且可移植
这种设计意味着你可以与世界上任何人共享一个 Unix 时间戳,双方都可以毫无歧义地将其转换为自己的本地时间。
闰秒:罕见的例外
Unix 时间戳理论上计算自 epoch 以来的秒数,但它们忽略闰秒。即使一天增加了一秒闰秒,在 Unix 时间中仍然是恰好 86400 秒。这意味着在闰秒期间,Unix 时间戳不会前进,闰秒实际上从计数中消失了。
这种简化使系统保持实用,但也意味着 Unix 时间戳与原子时存在轻微偏差。这种偏差很小,对于日常应用几乎无关紧要。
常见时间戳范围
| 时间戳 | 人类可读日期 | 含义 | |-----------|---------------------|--------------| | 0 | 1970-01-01 00:00:00 UTC | Unix epoch | | 86400 | 1970-01-02 00:00:00 UTC | epoch 之后一天 | | 946684800 | 2000-01-01 00:00:00 UTC | 2000 年 | | 1234567890 | 2009-02-13 23:31:30 UTC | 一个容易记住的模式 | | 1785292800 | 2026-07-19 00:00:00 UTC | 今天的 epoch | | 2147483647 | 2038-01-19 03:14:07 UTC | 32 位最大值 |
总结
Unix 时间戳是一种优雅、可移植的方式,用单个整数表示时间。它的设计——从 1970 年 1 月 1 日 UTC 起计秒——使其成为操作系统、数据库和编程语言之间的通用时间标准。虽然 2038 年问题对旧版系统依然构成威胁,但向 64 位时间的持续过渡确保 Unix 时间戳将在未来几代人中继续作为计算计时的基石。
准备好使用 Unix 时间戳了吗?使用我们的 Unix 时间戳转换器 在时间戳和人类可读日期之间即时转换。