Unix 时间戳 10 位和 13 位的区别,以及 2038 年问题
调接口时经常看到 1731000000 和 1731000000000 两种数字,长得像但差了一千倍。搞错了就会出现"时间显示 1970 年"这种经典 bug。
定义:从 1970 年 1 月 1 日 UTC 起的秒数
Unix 时间戳(Unix Epoch Time)定义为从 1970-01-01 00:00:00 UTC 到现在的秒数。它和时区完全无关——这是它最大的优点。
10 位 vs 13 位
| 位数 | 单位 | 示例 | 常见来源 |
|---|---|---|---|
| 10 位 | 秒 | 1731000000 | PHP、Python、Shell、数据库 |
| 13 位 | 毫秒 | 1731000000000 | JavaScript Date.now()、Java、Android |
判断方法很简单:看位数。当前时间(2026 年)的秒级时间戳是 10 位,毫秒级是 13 位。所以位数 ≤ 10 当秒处理,否则当毫秒处理——这也是本站工具采用的自动识别逻辑。
注意:这个判断在 2286 年之后会失效(秒级也会变成 11 位)。不过那时候的代码大概已经重写过了。
最常见的坑:时区
时间戳本身没有时区,但显示成日期时就需要时区。同一串数字,在中国显示 2024-11-08 01:20:00,在 UTC 显示 2024-11-07 17:20:00——差了 8 小时。
典型事故:
- 服务器时区是 UTC,前端按本地时区格式化 → 用户看到的时间差 8 小时
- 数据库存的是
DATETIME而不是时间戳 → 跨时区部署时数据错乱 - 把 "2026-11-15 10:00:00" 直接当时间戳存 → 丢失时区信息
结论:存储用 UTC 时间戳,显示时再按用户时区转换。这是唯一不会出错的策略。
2038 年问题
很多系统用 32 位有符号整数存时间戳。32 位能表示的最大值是 2,147,483,647,对应 2038-01-19 03:14:07 UTC。再往后就会溢出成负数,时间跳回 1901 年。
这就是"2038 年问题",和当年的"千年虫"性质一样。现在的新系统基本都用 64 位整数,能表示到约 2920 亿年,但老设备、老数据库字段、嵌入式系统仍然有风险。
检查方法:看数据库字段类型(INT 是 32 位,BIGINT 才是 64 位),看代码里有没有 int 存时间戳。
常用命令速查
# 当前时间戳
date +%s
# 时间戳转日期(Linux)
date -d @1731000000
# 日期转时间戳
date -d "2026-11-15 16:00:00" +%s
# JavaScript
Date.now() # 毫秒
Math.floor(Date.now()/1000) # 秒
需要互相转换?
打开时间戳工具