什么是 Unix 时间戳?开发者必知的时间表示法

TimeKit ·
#Unix时间戳#Epoch时间#开发者工具#时间戳转换

什么是 Unix 时间戳

Unix 时间戳(Unix Timestamp),也叫 Epoch 时间或 POSIX 时间,是一个简单的数字:从 1970 年 1 月 1 日 00:00:00 UTC 到某个时刻所经过的秒数

举个例子:

  • 0 = 1970-01-01 00:00:00 UTC
  • 1719014400 = 2024-06-22 00:00:00 UTC
  • 1735689600 = 2025-01-01 00:00:00 UTC

这个”1970 年 1 月 1 日”被称为 Unix 纪元(Unix Epoch),是 Unix 操作系统设计时选定的起点。为什么选这个日期?没有特别的技术原因——当时 Unix 开发者觉得这个日期”差不多就行”,它就成为了事实标准。

关键特性:Unix 时间戳永远是 UTC,不受时区影响。无论你在北京、纽约还是伦敦,同一时刻的 Unix 时间戳是同一个数字。这就是它最大的价值——一个全球统一的时间参照系。

为什么用 Unix 时间戳

无歧义

“2024-06-22 08:00”是北京时间还是 UTC?没有时区标注就无法确定。而 1719014400 永远指向同一个瞬间,不存在歧义。

便于存储和比较

时间戳是一个整数,数据库存储、索引、比较都非常高效。比较两个时间先后,就是比较两个数字大小——比解析日期字符串快几个数量级。

跨系统兼容

几乎所有编程语言和数据库都原生支持 Unix 时间戳。无论前端用 JavaScript、后端用 Python、数据库用 PostgreSQL,时间戳都是通用的交换格式。

便于计算时间差

两个时间戳相减,直接得到秒数差。不需要处理月份天数不同、闰年、时区等复杂问题。

秒 vs 毫秒

这是一个让很多开发者踩坑的区别:

  • 大多数系统和 API 使用秒:Linux 内核、Python time.time()、C time() 函数返回的都是秒级时间戳
  • JavaScript 使用毫秒Date.now()new Date().getTime() 返回的是毫秒级时间戳

这意味着同一个时刻:

  • Python:1719014400(秒)
  • JavaScript:1719014400000(毫秒)

如果你把 JavaScript 的毫秒时间戳直接传给一个期望秒的 API,时间会跑到遥远的未来(54000 年左右)。反过来,把秒级时间戳传给 JavaScript 的 new Date(),你会得到 1970 年的某个时刻。

经验法则:时间戳如果是 10 位数字,是秒;13 位数字,是毫秒。看到时间戳先数位数,再决定怎么用。

常见陷阱

2038 年问题

32 位有符号整数的最大值是 2,147,483,647,对应的时间是 2038 年 1 月 19 日 03:14:07 UTC。超过这个时间,32 位时间戳会溢出变成负数,系统会认为时间回到了 1901 年。

这不是假设——很多嵌入式系统、旧版 Linux 服务器仍在使用 32 位时间戳。解决方法是迁移到 64 位时间戳,现代系统已经基本完成迁移,但遗留系统的风险依然存在。

时区混淆

时间戳本身是 UTC,但人类阅读时需要转换成本地时间。常见错误:

  • 从时间戳转成本地时间时,忘了应用时区偏移
  • 在数据库里存了时间戳,但查询时用了错误的时区参数
  • 前后端时区不一致,导致显示的时间差了几小时

最佳实践:后端永远存 UTC 时间戳,前端根据用户时区渲染。不要在数据库里存”本地时间”。

闰秒

国际地球自转和参考系统服务(IERS)偶尔会插入闰秒,让 UTC 与地球自转保持同步。Unix 时间戳的处理方式是重复某一秒——闰秒发生时,同一秒的时间戳出现两次。

这意味着时间戳在闰秒时刻不是严格递增的。大多数应用可以忽略这个问题,但高精度计时系统(金融交易、科学实验)必须处理。

如何转换时间戳

用代码转换

各语言的标准库都支持时间戳转换:

  • JavaScriptnew Date(1719014400 * 1000) (注意乘以 1000 转毫秒)
  • Pythondatetime.fromtimestamp(1719014400)
  • Gotime.Unix(1719014400, 0)
  • JavaInstant.ofEpochSecond(1719014400)

用在线工具转换

开发调试时,打开终端写代码太重了。TimeKit 的时间戳转换器/zh/epoch-converter)可以直接互转:

  • 输入时间戳,立刻显示对应的 UTC 时间和本地时间
  • 输入日期时间,立刻显示对应的 Unix 时间戳(秒和毫秒都有)
  • 支持当前时间戳实时显示,方便对照

实际例子

API 调试

后端返回 "created_at": 1719014400,你需要确认这个时间对不对。打开时间戳转换器,输入 1719014400,看到是 2024-06-22 00:00:00 UTC,换算到北京时间就是 08:00——符合预期。

日志分析

服务器日志里的时间都是时间戳格式:[1719014400] ERROR: connection timeout。你需要知道这是什么时候发生的。快速转换后定位到具体时间,才能和用户反馈的问题时间点对上。

数据库查询

SELECT * FROM orders WHERE created_at > 1719014400——用时间戳做范围查询,比用日期字符串高效得多,而且不受时区设置影响。

时间戳是开发者日常打交道最多的时间格式。理解它的原理和陷阱,能帮你避免大量调试时间。下次看到一串 10 位数字,先数位数,再打开转换器确认——这习惯能省很多麻烦。