免费 Unix 时间戳转换器

在 Unix 时间戳和人类可读日期之间转换。

数据不会离开您的设备
当前 Unix 时间戳

时间戳 → 日期

日期 → 时间戳

什么是 Unix 时间戳?

Unix 时间戳(也称为纪元时间或 POSIX 时间)是自 1970 年 1 月 1 日 00:00:00 UTC 以来经过的秒数。它是一种简单、与时区无关的表示时间点的方式,广泛用于编程、数据库、API 和服务器日志。

例如,时间戳 1700000000 表示 2023 年 11 月 14 日 UTC 时间 22:13:20。JavaScript 使用毫秒时间戳(乘以 1000),而大多数其他语言和 API 使用秒。

常见问题

我可以输入哪些日期格式?

您可以以大多数标准格式输入日期:ISO 8601(2025-12-31T23:59:59Z)、常见日期字符串(Dec 31, 2025 11:59 PM)或简单格式如 2025-12-31 23:59:59。转换器使用浏览器内置的日期解析器。

它能自动检测秒与毫秒吗?

是的。如果时间戳大于 1 万亿,转换器会将其视为毫秒。否则,将其视为秒。两种格式都会显示在结果表中。

什么是 2038 年问题?

将 Unix 时间戳存储为 32 位有符号整数的系统将在 2038 年 1 月 19 日 UTC 时间 03:14:07 发生溢出。现代系统使用 64 位整数,可以表示未来数十亿年的日期。此工具使用 JavaScript 的 Number 类型,可以很好地处理 2038 年以后的时间戳。

为什么是 1970 年 1 月 1 日?

Unix 时间戳是自 Unix 纪元(1970 年 1 月 1 日(星期四)00:00:00 UTC 以来流逝的秒数的整数计数。它是一个独立的标量,能无歧义地命名时间中的一个瞬间,与日历无关、与时区无关)同一个数字无论你在东京还是多伦多,命名的都是同一瞬间。

选择 1970 多少有点随意,但并非完全随机。UNIX Programmer's Manual 第一版(1971 年 11 月)将系统时间定义为自 1971-01-01 起按 60 Hz 时钟节拍数。用 32 位无符号整数以 60 Hz 计数,系统在大约 2.26 年之后就会溢出,这个问题很快显而易见。1972 年准备第二版时,Ken Thompson 和 Dennis Ritchie 的团队改为从 1970-01-01 起按计数:32 位有符号整数以秒为单位可以维持大约 68 年,远远超出写代码的工程师们的工作生涯,并且工程开始之前最近的元旦让算术更简单。没有委员会投票,也没有 IANA 式的标准化流程。这个选择就此沿用下来,因为 Unix 是这样发布的,而一旦有一亿台机器都从那一刻开始计数,任何替代方案都不再可行。

POSIX(1988)把 1970 纪元写进了 IEEE Std 1003.1 中「Seconds Since the Epoch」一节。今天,同一个纪元支撑着 C/C++ time_t、Python time.time()、Ruby Time.now.to_i、JavaScript 与 Java(以毫秒为单位,见下文)、Linux/macOS 文件系统时间戳、Bitcoin 与 Ethereum 区块头部,以及 JWT iat/exp/nbf 声明。少数系统使用偏移纪元(Windows FILETIME 从 1601-01-01 起按 100 纳秒数刻度计数,.NET DateTime 从 0001-01-01 起按刻度计数),但凡是跨越操作系统或语言边界的事物,Unix 时间都是通用语。

秒还是毫秒,最常见的 bug

POSIX 把时间戳定义为自纪元以来的秒数。每一个 C 库、每一个 Python 解释器、每一个 Ruby/Go/Rust/Elixir 运行时返回的都是秒。JavaScript 是众所周知的例外Date.now()new Date().getTime() 返回的是毫秒。Java 的 System.currentTimeMillis() 遵循同样的约定,几个较新的数据库系统(例如 MongoDB BSON 的 Date 类型)也存储毫秒。

