【BUG】由于url设置东八区,而数据库实际为UTC导致的时间显示错误问题 | 您所在的位置:网站首页 › 东八区到西五区加还是减 › 【BUG】由于url设置东八区,而数据库实际为UTC导致的时间显示错误问题 |
今天发现了一个诡异的BUG。 从Linux服务器的数据库上将数据导入到本地后,发现显示的时间格式不一样。 我瞬间就明白过来,肯定是时区问题,但是为什么会这样呢? 查看一下数据库时区: show variables like'%time_zone';
可是,时区是怎么影响时间格式显示的呢? 因为我记得,MySQL时区的不同,只会影响日期相关函数,比如 now(),sysdate(), unix_timestamp(‘2021-12-29 15:50:20’)的返回结果,对数据表里的日期数据插入、查询是没有影响的。 快递时间的信息是快递100通过接口传给我的,它是在json中传过来的。 而json中是没有时间这种数据格式的,时间在json是以字符串的形式保存的。 以 2029-12-30 13:20:25举例,首先以东八区为例 /** * 日期型字符串转化为日期 格式 */ public static Date parseDate(Object str){ if (str == null){ return null; } try{ return parseDate(str.toString(), parsePatterns); }catch (ParseException e){ return null; } } public static void main(String[] args) { System.out.println(DateUtils.parseDate("2029-12-30 13:20:25")); System.out.println(TimeZone.getDefault().getID()); }parseDate(str.toString(), parsePatterns)调用的是apache下lang3包里的封装方法。 我把电脑时区分别设置为UTC和东八区,然后运行main方法。 发现结果让我很惊讶
经过三个小时的百度,以及掉了73根头发,我忽然虎躯一震,明白了其中的关键。 原来最大的区别,就是一个带有UTC, 一个带有CST。 为什么呢? 且听我缓缓道来。 因为我的数据库连接的url中是这样写的。
不幸的时,linux服务器上的时区是UTC,MySQL使用的是系统时区,也就是UTC。 但是在parseDate(str.toString(), parsePatterns),jvm会调用系统的时区进行转化,也就是说,会转化成Sun Dec 30 13:20:25 CST 2029. mybatis在封装数据的时候,它一看自己设置的是东八区,而你给我传的UTC时间。 得,我知道怎么做,东八区和UTC相差八个小时,我给你加上八个小时,妥妥得。 于是,存到数据库中得时间就变成了2029-12-30 21:20:25. 所以,最后会出现传入的时间,和数据库实际显示的时间不一样。 BUG修复 把linux服务器和数据库都改为东八区(服务器运行很久,不确定这样改,有没有影响,舍弃)将url中的时区设置为0时区(方法可行,成本低)如果仅针对快递100来说,应该定义一个方法,将转化的时间减去8个小时,这样在mybatis转化后,会加上8个小时,等于毫无变动(方法可行,成本低)经过讨论,决定采用第2种方法。 不过,随之而来,另外一个问题,数据库种每条记录都有个create_time,它在插入的时候默认使用sysdate(),这就导致了它总会比实际时间晚上8个小时。 即便采用第三种方法,也会出现这个问题。 后续解决方法: 以后所有的create_time字段都不获取数据库的sysdate(),而是使用new Date()即可。 这样即便服务器是UTC时区,而连接是东八区时间,最后数据库中依然显示的是东八区时间。 |
CopyRight 2018-2019 实验室设备网 版权所有 |