Unix 时间戳是什么:10 位、13 位与毫秒陷阱

看日志时遇到一串 1770000000,接口返回的 createdAt: 1770000000000,这些数字到底指哪一天?时间戳是所有系统对「时间」的通用语言,搞清它的三个规则,排查问题能省一半时间。

一、定义:从 1970 年起的秒数

Unix 时间戳 = 从 1970 年 1 月 1 日 00:00:00 UTC 起经过的秒数,不考虑闰秒。这个起点叫「纪元(Epoch)」。几个锚点帮你建立直觉:

时间戳对应 UTC 时间
01970-01-01 00:00:00
10000000002001-09-09 01:46:40
17700000002026-02-02 03:20:00
20000000002033-05-18 03:33:20

换算成北京时间(UTC+8)就在上面基础上加 8 小时,例如 1770000000 对应北京时间 2026-02-02 11:20:00。

二、10 位还是 13 位:最大的一号坑

同一个时刻有两种常见表达:10 位是秒,13 位是毫秒。JavaScript 的 Date.now() 返回毫秒,很多后端和数据库用秒。混用的典型症状是「时间显示在 1970 年」——把 13 位毫秒值当秒去解析,得到的是 1970 年 1 月的某一天;反过来把 10 位秒值当毫秒解析,得到的是 1970 年 1 月 20 日左右。看到「1970 年」先检查位数,十有八九是这个问题。

互转规则:秒转毫秒 ×1000,毫秒转秒 ÷1000(截断小数)。

三、时区:时间戳本身没有时区

时间戳是「绝对时间」,不随时区变化——北京 2026-02-02 11:20:00 和伦敦 2026-02-02 03:20:00 是同一个时间戳 1770000000。会变的是「格式化显示」。这带来两个实践原则:

  1. 存储与传输一律用时间戳或带时区的 ISO 8601(如 2026-02-02T11:20:00+08:00),只在展示层转本地时区;
  2. 不要用字符串「2026-02-02」直接 new Date() 跨时区解析——不同浏览器对无时区字符串的解析口径不一致,有的按 UTC 有的按本地,精确到秒的场景就会差 8 小时。

四、常见语言里的一行操作对照

实际干活时最常用的就这几行,记下来贴在手边:

排查线上问题时,先用本站工具把可疑时间戳转成两个时区的时间对照看,比改代码试错快得多。

⏱️ 时间戳转换:双向转换秒/毫秒时间戳与人类时间,自动识别当前本地时区,粘贴即查,调试日志必备。

五、接口对接时的三个约定习惯

  1. 文档里写清单位:「timestamp(秒)」这五个字值一个工作日。前后端对接时间字段,单位、时区两件事在接口文档里必须明写;
  2. 前端不做时区运算:前端只负责展示,把时间戳交给成熟的格式化函数处理。手写「+8 小时」的计算,迟早撞上夏令时或历史时区变更;
  3. 测试用三个特殊值:0(纪元起点)、闰年 2 月 29 日、年底最后一秒——日期逻辑的 Bug 十有八九藏在这三个边界上,测试用例常备。

顺带记住两个「远未来」锚点:2147483647 是 32 位整数的尽头(2038 年),9999999999 秒是 2286 年。日志里见到 22 开头的 10 位数时间戳,多半是单位又搞混了。

常见问题

问:2038 年问题是什么?
32 位有符号整数最大只能表示 2147483647 秒(2038-01-19),超过会溢出。现代 64 位系统已无此问题,但老嵌入式设备仍需注意。

问:为什么日志里的时间戳和我对不上一个小时?
大概率一方用了 UTC 一方用了本地时间格式化。固定一个口径:日志记录用时间戳,查看工具统一按本地时区渲染。