Unix 时间戳是什么?秒和毫秒、时区和常见换算错误
看日志、调接口、查数据库时,经常能看到 1700000000 或 1700000000000 这样一长串数字,这就是 Unix 时间戳。它看起来不直观,但几乎所有编程语言和数据库都支持,是系统之间交换时间最稳妥的方式。这篇文章说明它是什么、怎么换算,以及最常见的几个坑。
一、定义:从 1970 年开始数秒
Unix 时间戳表示从 1970 年 1 月 1 日 00:00:00 UTC(称为 Unix 纪元)开始经过的秒数。例如 0 就是纪元本身,86400 是一天之后,也就是 1970-01-02 00:00:00 UTC。
关键点在于:时间戳本身没有时区。同一个时刻,在北京、伦敦、纽约算出来的时间戳是同一个数字;只有把它“显示成年月日时分秒”时,才需要指定时区。
二、10 位和 13 位:秒与毫秒
目前的秒级时间戳是 10 位数,毫秒级是 13 位数,两者相差 1000 倍。
- JavaScript 的
Date.now()、Java 的System.currentTimeMillis()返回毫秒。 - Linux 的
date +%s、PHP 的time()、MySQL 的UNIX_TIMESTAMP()返回秒。 - Python 的
time.time()返回带小数的秒,例如 1700000000.123。
最常见的 bug 就是混用:把毫秒当秒,会得到五万多年后的日期;把秒当毫秒,会得到 1970 年 1 月 20 日左右的日期。看到“1970 年”或“遥远未来”,先检查单位。
三、为什么总是差 8 小时
北京时间是 UTC+8。如果把时间戳按 UTC 显示,再当作北京时间来看,就会早 8 小时;反之就晚 8 小时。例如:
1700000000按 UTC 显示是 2023-11-14 22:13:20;- 按北京时间显示是 2023-11-15 06:13:20。
两种显示都对,只是时区不同。排查时先确认三件事:时间戳是谁生成的、用什么单位、显示时用的是哪个时区。服务器的系统时区、数据库连接的时区、前端浏览器的时区,可能各不相同。
四、各种语言里怎么换算
JavaScript:
Math.floor(Date.now() / 1000) // 当前秒级时间戳
new Date(1700000000 * 1000).toISOString() // "2023-11-14T22:13:20.000Z"
new Date(1700000000 * 1000).toLocaleString("zh-CN", {timeZone: "Asia/Shanghai"})
Python:
from datetime import datetime, timezone, timedelta
datetime.fromtimestamp(1700000000, tz=timezone.utc)
datetime.fromtimestamp(1700000000, tz=timezone(timedelta(hours=8)))
注意 Python 里不带 tz 参数时会使用运行机器的本地时区,同一段代码在不同服务器上结果可能不同,建议总是显式指定。
Linux 命令行:
date +%s # 当前时间戳
date -d @1700000000 # 按本机时区显示
TZ=UTC date -d @1700000000 # 按 UTC 显示
MySQL:SELECT FROM_UNIXTIME(1700000000); 结果受会话时区 time_zone 影响;SELECT UNIX_TIMESTAMP('2023-11-15 06:13:20'); 把日期按会话时区解释后转成秒。
五、日期转时间戳要注意什么
把“2026-10-22 15:30:00”转成时间戳时,必须先说清楚这是哪个时区的 15:30。同一个字符串,按北京时间和按 UTC 解释,得到的时间戳相差 28800 秒(8 小时)。
有夏令时的地区更复杂:例如美国东部时间夏天是 UTC−4、冬天是 UTC−5,换算时要用时区名(如 America/New_York)而不是写死偏移量,交给系统的时区数据库处理。
六、2038 年问题
如果用 32 位有符号整数保存秒级时间戳,能表示的最大时刻是 2038-01-19 03:14:07 UTC,之后会溢出变成负数。现代操作系统和主流语言已普遍使用 64 位,但一些老旧嵌入式设备、老数据库字段(比如 MySQL 的 TIMESTAMP 类型有 2038 年上限)仍可能受影响。新设计的表如果要存很远的日期,建议使用 BIGINT 或 DATETIME。
七、排查清单
- 数一数位数:10 位是秒,13 位是毫秒。
- 确认生成方和读取方使用同一个单位。
- 确认显示时用的时区,存储和传输尽量统一用 UTC 或时间戳。
- 接口文档里写清楚字段单位,例如
created_at_ms。
八、在线快速换算
临时查一个时间戳时,不必打开终端写代码。本站的 Unix 时间戳转换工具 会实时显示当前秒和毫秒时间戳,能自动识别 10 位或 13 位,支持北京时间、UTC、东京、纽约等时区,也能把日期反向转成时间戳。所有换算都在浏览器本地进行。