时区规范

背景

全球业务为什么需要关注时区?
24个时区是如何产生的?过去世界各地原本各自订定当地时间,但随着交通和电讯的发达,各地交流日益频繁,不同的地方时间,造成许多困扰,于是在西元1884年的国际会议上制定了全球性的标准时,以英国伦敦格林威治这个地方为零度经线的起点(亦称为本初子午线),并以地球由西向东每24小时自转一周360°,订定每隔经度15°,时差1小时。而每15°的经线则称为该时区的中央经线,将全球划分为24个时区,其中包含23个整时区及180°经线左右两侧的2个半时区。就全球的时间来看,东经的时间比西经要早,也就是如果格林威治时间是中午12时,则中央经线15°E的时区为下午1时,中央经线30°E时区的时间为下午2时;反之,中央经线15°W的时区时间为上午11时,中央经线30°W时区的时间为上午10时。以台湾为例,台湾位于东经121°,换算后与格林威治就有8小时的时差。如果两人同时从格林威治的0°各往东、西方前进,当他们在经线180°时,就会相差24小时,所以经线180°被定为国际换日线,由西向东通过此线时日期要减去一日,反之,若由东向西则要增加一日。

国家的本地时区

  • 中国只有一个时区:CST:中华人民共和国成立后,为了方便管理,使用了单一时区制,以东八区的北京时间为标准时。 中国的五时区划分制也基本退出历史舞台。
  • 而美国有四个时区,以美国为例,美国本土分四个时区,加上阿拉斯加和夏威夷,美国有六个时区。

全球业务独立部署时区设计

JVM

JVM建议跟数据库时区保持一致,为了避免JAVA应用的时区跟操作系统时区不一样,在启动参数加上对应的时区,如-Duser.timezone=UTC+0800

操作系统

Mysql

统一使用UTC

datetime vs datetime

类型 表示范围
datetime '1000-01-01 00:00:00.000000' to '9999-12-31 23:59:59.999999'
timestamp '1970-01-01 00:00:01.000000' to '2038-01-19 03:14:07.999999'

timestamp翻译为汉语即"时间戳",它是当前时间到 Unix元年(1970 年 1 月 1 日 0 时 0 分 0 秒)的秒数。只占 4 个字节,timestamp表示是绝对时间,不受时区影响,也叫纪元时epoch。

datetime不存储时区信息.

关于datetime和timestamp的选择使用.
1 在满足使用条件的情况下,占据存储空间越少越好,此时选择timestamp比datetime更好.
2 关于日期的使用范围, timestamp类型最大只支持到2038-01-19年,所以如果使用的日期时间较大, 则选择datetime比timestamp更好.

3 使用 BIGINT 存储时间戳:可以将时间以 Unix 时间戳(从 1970 年 1 月 1 日 00:00:00 UTC 到指定时间的秒数)的形式存储为 BIGINT 类型。这种方式可以存储更大范围的时间,并且可以方便地进行时间计算。例如:

ES

https://www.cnblogs.com/aibi1/p/18708477

特殊架构

应用和数据库时区不一样怎么转化

大多数场景下,我们建议应用和数据库设置为同一时区。但是有些场景应用和数据库的时区可能不一样,比如应用部署在海外,设置为UTC,但是大数据存储在国内设置的是东八区。

应用在与数据服务器连接的时候,就获取到数据库的时区,如果数据库的时区未设置,为空,那么应用根本无法连接数据库服务器,会出现错误日志,让指定 serverTimeZone。

serverTimeZone设置demo

jdbc:mysql://xxx?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC+8

jdbc驱动的参数serverTimeZone的作用就是指定应用和mysql服务器的会话期间的mysql服务器时区,就是临时指定mysql服务器的时区。
如果数据库已经设置了时区,serverTimeZone可以不做设定。

全球多套部署

比如北美单独部署一套代码,欧洲单独部署。
可以选择当地的时区,那么还是建议全部使用UTC,因为可能存在海外集群合并迁移的问题。

业务层

定时任务

有些定时任务在凌晨(非通勤时间)跑,但是这个凌晨相对别的时区的人却是上班时间。

比如:原来的job,每天0点后,算前1天的即可,只要跑一次,现在海外用户加进来后,比如有3个海外地区,job就要在额外的3个时间点,分别计算各个地区的自然天汇总数据。可能需要把原来的job部署多份(或配置多个启动的时间点),然后在每个不同的时间点,要有各自的逻辑,计算指定地区的数据。

所以,还有另一个思路:把按天计算的报表,汇总的时间颗粒度细化,变成按小时计算,每个小时汇总前1个小时的数据,1个小时一条记录,然后不同时区的用户在查看时,根据当地自然天,查询出对应匹配的24条记录,最后做个简单的sum即可。这样job就不用区别对待各个地区,逻辑是统一的,对所有地区,只算上1个小时数据。

客户个性化需求

如果国内的用户飞到美国,登录系统后,他期望看到的还是中国的时区。
方案1 : 根据租户设置固定时区,当用户登录后,前端获取到该用户设置的时区,作为前端数据展现的时区。此外,后端还需要提供应用的时区给前端。
方案2: 登录账号可以设置偏好时区,用户可以修改。

编码规范

时区类选择

建议使用带时区的ZonedDateTime 。 如使用Date或者localDateTime。当JVM时区和数据库或者ES不一致,容易产生时区丢失。

跨系统集成

以接口提供方的时区作为标准时区,接口调用方要根据提供方做时区转化

posted @   向着朝阳  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示