时间相关的 bug 有个共性:不会立刻炸,而是在报表对不上、定时任务早跑一小时、订单时间显示成明天的时候才被发现。而排查时间问题,九成落在两件事上:单位搞错了,和时区理解错了。
拿到一串数字先丢进时间转换器看一眼它到底是哪一天,比在脑子里推算靠谱。
一、10 位还是 13 位
Unix 时间戳的定义是「从 1970-01-01 00:00:00 UTC 起经过的秒数」。
- 10 位是秒。后端语言(Java 的
System.currentTimeMillis()/1000、Go 的Unix()、PHP 的time())和数据库常用。 - 13 位是毫秒。JavaScript 的
Date.now()、Java 的System.currentTimeMillis()是毫秒。
一个好记的判据:当前时间戳的秒数是 10 位(约 17 亿),要涨到 11 位得等到 2286 年。所以看位数就能判断单位,不用记具体数值。
搞错单位的后果很直观:把秒当毫秒解析,1762000000 会变成 1970 年 1 月 21 日;把毫秒当秒解析,会算到公元 57000 多年。看到「1970 年」或者「五万年后」这种结果,先怀疑单位。
还有 16 位和 19 位的:微秒和纳秒,常见于 Prometheus、ClickHouse、某些日志系统。转换前先除到毫秒。
二、时间戳本身没有时区
这是最值得先纠正的一个误解。
时间戳是一个绝对时刻,全世界同一瞬间的时间戳完全相同。时区只在「把时间戳显示成人类可读的年月日」这一步才介入。北京的 2026-09-06 12:00 和伦敦的 2026-09-06 04:00(夏令时)对应同一个时间戳。
所以:
- 存储和传输用时间戳,不会有时区歧义;
- 存储用「2026-09-06 12:00:00」这种字符串就一定有歧义,因为它没说是哪个时区的 12 点;
- 数据库里如果用了不带时区的
datetime类型,那么这个值属于哪个时区取决于写入它的那台服务器的配置——服务器迁移或者容器时区不一致时,历史数据就再也说不清了。
「差 8 小时」几乎总是同一个原因:某一环节把中国时间的字符串当成了 UTC 来解析,或者反过来。
三、JavaScript 里那个坑
同样是解析日期字符串,横杠和斜杠的结果不一样:
new Date('2026-09-06') 按 UTC 零点解析
new Date('2026-09-06T00:00:00') 按本地时区解析
new Date('2026/09/06') 按本地时区解析
第一行是 ISO 8601 的纯日期形式,规范要求按 UTC 处理。在东八区,它得到的是北京时间 09-06 08:00。如果你的业务逻辑是「今天零点」,用这行代码就整体偏了 8 小时。
规避方式很简单:任何要跨系统传递的时间,都带上时区偏移。
2026-09-06T12:00:00+08:00 明确东八区
2026-09-06T04:00:00Z 明确 UTC,Z 就是 +00:00
写全的字符串在所有语言、所有环境下解析结果一致,这是 ISO 8601 存在的意义。
四、几个实际场景的取舍
接口传时间:传时间戳(毫秒),或者传带偏移的 ISO 8601 字符串。别传 "2026-09-06 12:00:00"。
前端展示:拿到时间戳后用当前浏览器时区格式化,用户看到的就是他本地的时间。跨国业务如果需要显示「活动按北京时间几点开始」,必须显式指定时区,不能依赖用户本地时区。
日志排查:日志时间戳建议统一用 UTC 落盘,查询时再转换。多机房、多时区部署时,混用本地时间的日志根本没法按时间排序。
数据库:MySQL 的 timestamp 会做时区转换、datetime 不会;PostgreSQL 的 timestamptz 存的是绝对时刻。选型时想清楚要不要时区语义,不要靠默认。
定时任务:Cron 表达式没有时区概念,跑在哪台机器就用哪台机器的时区。写完表达式建议用 Cron 表达式解析看一下最近几次的执行时间是否符合预期——0 0 * * * 这种「每天零点」在服务器时区是 UTC 时,实际执行是北京时间早上 8 点。
五、2038 年问题
用 32 位有符号整数存秒级时间戳,上限是 2147483647,对应 2038-01-19 03:14:07 UTC,再加一秒会溢出成负数、回到 1901 年。
现在还需要关心它的场景:
- 老系统里用
int存时间戳的数据库字段; - 32 位嵌入式设备、老旧路由器;
- 业务上要计算 2038 年以后的日期,比如 30 年期房贷的还款计划表、长期合同到期日。
64 位系统和 bigint 字段没有这个问题。但字段类型是 int 的话,用的是 64 位服务器也照样溢出——限制在存储层,不在 CPU。
常见问题
闰秒会影响时间戳吗? Unix 时间戳的定义假设每天恰好 86400 秒,不包含闰秒。闰秒发生时系统通常靠 NTP 平滑校正,对业务代码基本无感。国际计量大会已决定在 2035 年前取消闰秒。
为什么两个系统的时间戳差几秒? 机器时钟漂移,正常现象。分布式场景下不要用「本机时间」做严格的先后判断,跨机器比较时间需要时钟同步(NTP)甚至逻辑时钟。
时间戳能表示 1970 年之前的日期吗? 可以,用负数。但很多语言的库和数据库对负时间戳支持不一致,处理历史日期(出生日期、历史事件)建议直接存日期字符串。
夏令时怎么处理? 中国大陆从 1992 年起不用夏令时。涉及欧美时区的业务不要自己加减小时数,必须用带时区数据库(IANA tzdata)的日期库,因为夏令时的切换规则每年可能调整。
转换过程会上传数据吗? 不会。时间转换、Cron 解析都在浏览器本地完成,日志片段和业务时间不会离开你的设备。