一、背景
门店收银系统分布在澳洲、中国、新西兰,分跨不同时区,系统需要显示不同时区的时间,这是比较折腾的一件事,今天讲一下我们是怎么作的。
二、时区概念
时区
划分时区作用是为了统一时间,让各个区域12点都是正中午的时候,其实我没想明白为什么这么折腾,我这边18点是正中午有什么不可以的呢,这世界就是这样总喜欢把简单的事情搞复杂了,时区的划分以地球表面按经线从东到西划成一个个区域,每隔经度15°划分一个时区,规定相邻区域的时间相差1小时,,如下图所示。
格林尼治时间:英国皇家格林尼治天文台,UTC/GMT 0 (零时区)。
中国时区:有东五区、东六区、东七区、东八区、东九区,新疆在东五、东六、而东北在东九区,但解放后我们国家统一采用东八区的北京时间为准,这样我在云南晚上8点钟的太阳还是很亮。
澳大利亚时区:有东部时区(东十区)、中部时区(东9.5时区)、西部时区(东八区),还有夏令时(现在我们没管它)。
UTC:Coordinated Universal Time,世界统一时间,中国、西澳都是UTC+8,
GMT:Greenwish Mean Time ,以地球公转和自转来计算时间,而UTC以原子钟来计算时间。
UNIX时间戳:1970年1月1日(UTC/GMT的午夜)开始所经过的秒数。
三、操作系统、数据库、编程语言时区设置
1、Linux操作系统时区设置
北京时间8月3日15:04:59在两台机器执行命令查时区
# date -R
Tue, 03 Aug 2021 07:04:59 +0000 +0000用的是UTC0时区
Tue, 03 Aug 2021 15:04:59 +0800 +0800用的是UTC+8时区
一般阿里云中国区服务器默认都是UTC+8,阿里云海外机器UTC+0,亚马逊的是UTC+0,购买服务器后都需要确认一下。
#设置时区
tzselect #向导式的选择时区,选择大州、
国家和城市,然后在/usr/share/zoneinfo
下会生成时区的文件,将该文件覆盖/etc/localtime
即可完成时区设置。
2、MySQL数据库时区
3、Java时区
3.1 通过JVM参数指定时区
3.2 通过Java代码指定时区
这里吐槽一下,获取时区时没有Beijing,据说是历史问题。
时区设置优先级:Java语言时区设置>JVM时区设置>Linux /etc/localtime
四、收银系统跨时区设计
1、AWS RDS表中所有日期时间字段全部用int类型,只存储时间戳,不存具体日期格式数据。
2、AWS Linux使用的是UTC+0时区。
3、往数据库写入数据时全部使用UNIX时间戳。
4、门店表配置了对应时区,比如 Perth时区是东八区,Jindalee 是东十区等。
5、查询结果日期字段展示处理
6、查询条件处理
比如查询订单查询条件输入 起始日期、 结束日期,
前端JS直接把输入的日期传给后端,比如 2021-08-02~2021-08-02
2021-08-02~2021-08-02经过转换后就变成获取东八区2021-08-02 00:00:00 到2021-08-02 23:59:59的时间戳,然后再到数据库去获取数据。
注:这里其实应该传入门店对应的时区,我们当前系统时区主要集中在东八到东十一区,门店开店时间在北京时间凌晨5点~下午6点这个区间,这样处理暂时没有问题。