遇到mysql查询出来的时间在页面上相差几个小时

参考:https://blog.csdn.net/vae1314chuanchen/article/details/81838476

https://blog.csdn.net/sweatOtt/article/details/78111748

https://blog.csdn.net/weixin_42353194/article/details/90599215

一、修改MySql数据库的默认时区

MySql数据库创建后,默认的时区比东八区少了八个小时。如果Sql语句中使用到MySql的时间的话就会比正常时间少了八个小时。所以需要修改MySql的系统时区,使其显示的时间和我们现在的时间一致。
  
1)查看mysql系统时间

select now(); 
2)查看数据库时区

show variables like '%time_zone%';
3)设置时区更改为东八区

set global time_zone = '+8:00';
4)刷新权限

flush privileges; 
5)退出后重新登录,即可。

6)修改my.cnf实现永久修改MySQL时区。

cd /etc
vim my.cnf
7)在mysqld下边的配置中添加一行:

default-time_zone = '+8:00'
8)然后重启mysql

service mysql restart
sudo systemctl restart mysqld
二、修改数据库的驱动

若时间还是不对,有可能是驱动的问题,检查下驱动信息,如果连接参数中的字段serverTimezone设置为UTC,将UTC更改为 Asia/Shanghai就可以了。

jdbc:mysql://127.0.0.1:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=Asia/Shanghai
三、查看和修改Linux服务器上的时区

对于部署在海外的Linux服务器来说,拿到的机器时区和本地并不一样,导致运行在上面的应用也面临时区问题,所以有必要修改Linux服务器上的时区。
  1、查看服务器当前的时区
  查看当前生效的时区,可以通过date -R命令来查看当前时间。

[webadmin@host ~]$ sudo date -R
Sun, 19 Aug 2018 15:18:38 +0800
注:+0800,即东8区。
  2、设置时区
  1)通过tzselect命令查看时区向导
  tzselect命令看起来很像一个时区选择的工具,但并非如此。事实上tzselect仅仅是一个查看时区表示方式的『向导』程序而已。通过依次询问大洲→国家→城市,最后告诉你如何TZ变量的写法,比如北京时间是:Asia/Shanghai。
  2)通过修改TZ变量**,直接修改时区信息
  可以通过修改TZ变量,直接修改时区信息,比如:

[webadmin@host ~]$ sudo date -R
Sun, 19 Aug 2018 15:25:15 +0800
[webadmin@host ~]$ sudo export  TZ='Asia/Shanghai'
[webadmin@host ~]$ sudo date -R              
Sun, 19 Aug 2018 15:25:51 +0800
有Linux经验的小伙伴都知道,不写在文件里的设置更改很难生效一般是会话级的,重新登录会消失。所以,这样直接修改TZ的尿性绝对做不到持久化更改时区的。
  正确的方式是到/etc/profile里(或用户的.profile或.bashrc文件),直接export TZ变量为要更改的时区(时区的名字可以用tzselect向导来确定)。
  下面展示一波正确的做法:
  
1)代开文件.bash_profile

sudo vim ~/.bash_profile 
2)在文末添加export TZ=‘Asia/Shanghai’
3)使配置生效

source ~/.bash_profile
3)重启相关service或者直接重启服务器
  4)通过/etc/localtime文件修改时区
  默认情况下情况下,TZ属性是空,这时候是靠**/etc/localtime文件来确定的时区。而此文件通常又是一个到/usr/share/zoneinfo/下各种时区文件的软连接。通过修改/etc/localtime**指向的软连接,进而修改系统的时区。比如下面的方法,将localtime文件设置为了北京时间:

 ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

四、

默认情况下mysql的time_zone为SYSTEM,也就是mysql的时区和服务器的时区是一样的。一般服务器都是东八区。在使用mysql时,客户端所在的时区一般也是东八区。所以从mysql查询timestamp类型数据时一切正常。

现在如果我们的条件是这样的:

使用的jdbc url长这样jdbc:mysql://localhost:3306/table_name
客户端的时区为零时区
mysql的时区是东八区
 

上面几个条件如果满足了,这时候你从mysql查找timestamp的数据,拿到的timestamp值和数据库中的值是一样的,没有考虑时区的问题,所以事实上是多了8小时。

通过debug,发现jdbc的ConnectionImpl类中configureTimezone()配置time zone时有几个条件

        String canonicalTimezone = getServerTimezone();

        if ((getUseTimezone() || !getUseLegacyDatetimeCode()) && configuredTimeZoneOnServer != null) {
            // user can override this with driver properties, so don't detect if that's the case
            if (canonicalTimezone == null || StringUtils.isEmptyOrWhitespaceOnly(canonicalTimezone)) {
                try {
                    canonicalTimezone = TimeUtil.getCanonicalTimezone(configuredTimeZoneOnServer, getExceptionInterceptor());
                } catch (IllegalArgumentException iae) {
                    throw SQLError.createSQLException(iae.getMessage(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
                }
            }
        }

        if (canonicalTimezone != null && canonicalTimezone.length() > 0) {
            this.serverTimezoneTZ = TimeZone.getTimeZone(canonicalTimezone);
            ...
getServerTimezone()方法拿到的值默认为null,getUseTimezone()和getUseLegacyDatetimeCode()方法得到的值分别是false和true,这样就导致了connector不会使用数据库的time zone。所以我们从数据库内读取timestamp数据,不做任何时区转化。

如果想要开启时区转换,需要将useTimezone设置为true, 即jdbc:mysql://localhost:3306/table_name?useTimezone=true

我们可以看mysql文档对useTimezone描述

useTimezone 
Convert time/date types between client and server time zones (true/false, defaults to ‘false’)? This is part of the legacy date-time code, thus the property has an effect only when “useLegacyDatetimeCode=true.” 
Default: false
将useTimezone设置为true后,还有一点很重要,如果mysql的time_zone为SYSTEM,连接数据库是会报错的,需要给定一个明确的时区。我们可以把数据库的time_zone设置为+08:00,这样timestamp的数据就会根据时区进行转换。 如果不想修改数据库的time_zone,可以在客户端进行设置,指定time_zone,jdbc:mysql://localhost:3306/table_name?useTimezone=true&serverTimezone=GMT%2B8,GMT%2B8表示东八区。


五、最后一种方法:

设置spring配置文件:

1、spring.datasource.url=jdbc:mysql://10.35.105.25:3306/database?characterEncoding=utf-8&serverTimezone=GMT%2B8

数据库配置后面加上&serverTimezone=GMT%2B8

2、spring.jackson.date-format=yyyy-MM-dd HH:mm:ss

     spring.jackson.time-zone=GMT+8

第一步为设置数据库时间为东八区(北京)时间,保证debug时候从数据库查出时间一致。第二步为返回给前端的时间格式和时区设定,保证前端页面显示时间和数据库一致。

 

总结:认真分析各个步骤:数据库,驱动,后端向前端返回的时区

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值