现象
问题描述:页面时间和数据库时间相差13小时。
排坑过程
被转换的日期属性:用的就是jackson的日期转换成字符串。
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date lastLoginTime;
一、添加jackson时区配置
网上说是jackson转换时区问题,随后加上了
yml配置:
spring:
jackson:
time-zone: GMT+8
测试后,仍然没有解决问题。
二、数据库时区设置
排查后发现java服务拿到日期的时候已经错误了,并不是jackson转化的时候出现的问题。
我存在mysql中的类型是timestamp,先看下timestamp的特点
- 值以UTC格式保存( it stores the number of milliseconds)
- 与时区有关,存储的时候根据数据库配置的时区进行转化为UTC时间,取的时候把UTC时间转成数据库配置时区的时间。
再看下mysql驱动(mysql-connector)中获取时区的方法。
String configuredTimeZoneOnServer = this.serverSession.getServerVariable("time_zone"); if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) { configuredTimeZoneOnServer = this.serverSession.getServerVariable("system_time_zone"); }
查看mysql时区的配置
show variables like '%time_zone%';
根据上面代码,time_zone=='SYSTEM'的时候取system_time_zone的值
system_time_zone的值为CST
坑
CST在数据库中是中国标准时间的意思,但是与jdbc转化的时候把它当成了美国中部时间,这2个时区都叫CST。
这个美国中部时间在夏令时=UTC-5,上海时区=UTC+8,所以出现了和数据库时间差13小时的现象。(冬令时差14小时)。
解决
直接设置数据库的time_zone这样mysql驱动就不会读到system_time_zone
set global time_zone='+8:00'; set time_zone = '+8:00'; flush privileges;
时区设置也可以通过修改mysql配置实现,修改 my.cnf
文件,在[mysqld]
节下增加 default-time-zone = '+08:00'。