结果就是一个长期存在的跨语言 bug:一个 Go 后端把 1700000000(秒)写入 JSON 字段;Node.js 客户端把它传入 new Date(1700000000),但 JavaScript 期望毫秒,于是得到的日期是 1970-01-20,而不是 2023 年末。修复办法是 new Date(1700000000 * 1000)。反过来,把 JS 的毫秒时间戳塞进 Python 的 datetime.fromtimestamp() 会得到大约 55895 年。Stack Overflow 上数十个变体问到「JavaScript Date 显示 1970」,根因绝大多数情况下就是这种错配。

本转换器采用了一个启发式:如果输入大于 1,000,000,000,000,就当作毫秒;否则当作秒。这样可行,是因为 1e12 秒会到公元 33658 年(远远超过任何真实世界中以秒为单位的输入),而 1e12 毫秒是 2001 年 9 月 9 日 UTC(在现代范围之内)。一些科学系统和 Linux 内核 API 使用的微秒/纳秒时间戳会把门槛进一步抬高,对这些请显式指定精度。

2038 年问题(「Y2K38」)

32 位有符号整数能存储 −2,147,483,648 到 +2,147,483,647 之间的值。如果把它解释为自 1970-01-01 UTC 起的秒数,可表示的最大时刻是 2038 年 1 月 19 日(星期二)03:14:07 UTC。再过一秒,计数器溢出并回卷到最小负值,解码为 1901 年 12 月 13 日(星期五)20:45:52 UTC。任何 32 位宽的 time_t、任何用 4 字节有符号整数存储时间的数据库列、任何固件大致在 2010 年之前写成的嵌入式系统,都存在风险。

暴露面令人不安:今天仍在安装、生命周期 15-30 年的工业 PLC 和 SCADA 控制器;老 MySQL TIMESTAMP 列文档已写明在 2038 边界饱和;ext3 文件系统;打包 4 字节时间戳的二进制协议格式(DNSSEC RRSIG 字段、NTPv3、若干工业现场总线);悄悄运行老旧 32 位 Linux 内核的智能电视和车机娱乐系统。主流修复方法是把 time_t 加宽到 64 位,这会把上限延伸到大约+2920 亿年,超出太阳热寂之后。Linux 5.6(2020 年 3 月)通过 Arnd Bergmann 的 y2038 补丁集为所有 32 位架构添加了 64 位时间系统调用;glibc 2.34(2021 年 8 月)通过 _TIME_BITS=64 让 64 位 time_t 可选启用;Debian 13「Trixie」(2025)是第一个完整重新编译整个 archive 的发行版。Apple 在 macOS 10.15(2019)和 iOS 11(2017)中废弃了 32 位二进制,因此消费级设备阵营实际上已免疫。

剩余的风险面绝大部分是嵌入式磁盘上的遗留数据:一个 64 位内核从遗留数据库读取 32 位时间戳列,跟数据库本身一样坏。迁移是按应用而异的数据格式问题,不仅仅是内核问题。

JavaScript Date,业界最受诅咒的 API

JavaScript 的 Date 对象是 1995 年 5 月 Brendan Eich 用 10 天写出最初的 LiveScript 期间,从 Java 1.0 整段照抄过来的。Java 自己在 JDK 1.1(1997)里弃用了 java.util.Date 的大多数方法,但 JavaScript 继承下来并且不能打破 web 兼容性,所以它们仍然在。结果是一个这样的 API:

Temporal API(TC39 自 2021 年 3 月进入 Stage 3)是现代替代品,提供 Temporal.InstantTemporal.PlainDateTemporal.PlainTimeTemporal.ZonedDateTime,以及真正的 Temporal.Duration 类型。浏览器支持正在推进(Firefox Nightly、Safari 18 部分支持,截至 2024 年的 Chrome 隐藏在 flag 后);polyfill 可用,但会增加约 25 KB。Moment.js 2020 年 9 月被维护者放入维护模式,2026 年新项目的建议是浏览器支持允许就优先用 Temporal,否则用 Luxondate-fns,不要用 Moment.js。

