一、前言
前两天测试向我反馈生产环境挖机进口日期页面上展示的比数据库中存储的早了一天,但在测试环境是正常的,并且其它时间字段都没有任何问题,很是奇怪,安排开发排查没有头绪,然后我自己登录生产环境确认LInux系统都统一为UTC时区,MySQL测试环境是UTC,但生产环境默认是东八区,将生产环境MySQL设置为UTC问题即解决,当时比较忙也没仔细多想,今天有时间就重新把问题重现梳理一下。
注1:这又是阿里云的一个坑,我是在阿里云国际站买的RDS实例区域为悉尼,为何时区设置为东八区,这个太没道理了,顺便吐槽一下,阿里云国内和国外是不同团队负责,阿里云国内站不支持外国公司开账号,搞得我们现在既有阿里云国内账号买了国内区域的也买了澳洲的,然后国际站也开了账号买了澳洲的设备。
注2:一般我们系统中日期都是使用long类型存储时间戳, 这样只需要在展示时根据当前所在区域进行转换为对应时区即可。
1、跨时区系统设计方案
二、场景重现
1、Linux系统时区设置为UTC.
设置前:东八区
设置时区软链
ln -sf /usr/share/zoneinfo/UTC /etc/localtime
设置后:国际标准时间,英国格林威治标准时间(子午线)
2、MySQL数据库
time_zone为08:00 表示东八区,
在表test_utf中存入一条数据,arrivalDate写入2022-08-13
3、使用JDBC直接连接测试
用命令
java -classpath mysql-connector-java-8.0.13.jar TestUTC.java
执行后输出如下:
arrivalDate = 2022-08-12
4、解决方案
1、数据库时区还是使用东八区,Linux时区还是UTC不变,在数据库连接上加上参数serverTimezone=UTC,这样执行后 arrivalDate = 2022-08-13 可解决问题。
2、直接将数据库时间变更为UTC,set global time_zone = '+0:00'; 也可解决问题。
3、使用rs.getString()方法获取日期的值,返回的也是arrivalDate = 2022-08-13 亦能解决问题。
注:系统中使用MyBatis通过类映射返回数据,但底层原理是一样的,还是因为数据库驱动的造成时区问题。