Unix 时间戳与时区速查
时间戳是秒还是毫秒、为什么要用 UTC、本地时间和时区偏移怎么换算,以及 2038 年问题到底会发生在哪些系统上。
时间戳和时区是两类问题,但经常被混在一起。时间戳回答「这是哪一刻」,与时区无关——同一时刻在全世界都是同一个时间戳;时区回答「这一刻在当地显示成几点」。把这两件事分开,很多「服务器时间和本地差 8 小时」的困惑就自然解开了。
这篇先讲时间戳本身的定义与位数识别,再给时区偏移与时间格式的对照表,最后说明 2038 年问题的来龙去脉——包括它为什么比很多人想象的影响面更小、又在哪些地方仍然是真实风险。
1Unix 时间戳的五个基本事实
时间戳的概念很简单,但有几个细节决定了它用得对不对。
- 定义
- 从 1970-01-01 00:00:00 UTC 起经过的秒数,不计闰秒
- 为什么是 1970
- Unix 系统早期约定的纪元(epoch)时间,后来成为跨平台的事实标准
- 本质是 UTC
- 时间戳不携带时区信息,同一个时间戳在任何时区指向同一时刻。显示成本地时间才需要时区
- 正数向前、负数向后
- 1970 年之前的时刻用负数表示,这也是老系统日期计算出错的原因之一
- 不是「秒」的专利
- 秒、毫秒、微秒、纳秒都是常见单位,接口间不一致是时间 bug 的头号来源
2秒 / 毫秒 / 微秒:靠位数识别
拿到一个纯数字的时间戳,第一步永远是判断单位。最实用的方法就是数位数——在当前这个年代(2020 到 2050 年前后),位数与单位的对应关系非常稳定。
| 单位 | 当前位数 | 示例 | 常见来源 |
|---|---|---|---|
| 秒(s) | 10 位 | 1759600000 | Unix 时间命令、PHP time()、Python time.time() |
| 毫秒(ms) | 13 位 | 1759600000000 | JavaScript Date.now()、Java System.currentTimeMillis() |
| 微秒(μs) | 16 位 | 1759600000000000 | Python datetime、数据库高精度时间字段 |
| 纳秒(ns) | 19 位 | 1759600000000000000 | Java System.nanoTime()、Go 的 UnixNano() |
换算关系:1 秒 = 1000 毫秒 = 1,000,000 微秒 = 1,000,000,000 纳秒。把毫秒当秒用,时间会跳到几万年之后;把秒当毫秒用,则会退回到 1970 年附近——这两个错误都极常见。
3常用时区偏移对照
时区偏移是「本地时间与 UTC 的差值」。需要留意的是,部分国家实行夏令时,同一个地区冬夏的偏移并不相同——这是跨国系统里最容易出错的地方。
| 时区 | UTC 偏移 | 说明 |
|---|---|---|
| UTC | +00:00 | 协调世界时,全球时间的基准 |
| GMT | +00:00 | 格林威治标准时间,民用场景下与 UTC 等价 |
| 中国标准时间 CST | +08:00 | 全国统一使用,不实行夏令时 |
| 日本标准时间 JST | +09:00 | 不实行夏令时 |
| 韩国标准时间 KST | +09:00 | 与日本同偏移 |
| 印度标准时间 IST | +05:30 | 半小时偏移,注意不是整点 |
| 美国东部时间 ET | −05:00 / −04:00 | 实行夏令时,冬夏偏移不同 |
| 欧洲中部时间 CET | +01:00 / +02:00 | 实行夏令时,冬夏偏移不同 |
写代码时的好习惯:内部一律用 UTC 存储与传输,只在「展示给用户」的最后一步转成本地时间。中国全年 UTC+8 不实行夏令时,处理起来反而简单;一旦涉及欧美,务必用带时区数据库的库(如各语言的标准时区库)而不是手工加减小时数。
4四种常见时间格式对照
同是一个时刻,不同场景会用完全不同的写法。跨系统传输时优先选带时区信息的格式,避免「无时区的日期字符串被不同系统理解成不同时刻」。
| 格式 | 示例 | 出处与说明 |
|---|---|---|
| Unix 时间戳 | 1759600000 | 系统内部与接口传输,最紧凑、无歧义 |
| ISO 8601 | 2026-10-05T08:00:00Z | 国际标准,结尾 Z 表示 UTC;带偏移写 +08:00 |
| RFC 7231 | Sun, 05 Oct 2026 08:00:00 GMT | HTTP 响应头 Date、Expires 使用 |
| RFC 2822 | Sun, 05 Oct 2026 08:00:00 +0800 | 邮件头使用 |
| 本地日期字符串 | 2026-10-05 | 面向用户展示;无时区信息,跨系统慎用 |
特别注意「无时区的日期字符串」:`2026-10-05` 这类不带时间与时区的写法,在不同系统里可能被解释为当地零点,也可能被解释为 UTC 零点,两者相差最多一整天。跨时区传输时一律改用 ISO 8601 带偏移的写法,或直接传时间戳。
52038 年问题:会发生什么,谁受影响
这是一个「成因简单、影响面被普遍高估、但确实还没完全解决」的经典问题。理解它的关键是把「32 位存储」这个前提看清楚。
- 成因
- 用 32 位有符号整数存储秒级时间戳时,能表示的最大值是 2147483647,对应 2038-01-19 03:14:07 UTC
- 溢出的后果
- 再加 1 秒就会翻成负数,时间回退到 1901 年附近。任何基于时间的比较、排序、过期判断都会失效
- 为什么影响面比想象的小
- 64 位系统与主流语言的新版本早已改用 64 位整数,能表示到约 2920 亿年之后,覆盖范围足够
- 仍然真实存在的风险
- 嵌入式设备与固件、老版本的操作系统、以 32 位整数存时间的数据库字段与协议格式、长期不升级的工业软件
- 更容易忽视的一点
- 溢出不是只在 2038 年发生:只要用 32 位秒存储,任何计算超出这个范围都会立刻溢出,例如「当前时间加 30 年」这类运算
- 应对方式
- 新系统一律用 64 位存储;存量系统盘查所有用 int32 存时间的字段与变量,尤其是数据库的 timestamp 类型与自定义二进制协议
看完就能用的站内工具
全部工具总览 →时间戳转换是一款免费的在线Unix时间戳与日期时间互转工具,支持毫秒级精度和多种日期格式
输入北京时间或UTC时间,快速换算全球主要城市时间,支持夏令时,纯浏览器本地计算
世界时钟 - 同时查看多个城市当前时间,跨国沟通必备
在线对指定日期时间进行加减计算,支持年、月、周、天、小时、分钟、秒,并给出结果星期与相差天数
在线日期计算器:计算两日期相差天数与工作日、年/月/日精确分解;日期加减支持天/周/月/年及仅工作日推算;可查年龄(精确到岁/月/日)、生肖、星座,以及今天是第几周第几天
关于「Unix 时间戳与时区速查」的常见问题
怎么判断一个时间戳是秒还是毫秒?
最直接的方法是数位数:10 位是秒,13 位是毫秒,16 位是微秒,19 位是纳秒。这个规则在当前年代(约 2001 到 2286 年之间)都成立。另一个辅助判断是看结果合不合理——把 13 位数字当秒解释,会得到几万年之后的日期;把 10 位当毫秒解释,则会回到 1970 年附近。实际对接接口时,最好直接看文档或响应字段名(如 timestamp 与 timestamp_ms)。
时间戳需要存时区吗?
时间戳本身不需要——它记录的是一个绝对时刻,与时区无关,同一时刻在全球都是同一个值。需要时区的场景是「显示」:要把它渲染成用户看得懂的时间,就必须知道目标时区。所以正确的做法是存储用 UTC 时间戳(或带时区的 ISO 8601),展示时再按用户所在时区转换。反过来,把「无时区的日期字符串」存进数据库,才是真正会引发跨时区歧义的做法。
为什么服务器返回的时间和本地差了 8 小时?
大概率是某一端把 UTC 当成了本地时间。常见情形有三:后端返回的是 UTC 时间字符串但没带时区标记,前端直接按本地时间渲染,于是少了 8 小时;服务器系统时区配置为 UTC 而应用按本地时区处理;数据库存的是 UTC 但读取时按本地时间解释。排查方法是打印出原始值,确认它是时间戳、带偏移的 ISO 字符串,还是不含时区的裸字符串——歧义基本都出在第三种。
2038 年问题需要担心吗?
对绝大多数 Web 应用与个人电脑来说不需要——64 位系统与主流语言早已改用 64 位整数存储时间,覆盖范围远超 2038 年。但有三个领域要留神:嵌入式设备与固件(更新周期极长)、以 32 位整数存时间的数据库字段和二进制协议、以及长期不升级的老系统与工业软件。另外提醒一点:真正的溢出并不只发生在 2038 年那一刻,任何超过 32 位范围的运算(比如给当前时间加 30 年)都会立刻出错。
继续查:相关内容
全部速查 →内容说明:本页速查数据由本站自行整理,事实性内容以对应官方规范与文档为准,未复制第三方速查表或百科的表述。数据最后核对日期:2026-10-05。若发现错误或已更新的标准,欢迎通过页脚反馈入口告知。
速查在线工具箱