想知道某件事到底发生在什么时候,不用在脑子里做时间戳算术。把值粘进来,选好你关心的那个时区,剩下的交给转换器。
真正要留意的是:你手里这个数到底是什么单位。Unix 时间戳通常指纪元以来的秒数,但在 JavaScript 里它往往是毫秒。两者描述的是同一类瞬间,可是少了或多了三个零,一件平平无奇的 2026 年的事就被送回了 1970 年。
从你手里的那个值开始
方向明确的话,直接用下面这几个工具:
- Epoch 转日期:把 Unix 时间戳变成能读的日期。
- 日期转 Epoch:把日期、时间和时区变成 Unix 秒或毫秒。
- Unix 时间戳速查:常用的当前时刻、日/周/月/年边界时间戳。
- 时区转换器:瞬间已经确定,只是需要换个时区来显示。
上方的实时时钟也很顺手:给 Unix 风格的接口用就复制秒,给 JavaScript 和浏览器端代码用就复制毫秒。
Unix 时间戳到底是什么
Unix 时间是从纪元开始计的秒数,纪元定义为 1970-01-01 00:00:00 UTC。这个数字是 UTC 时间轴上的一个点,它本身不携带时区、语言环境或显示格式。
正因为分得这么干净,时间戳在系统之间传递才特别省心。新加坡的服务器、法兰克福的数据库、芝加哥的笔记本可以持有同一个整数,并且对它代表的那个事件毫无分歧。至于显示,各自按本地时间来就好,事件发生的那一刻不会因此改变。
Unix 时间不计闰秒。做应用开发时这通常正是你想要的:它和操作系统、数据库、日志、API 所遵循的 POSIX 惯例保持一致。
秒还是毫秒:三个零的坑
大多数命令行工具、数据库函数和写着 “Unix timestamp” 的接口字段,指的都是秒;而 JavaScript 的 Date.now() 返回的是毫秒。两个值看上去都挺合理——这正是这个 bug 如此常见的原因。
| 值 | 单位 | 对应的同一瞬间 |
|---|---|---|
1700000000 |
Unix 秒 | 2023-11-14T22:13:20Z |
1700000000000 |
Epoch 毫秒 | 2023-11-14T22:13:20.000Z |
对于当代的日期,位数是个好用的第一判断:
- 10 位基本就是 Unix 秒。
- 13 位多半是 JavaScript 风格的 epoch 毫秒。
本站的转换器就是靠这个经验规则加快日常转换的。但它只是便利,不是铁律。归档记录、故意设得很远的未来测试日期,或者从某个用微秒的系统里复制出来的值,都需要你明确指定单位。当接口文档写明某个字段是秒或毫秒时,相信文档,别相信位数。
写成代码,这件事无聊得恰到好处:
const seconds = 1700000000;
const milliseconds = seconds * 1000;
new Date(milliseconds).toISOString();
// "2023-11-14T22:13:20.000Z"
反方向就是除以一千。只有当接收方要求整数秒时,才需要 Math.floor()。
把 epoch 值转成日期
日志、webhook、数据库记录或接口响应里给了你一个时间戳,那就从 Epoch 转日期开始。转换器会给出:
- ISO 8601 格式的 UTC 字符串,适合日志和接口;
- UTC 日期和时间,方便跨系统比对;
- 你选定时区下的可读日期;
- 一句相对时间描述,快速建立直观感受。
比如 1700000000 就是 2023-11-14T22:13:20Z。换个显示时区,钟面时间会变,时间戳不会变。可以把时间戳想成地图上的那枚图钉,时区只是旁边贴的标签。
把日期和时间转成 Unix 时间
反过来做,多出一个必须回答的问题:这个时间是哪个时区的?
“6 月 20 日上午 9:25” 在配上时区之前不是一个确定的瞬间。它可能是 09:25Z,可能是纽约的上午 9:25,也可能是东京的上午 9:25——三个完全不同的时刻。切到 日期 → Epoch 标签页,填入日历日期、时间和 IANA 时区,点转换,然后复制结果。
这件事在定时任务、活动报名、账单截止和提醒功能里尤其要紧,在夏令时切换的当口更是如此——那时候某个本地钟面时间可能出现两次,也可能根本不存在。事件本身存转换出来的时间戳;如果这个日程是按当地钟面时间定义的,那就把 IANA 时区名一起存下来。
UTC、本地时间和具名时区
技术场景下最安全的通用显示方式是 UTC,因为它让每个读者面对同一块钟。ISO 8601 字符串结尾带 Z 的就是 UTC:
比如:
2026-06-20T09:25:00Z
但面向用户的输出,最好选一个 IANA 时区名,比如 America/New_York、Europe/London 或 Asia/Tokyo。IANA 名字优于 -05:00 这样的固定偏移,因为它会自动跟随当地的夏令时规则。
有个习惯能挡掉出乎意料多的事故:在服务端渲染的页面、定时邮件、截图和测试里,把时区显式写出来。否则运行时会拿它自己的本地时区来解释——还是同一个瞬间,只是你的服务器决定换一块钟来读它。
比秒更细的精度
日常用的是秒和毫秒,但有些系统会用更小的单位:
| 单位 | 常见场景 | 说明 |
|---|---|---|
| 秒 | Unix 接口、JWT claims、shell 工具 | 经典的 Unix 时间戳 |
| 毫秒 | JavaScript、浏览器事件、大量 Web API | Date.now() 返回的就是这个 |
| 微秒 | 部分数据库和链路追踪系统 | 最好确认一下字段约定 |
| 纳秒 | 高精度运行时与测量场景 | 通常需要 BigInt 或字符串承载 |
看到 16 位或 19 位的数字,别当成不言自明。它可能是 Unix 纪元以来的微秒或纳秒,也可能压根用的是另一个纪元。Chrome / WebKit 时间戳、.NET ticks 以及好几种数据库格式都有各自的起算日。单位和纪元是绑在一起的,得一起确认。
还有一点:如果你要测的是“过了多久”,而不是记录“什么时候发生”,请用单调时钟——浏览器和 Node.js 里是 performance.now()。墙上时钟是可以被校准的,而经过的时间不该因为机器纠正了自己就往回跳。
2038 年这道坎
时间戳最有名的边界情况就是 2038 年问题。有符号 32 位整数最多能装 2147483647 秒,也就是:
2038-01-19T03:14:07Z
还在用这种表示的软件,会在下一秒溢出。现代平台大多换成了更宽的时间类型,但老的文件格式、上了年纪的嵌入式设备和兼容层仍然可能受制于此。如果你的系统数据保留期很长,或者要和老系统对接,现在就拿这个边界附近的日期测一测(而不是等到 2038 年,那时候大家都忙着假装自己早就料到了)。
常用时间戳速查
下面这些值适合写测试、翻日志或者做个快速自检,均以 UTC 显示。
| Unix 秒 | ISO 8601 UTC | 为什么会用到 |
|---|---|---|
0 |
1970-01-01T00:00:00Z |
Unix 纪元本身 |
86400 |
1970-01-02T00:00:00Z |
纪元之后一天 |
1000000000 |
2001-09-09T01:46:40Z |
第一个 10 位里程碑 |
1700000000 |
2023-11-14T22:13:20Z |
顺手的当代示例 |
2147483647 |
2038-01-19T03:14:07Z |
有符号 32 位上限 |
一套靠谱的时间戳工作流
碰到不认识的时间值,别靠眼力猜。按下面四点过一遍:
- 纪元: 零点对应的是哪一天?
- 单位: 这个值是秒、毫秒、微秒还是纳秒?
- 时区: 输入的是一个确定瞬间,还是一个需要配时区才成立的本地日期时间?
- 输出约定: 下游系统要什么——数字还是 ISO 8601 字符串?秒还是毫秒?
这四个答案一清楚,转时间戳就是例行公事。算术交给转换器,你只需要在交接的边界上守住含义不走样。
Frequent questions:
- Q: 我该用哪个转换器?
- A: 手里已经有时间戳、想看懂它是哪一天,用 Epoch 转日期;反过来,手里是日历日期和时间、需要得到 Unix 秒或毫秒,用日期转 Epoch。
- Q: 转换器能同时认秒和毫秒吗?
- A: 可以。它按数值大小自动判断:常见的秒级时间戳一般是 10 位,毫秒级一般是 13 位。但如果是很久以前或者很遥远的未来的日期,最好先确认单位再转。
- Q: 怎么把 Unix 时间戳转成可读日期?
- A: 切到「Epoch → 日期」标签页,粘贴时间戳,选好时区,点转换。结果里会同时给出 ISO 8601、UTC 字符串和适合人看的本地格式。
- Q: 怎么把日期或时间转成 Unix 时间戳?
- A: 切到「日期 → Epoch」标签页,填入日期、时间和时区,然后按秒或毫秒复制结果。
- Q: Unix 时间和 UTC 有什么区别?
- A: Unix 时间是从纪元 1970-01-01T00:00:00Z 开始计数的一个数字,而定义这个起点的时间标准是 UTC。时间戳本身是时间轴上的一个确定瞬间,时区只影响它被显示成什么样子。
- Q: 毫秒怎么换算成秒?
- A: 除以 1000。如果对方接口要的是整数秒,JavaScript 里用 Math.floor(milliseconds / 1000)。反过来,秒乘 1000 就是毫秒。
- Q: Unix 时间戳可以是负数吗?
- A: 可以。负值表示 1970-01-01T00:00:00Z 之前的瞬间。比如 -86400 就是 1969-12-31T00:00:00Z。
- Q: 什么是 2038 年问题?
- A: 如果程序用有符号 32 位整数存 Unix 秒,它就表示不了 2038-01-19T03:14:07Z 之后的时间。现在的系统大多改用了更宽的类型,但老旧的嵌入式设备和历史遗留代码仍然值得排查一遍。