什么时候你会用到这个

关于闰秒的一点说明

自 1972 年以来,UTC 中已经插入了 27 次闰秒,用来让挂钟时间与地球减缓的自转保持对齐。最近一次是 2016 年 12 月 31 日 23:59:60 UTC。Unix 时间不编码闰秒,POSIX 明确表示:Unix 时间戳假装每一天都恰好有 86,400 秒。较老的 Linux 系统会「重复」最后一秒;Google 与 AWS 使用「leap smear」,把多出来的那一秒散布到 24 小时窗口里。无论哪种方式,Unix 时间在存储里都不会出现 23:59:60,而两个跨越闰秒的时间戳相减得到的结果会比真实 SI 秒经过的时间短一秒。对应用代码而言这是不可见的;对天文或金融交易软件可能有意义。2022 年 11 月,第 27 届国际计量大会(CGPM)投票决定到 2035 年停止插入闰秒,改用一次性大得多的周期性调整代替。

速查表

TimestampUTC datetimeNote
01970-01-01 00:00:00The epoch
1,000,000,0002001-09-09 01:46:40First "billion-second" milestone
1,234,567,8902009-02-13 23:31:30"Cool number" celebrated by some devs
1,700,000,0002023-11-14 22:13:20
2,000,000,0002033-05-18 03:33:20"Two billionth second"
2,147,483,6472038-01-19 03:14:07Last second representable in signed 32-bit
4,294,967,2952106-02-07 06:28:15Last representable in unsigned 32-bit (Bitcoin's nTime limit)
9,999,999,9992286-11-20 17:46:39Last 10-digit timestamp

更多问答

为什么同一个时间戳在我朋友的机器上显示的时间不一样?

因为底层数字是 UTC,而显示时会转换成本地时间。1700000000 是 22:13:20 UTC,但在纽约是 17:13:20,在悉尼则是次日 06:13:20。数字相同,只是渲染不同。要排除时区混淆,请让两台机器都以 UTC 显示。

Y2K 和 Y2K38 有什么区别?

Y2K(2000 年)是一个发生在应用代码里的逻辑问题:很多系统把年份存成两位 ASCII 数字,因此「00」在 1900 与 2000 之间出现歧义。每一个应用都要单独检查、单独打补丁;估算全球总修复支出为 3000-6000 亿美元。Y2K38 主要是底层库的数据类型问题(把 C 库和内核重新对 64 位 time_t 编译,就为所有链接它们的应用解决了一大块表面。剩下的硬骨头是磁盘上持久化的数据(数据库、文件元数据、二进制协议),它们需要数据迁移工具。常识性判断是:2038 将是比 2000 更小、更不上头条的事件)更多局部的嵌入式设备故障,更少头条级的故障停摆。

为什么 new Date('2024-03-15') 有时显示 3 月 14 日?

因为根据 ES5 标准,那个字符串被当作 UTC 午夜来解析,然后再以你的本地时区显示。在像美国太平洋时间这样的 UTC-8 时区,3 月 15 日的 UTC 午夜在本地是 3 月 14 日下午 4 点,所以 .getDate() 返回 14。现代代码的修法是要么 new Date('2024-03-15T12:00:00')(省略 Z 时 JavaScript 会把它当作本地正午),要么(更好的办法是)等 Temporal.PlainDate.from() API 上线后改用它。

会发送任何东西到服务器吗?

不会。转换是 JavaScript 算术在你的浏览器里本地完成的。关于你输入的时间戳,没有一个字节离开过页面,这在数值是客户 ID、内部日志行、或你不愿上传到任何地方的会话调试数据时很有用。页面加载后即可离线运行。

相关工具