找回密码
 立即注册
首页 业界区 安全 一文搞懂时刻、时间戳、时间

一文搞懂时刻、时间戳、时间

邹语彤 前天 10:20
在软件开发中,处理“时间”往往是 Bug 的高发区。你是否遇到过:数据库存的时间慢了 8 小时?跨时区系统在计算过期时间时出现偏差?前端显示的日期和后端对不上?
这些问题的根源通常在于对 时刻(Moment)时间戳(Timestamp)本地时间(Local Time) 这几个核心概念的混淆。本文将带你彻底理清这些概念。
基本概念

什么是“时刻”?

时刻(Moment) 是宇宙时间轴上的一个绝对点。
想象一下,2026年世界杯决赛进球的一瞬间,全球观众都在欢呼。对于此时此刻:

  • 伦敦的观众看到钟表指向 23:00;
  • 意大利的观众看到的是次日 00:00;
  • 北京的观众看到的是次日 07:00。
虽然各地的表盘读数不同,但这一“瞬间”在物理上是唯一的。 这种唯一性,就是我们程序逻辑中需要锁定的核心。
时间戳(Timestamp)

为了在计算机中客观地表示这个“唯一时刻”,我们引入了时间戳
时间戳(Unix Timestamp)是指从 1970年01月01日 00:00:00 UTC 起至现在的总秒数(或毫秒数)。
时间戳是一个绝对数值,它不属于任何时区。
无论你在纽约、伦敦还是北京,在同一物理时刻获取到的 Unix 时间戳一定是完全相同的。它就像一把公用的刻度尺,记录的是距离“原点”的物理距离。
如果有同事说:给你传东八的时间戳 ,那就是理解错了。
本地时间

当我们说当前时刻是2026年1月5日早上7:00的时候,我们说的实际上是本地时间。在国内就是北京时间。在这个时刻,如果地球上不同地方的人们同时看一眼手表,他们各自的本地时间是不同的:

  • 伦敦 2026-01-04 23:00:00
  • 意大利 2026-01-05 00:00:00
  • 北京 2026-01-05 07:00:00
所以,不同的时区,在同一时刻,本地时间是不同的。全球一共分为24个时区,伦敦所在的时区称为标准时区,其他时区按东/西偏移的小时区分,北京所在的时区是东八区。
时区

因为光靠本地时间还无法唯一确定一个准确的时刻,所以我们还需要给本地时间加上一个时区。时区有好几种表示方式。
一种是以GMT或者UTC加时区偏移表示,例如:GMT+08:00或者UTC+08:00表示东八区。

  • UTC+0 2026-01-04 23:00:00
  • UTC+1 2026-01-05 00:00:00
  • UTC+8 2026-01-05 07:00:00
GMT和UTC可以认为基本是等价的,只是UTC使用更精确的原子钟计时,每隔几年会有一个闰秒,我们在开发程序的时候可以忽略两者的误差,因为计算机的时钟在联网的时候会自动与时间服务器同步时间。
另一种是缩写,例如,CST表示China Standard Time,也就是中国标准时间。但是CST也可以表示美国中部时间Central Standard Time USA,因此,缩写容易产生混淆,我们尽量不要使用缩写。
最后一种是以洲/城市表示,例如,Asia/Shanghai,表示上海所在地的时区。特别注意城市名称不是任意的城市,而是由国际标准组织规定的城市。
时刻相同的意思就是,分别在两个时区的两个人,如果在这一刻通电话,他们各自报出自己手表上的时间,虽然本地时间是不同的,但是这两个时间表示的时刻是相同的。
夏令时

