背景

今天早上刚上班,就被同事提示,程序的日期处理有问题。数据库里日期为:2019-05-21 11:00:00 而前端显示的日期为:2019-05-21 16:00:00

分析

那肯定是和时区相关了,别问为什么,这是程序猿该有的直觉。
首先,看一下mysql的时区是什么?
命令:show variables like '%time_zone%';
结果:

system_time_zoneCST
time_zoneSYSTEM

那么CST时区究竟是什么时区呢,我们下面简单介绍一下:
CST 的时区是一个很混乱的时区,有四种含义:

  • 美国中部时间 Central Standard Time (USA) UTC-06:00
  • 澳大利亚中部时间 Central Standard Time (Australia) UTC+09:30
  • 中国标准时 China Standard Time UTC+08:00
  • 古巴标准时 Cuba Standard Time UTC-04:00

今天是“4月28日”。为什么提到日期?因为美国从“3月11日”至“11月7日”实行夏令时,美国中部时间改为 UTC-05:00,与 UTC+08:00 相差 13 小时。
JDBC与MySQL开始建立连接时,在配置时区的时候,会拿到MySQL的时区是CST,然后Java 会误以为是 CST -0500,而非 CST +0800。
正是因为这个原因,所以导致时间出现问题:16:00:00减去5个小时,正好是11:00:00

解决方案

1、不动mysql数据库的时区的前提下

将项目的时区设置为世界标准时区UTC
在mysql的连接url上加上UTC时区

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mccs?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC

可能有些同学会疑惑,为什么不设置为中国的时区(上海),其实呢,是可以的,但是单单只设置项目的时区是不行的,我们下面看看:

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mccs?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai

返回给前端的日期为:2019-05-21 03:00:00。因为我们的时区是CST +0800。所以11:00:00减去8个小时候就是03:00:00了。
那么可以看出,单单设置项目的时区为中国时区是不行的。那么有什么补救方法呢?
如果对日期的格式化你是用的是jackson,那么再加多一条配置,就可以了:

spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
2、直接修改mysql数据的时区

直接修改mysql数据库的时区是最彻底的,之后所有的项目都不用管时区的问题了。
方式一:命令修改

方式二:修改配置文件【linux:my.cnf,windows:my.ini】
在[mysqld]区域中加上:default-time_zone = '+8:00'

最后记得重启MySQL的服务。

01-18 21:35