什么是 Unix 时间戳?开发者必知的时间表示法
什么是 Unix 时间戳
Unix 时间戳(Unix Timestamp),也叫 Epoch 时间或 POSIX 时间,是一个简单的数字:从 1970 年 1 月 1 日 00:00:00 UTC 到某个时刻所经过的秒数。
举个例子:
0= 1970-01-01 00:00:00 UTC1719014400= 2024-06-22 00:00:00 UTC1735689600= 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()、Ctime()函数返回的都是秒级时间戳 - 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 时间戳的处理方式是重复某一秒——闰秒发生时,同一秒的时间戳出现两次。
这意味着时间戳在闰秒时刻不是严格递增的。大多数应用可以忽略这个问题,但高精度计时系统(金融交易、科学实验)必须处理。
如何转换时间戳
用代码转换
各语言的标准库都支持时间戳转换:
- JavaScript:
new Date(1719014400 * 1000)(注意乘以 1000 转毫秒) - Python:
datetime.fromtimestamp(1719014400) - Go:
time.Unix(1719014400, 0) - Java:
Instant.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 位数字,先数位数,再打开转换器确认——这习惯能省很多麻烦。