时区还不是最复杂的,更复杂的是夏令时。所谓夏令时,就是夏天开始的时候,把时间往后拨1小时,夏天结束的时候,再把时间往前拨1小时。
因为涉及到夏令时,相同的时区,如果表示的方式不同,转换出的时间是不同的。我们举个例子:
意大利的夏令时通常从每年3月的最后一个星期日开始,到10月的最后一个星期日结束。

  • 开始时间:2025年3月30日(星期日)凌晨2点,意大利将进入夏令时,届时所有时钟需拨快一个小时,直接跳到3点,此时可以理解为GMT+2的时间。
  • 结束时间:2025年10月26日(星期日)凌晨3点,夏令时结束,时钟需拨回一个小时,调整为2点,此时可以理解为GMT+1的时间。
所以对于2025-4-1和2025-10-27两个日期来说,假设北京人在意大利:

  • 如果以GMT或者UTC作为时区,无论日期是多少,时间都是19:00;
  • 如果以国家/城市表示,例如Europe/Rome,虽然意大利也在东一区,但是,因为夏令时的存在,在不同的日期,GMT时间和意大利时间可能是不一样的:
时区2025-4-12025-10-27GMT+01:0019:0019:00UTC+01:0019:0019:00Europe/Rome20:0019:00实行夏令时的不同地区,进入和退出夏令时的时间很可能是不同的。同一个地区,根据历史上是否实行过夏令时,标准时间在不同年份换算成当地时间也是不同的。因此,计算夏令时,没有统一的公式,必须按照一组给定的规则来算,并且,该规则要定期更新。
逻辑关系:一张图看懂转换

为了直观表达这种“多对一”的关系,我画了下面这张图:
flowchart TD    A[同一物理时刻] --> B["UTC+0
2026-01-04 23:00:00"]    A --> C["UTC+1
2026-01-05 00:00:00"]    A --> E["UTC+8
2026-01-05 07:00:00"]    B --> D    C --> D        E --> D    D["1767567600000
(Unix 时间戳:自1970-01-01 00:00:00 UTC起的毫秒数)"]        style A fill:#f9f,stroke:#333,stroke-width:2px    style D fill:#bbf,stroke:#333,stroke-width:2px深度解析:

  • 顶层(物理现实):代表宇宙中发生的一件事。
  • 中层(表现形式):由于观察者身处不同的时区(Timezone),同样的时刻被格式化成了不同的字符串。
  • 底层(存储/交换标准):无论表现形式如何,最终在机器层面都会收敛为一个相同的时间戳(如 1767567600000)。
开发中的最佳实践

基于以上原理,我们在开发时应遵循以下准则:
A. 后端存储:永远使用 UTC 或 时间戳

在数据库(如 MySQL, PostgreSQL)中,建议存储:

  • Long 型时间戳:最稳妥,完全避免时区转换开销。
  • 带时区的 Timestamp 类型:由数据库底层处理 UTC 转换。
  • 禁止:存储不带时区的本地时间字符串(如 2026-01-05 07:00:00),因为没有时区信息,这个字符串就是死数据,无法还原回绝对时刻。
B. 接口传输:标准化 ISO 8601 或 时间戳

前后端交互时,推荐使用:

  • Unix 时间戳(毫秒级)。
  • ISO 8601 格式:2026-01-05T07:00:00+08:00。这种格式自带偏移量信息,是可解析的。
C. 前端展示:根据用户时区转换

前端代码(JS/Mobile)接收到后端传来的绝对时刻(时间戳)后,再调用系统 API 转换为用户当前所在时区的文字。
  1. // 无论后端在哪个时区,传来的都是同一个 1767567600000
  2. const timestamp = 1767567600000;
  3. const date = new Date(timestamp);
  4. console.log(date.toLocaleString()); // 自动根据用户电脑时区显示
复制代码
总结


  • 时刻:是物理世界的点。
  • 时间戳:是时刻的数字度量,与时区无关
  • 本地时间:是时间戳在不同时区下的投影形式
作者:飞鸿影
出处:http://52fhy.cnblogs.com/
版权申明:没有标明转载或特殊申明均为作者原创。本文采用以下协议进行授权,自由转载 - 非商用 - 非衍生 - 保持署名 | Creative Commons BY-NC-ND 3.0,转载请注明作者及出处。
1.png

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册