你从接口拿到的 1729843200 是什么?为什么用工具转出来总是差 8 小时?为什么有人给的是 10 位、有人给 13 位?这篇文章把时间戳这件事讲透。
Unix 时间戳(Unix timestamp)是从 1970 年 1 月 1 日 00:00:00 UTC 到某一时刻之间经过的秒数。这个起点有个专门的名字,叫 Unix 纪元(Unix Epoch)。
比如 1729843200 表示 2024 年 10 月 25 日 16:00:00 UTC。它不是什么特殊编码,就是一个普通的整数,一直在变大。
| 对比项 | 时间戳 | 日期字符串 |
|---|---|---|
| 时区歧义 | 无(天然 UTC) | 有(2024-10-25 16:00 是哪个时区?) |
| 存储大小 | 10 位数字 | 19 字符以上 |
| 能比较大小吗 | 能,直接比数字 | 不能,得先解析 |
| 跨语言兼容 | 所有语言都能处理整数 | 格式五花八门 |
| 人能看懂吗 | 不能 | 能 |
结论很清楚:机器之间传时间戳,给人看的时候再转成日期字符串。这也是几乎所有 API 的做法。
这是最容易踩的坑。时间戳的单位有两种:
| 位数 | 单位 | 典型来源 |
|---|---|---|
| 10 位 | 秒(second) | PHP、Linux date +%s、多数后端接口 |
| 13 位 | 毫秒(millisecond) | JavaScript Date.now()、Java System.currentTimeMillis()、Android |
把 13 位当成秒来解析,会得到一个五万多年后的日期:
1729843200000 当作秒解析 → 公元 56780 年
1729843200 当作秒解析 → 2024-10-25 16:00:00 UTC ✓
反过来,把 10 位当毫秒,会得到一个 1970 年附近的日期。看到结果明显不对,先数位数。
很多老系统用 32 位有符号整数存时间戳,它能表示的最大值是 2147483647。这个数字对应的时刻是:
2038-01-19 03:14:07 UTC
即 北京时间 2038-01-19 11:14:07
过了这一秒,数值就会溢出变成负数,时间跳回 1901 年。这和传说中的“千年虫”是同一类问题。
影响范围:老版本的 32 位 Linux、嵌入式设备、用 32 位 int 的数据库字段、部分老语言运行时。现在的新系统多数已改用 64 位,理论上够用几千亿年。
因为你所在时区是 UTC+8。同一个时间戳,在不同时区换算出来的“墙上时间”不同:
时间戳 1729843200
UTC → 2024-10-25 16:00:00
北京时间 → 2024-10-26 00:00:00 (+8 小时)
时间戳本身没有问题,是“按哪个时区显示”的问题。判断方法:
全部在浏览器本地计算,不联网、不上传。
date +%s 得到秒,date +%s%3N 得到毫秒。Python:import time; int(time.time())。JavaScript:Date.now()。