Loading

05-SpringBoot + MySQL时区问题

1、问题说明

使用springboot + MySQL的项目中,经常出现前端页面展示的时间和MySQL数据库里的时间不一致的情况,致人崩溃,故花时间搞清楚之其中的原理。

2、问题分析

数据库中的时间到我们将他展示到页面上,要经过如下流程:

**数据库服务器 ——> Java代码 ——> 日期格式化(展示)

其中,有两个地方涉及到时区问题(手动配置):

  1. 服务器时区:即MySQL的时区,通过url指定serverTimezone来指定本次连接MySQL的时区,不知道时默认为系统时区

    show VARIABLES like '%time_zone%'; 
    

    image-20211104204825079

    这是安装MySQL默认的时区,为SYSTEM,即系统时区,国内为东八区。

    大多数情况下,这里的默认时区不一定为东八区;

    故常见操作为通过数据库连接urlserverTimezone属性来指定当前连接中数据库的时区

  2. 格式化日期时指定的时区(不通过timezone指定时区时,默认为UTC时区)

    timezone和上面通过serverTimezone指定时区时,若想指定为东八区,这值必须为GMT+8,而不能为UTC+8,后者不生效

    UTC+8不生效原因:语义上,两者几乎无区别,但实际上,时区的划分是以本初子午线划分的,而GMT时间就是以此为基础而来的,故GMT+8表示东八区没问题,而UTC是后面才出现的,因此timezone不支持,即不生效。详见https://juejin.cn/post/7076729170205605918

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    

当然,Java代码也有时区,但是一般我们不会去修改,而是使用默认时区东八区。

PS:

Java代码的时区指的是用Date类型来作为中间变量存储从数据库中查询出来的日期

LocalDateTime类型仅仅是一串数字的集合,不包含时区,即你给它什么,他就还给你什么,不会因为时区发生变化而改变它的值

3、解决方案

1. 使用LocalDateTime类型代替Date类型保存日期

上面也说过,LocalDateTime类型不包含时区,仅仅是一串数字的集合,故能避免时区问题

2. 统一配置时区为东八区

由于Java程序使用的时区不会发生变化(采用操作系统时区,国内一般默认为东八区),因此保证MySQL的时区以及格式化字符串指定的时区斗鱼Java程序的时区保存一致为东八区即可。

若不一致,则有一下几种情况(下图为查询操作的过程,插入操作于此相反):

image-20211104203016430

对于情况1,虽然说最终页面展示的时间与数据库的时间一致,但是java代码的时间是不对的,因此也不推荐。

posted @ 2022-03-21 20:14  OMaster  阅读(522)  评论(0编辑  收藏  举报