时间与时区陷阱:UTC、本地时间与夏令时的那些坑
存 UTC、按需转本地是铁律。讲清 UTC/GMT/CST 缩写歧义、夏令时切换、数据库时区配置这些高频翻车点。
一、UTC、GMT、CST 都是什么
- UTC:协调世界时,全球基准,不带时区偏移。
- GMT:格林威治平时,老概念,日常与 UTC 等同看待。
- CST 歧义炸弹:可指中国标准时间(UTC+8)也可指美国中部时间(UTC-6)还可能是古巴标准时间——日志里见到 CST 先确认环境再判断。
二、铁律:存储一律 UTC
- 数据库存 UTC(或时间戳),展示时按用户时区转换。
- 服务器时区设 UTC:日志时间线全球一致,排查分布式问题不头疼。
- 前端负责本地化:拿到 UTC/时间戳后按浏览器区域渲染。
反例:服务器存「北京时间」,海外用户一看时间全错,夏令时地区更是灾难。
三、夏令时的坑
- 夏令时切换日:春天丢一小时、秋天重复一小时——那一个小时要么没有、要么出现两次。
- 用本地时间做定时/去重/唯一约束,切换日必然出 bug:该触发的没触发、日志时间倒流。
- 解法:内部运算全部 UTC,只有「给人看的瞬间」才转本地时间。
四、常见翻车现场
- MySQL 时区:连接串不指定时区时用服务器默认,容器里常是 UTC,本机开发是本地——同样代码不同结果。JDBC 建议
serverTimezone=UTC显式写死。 - 日志时间对不上:应用日志本地时间、Nginx 日志 UTC,事故排查时间线错 8 小时。
- 「今天」的边界:按用户所在时区算「今日零点」,别拿服务器零点当边界。
在线体验
不用装任何环境,直接用本站时间戳转换工具在线操作,数据都在浏览器本地处理,方便又安全。
常见问题
北京时间 2024-01-01 00:00 的时间戳怎么算?
先换算成 UTC(减 8 小时 = 2023-12-31 16:00 UTC)再求与纪元的秒差。在线工具通常可选时区,注意确认选项。
为什么推荐服务器时区设成 UTC?
日志、监控、分布式链路追踪的时间戳全链路一致,不用心算偏移;也不受夏令时影响。代价只是人看日志要换算,这活交给工具。
Java 的 Date 有时区吗?
没有。Date 内部只是毫秒时间戳(绝对时间),时区只在格式化显示时参与。因此同一 Date 在不同机器 print 出不同字符串很正常。
