Mysql 时区差8小时的多种问题 统统解决
创始人
2025-06-01 03:29:55
0

笑小枫专属目录

    • 背景
    • 知识点
    • 代码中常见的三种时间差错问题
      • 【我遇到的】本地获取的时间没有错,存入数据库的时候时间相差8小时
      • java下使用 `new date()`获取的时间会和真实的本地时间相差8小时
      • 数据库时间没有错,获取到了后端,之后返回给前端相差8小时
    • 数据库代码时区的问题
      • 通过Sql命令修改,临时生效
      • 通过配置文件来进行修改,永久性生效
    • 总结

背景

最近在开发【Java面试 | 笑小枫】小程序,便发现老是有人半夜偷偷刷题,如下图所示:

image-20230321205840646

现在都这么卷了吗?大半夜的都不睡觉了吗?还在撸题~越想越不对,赶紧看了一下,发现自己录入题目的时间也好多都在凌晨。

好家伙,秒懂,时区错了。错就错了吧,影响也不大。

直到现在出现了每日签到的功能,好吧顺手改一下,反正也不难。都改了,顺手整理篇博客吧。

知识点

UTC:Coordinated Universal Time 协调世界时。

GMT:Greenwich Mean Time 格林尼治标准时间。(在协调世界时意义上的0时区,即GMT = UTC+0)

中国的时间是【东八区】,比GMT多八个小时,即 GMT+8(或UTC+8,但习惯上还是用GMT+8)

代码中常见的三种时间差错问题

【我遇到的】本地获取的时间没有错,存入数据库的时候时间相差8小时

mybatis将本地的数据传入到mysql数据库服务器的时候,服务器会对数据进行检测,会把date类型的数据自动转换为mysql服务器所对应的时区,即0时区,所以会相差8小时。

解决方案:

  • 在数据库链接上添加serverTimezone=GMT%2B8

image-20230321214129614

java下使用 new date()获取的时间会和真实的本地时间相差8小时

new date()调用的是jvm时间,而jvm使用的时间默认是0时区的时间,即:和北京时间将会相差8小时。

解决方案:

  • 手动设置jvm时间:将时间改为第8时区的时间:
  • 如果是springboot项目,可以面向切面加上这个,或者启动main类上加上如下代码:
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));

数据库时间没有错,获取到了后端,之后返回给前端相差8小时

springboot中对加了@RestController或者@Controller+@ResponseBody注解的方法的返回值默认是Json格式,所以,对date类型的数据,在返回浏览器端时,会被springboot默认的Jackson框架转换,而Jackson框架默认的时区GMT(相对于中国是少了8小时)。所以最终返回到前端结果是相差8小时。

解决方案:

  • 将spring的json构造器的时区改正即可,在application.yml文件中添加:
spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8
  • 可以使用注解,在entity实体类的date数据上添加注解,那么数据库传回的data数据要转换为json格式的时候就是北京时间了,再次传回到前端的时候,也不会出现时区问题。
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date updateDate;

数据库代码时区的问题

以上说的都是代码中时间的问题,还有一种情况,就是sql使用NOW()获取时间,这种写法太可恶了。强烈不推荐

这种情况使用的是数据库的时间,首先我们看一下数据库时间

select NOW();
image-20230321215559765

如果和当前时间一致,那么恭喜你,没问题。

如果比当前时间少8小时,那么依旧恭喜你,你穿越了。

image-20230321215226932

言归正传,如果比当前时间少8小时,该怎么处理呢?

通过Sql命令修改,临时生效

本方法的优点是,生效快,不需要重启数据库;缺点是重启数据库后配置失效。

  1. 首先检查下Mysql系统时区
show variables like '%time_zone%';
image-20230321215721287
  1. 设置时区
-- 修改mysql全局时区为北京时间,即我们所在的东8区
set global time_zone = '+08:00'; -- 修改当前会话时区,不然需要重新打开会话才会生效
set time_zone = '+08:00';
  1. 立即刷新生效
flush privileges;

然后再执行一下我们的select NOW();查看一下时间,OK,时间一致

image-20230321220030720

通过配置文件来进行修改,永久性生效

本方法的优点是永久性生效,缺点是需要重启数据库

修改mysql的配置文件。linux系统上是my.cnf文件,window系统是my.ini

在[mysqld]区域中加上 default-time_zone = ‘+8:00’

重启mysql使新时区生效

总结

本文到这里就结束了。总结一下吧

  1. 代码中常见的数据问题是,程序中正常,保存到数据库中差8小时,这种情况用在数据库连接中添加serverTimezone=GMT%2B8
  2. Java下使用 new date()获取的时间会和真实的本地时间相差8小时,这个需要修改JVM时区,正常很少见
  3. 数据库时间没有错,获取到了后端,之后返回给前端相差8小时,可以通过设置json转换的时区来进行调整
  4. 修改数据库的时区,可以通过命令临时修改和通过配置文件永久性修改

image-20230321205540732

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...