首页 > 解决方案 > 持久化到 MySQL 数据库时 LocalDate 发生变化

问题描述

我有一个在 Linux 机器上运行的 Java 应用程序,它从 API 检索一些数据并将其保存到 MySQL 数据库中。当我尝试将日期和时间(LocalDate,LocalTime)保存到数据库中时,Java 和数据库中的值是不同的。

例如,对于日期 2021 年 10 月 9 日和时间 00:00 伦敦时间,我在数据库中看到正确的日期,即 10 月 9 日,但时间是 23:00 而不是 00:00。我不得不提到它在从 DST 到 GMT 的时间变化之前工作。我用于保存到数据库中的 Java 代码是这样的,在对其进行调试时,值保持正确,日期为 10 月 9 日,时间为 00:00:

ZonedDateTime utcTime = fixturesList.get(i).getEvent_date();
ZoneId london = ZoneId.of("Europe/London");
ZonedDateTime dateTimeLondon = utcTime.toInstant().atZone(london);
currentMatchEntity.setDate(dateTimeLondon.toLocalDate());
currentMatchEntity.setTime(dateTimeLondon.toLocalTime());
matchesRepository.save(currentMatchEntity);

我认为 MySql 可能有错误的时区,所以我运行了以下查询,但结果似乎是正确的: 在此处输入图像描述

另外,我认为Linux机器可能存在一些问题,所以我运行了以下命令,但结果似乎也是正确的。

在此处输入图像描述

Java的休眠属性:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>

        <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://databaseAddress/databaseName;serverTimezone=GMT</property>

        <property name="connection.pool_size">2</property>

        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>

        <property name="show_sql">true</property>

        <property name="current_session_context_class">thread</property>


        <!-- DB schema will be updated if needed -->
        <!-- <property name="hbm2ddl.auto">update</property> -->
    </session-factory>
</hibernate-configuration>

为什么 MySQL 将时间保存为“23:00”而不是“00:00”?为什么它会减少一个小时?谁能帮我?

标签: javamysqljdbc

解决方案


一般来说,您应该能够避免编写代码来转换时区。但这需要

  • 正确设置客户端和服务器(操作系统和 MySQL),并且
  • DATETIME在和之间正确选择TIMESTAMP

DATETIME就像给墙上的时钟拍照一样。它已经设置了时区和日光/标准时间。

TIMESTAMP以 UTC 存储。您输入的内容会根据一些设置悄悄地转换为 UTC。读取时,它被转换回来。

另一个人TIMESTAMP通过他的计算机从您的服务器获取 a 将看到与您存储的时间不同的时间。对于DATETIME,你们都看到相同的字符串。

查看你的 MySQL 服务器是如何配置的:

SHOW VARIABLES LIKE '%zone%';

如果显示"SYSTEM",则查看操作系统设置以了解其含义。

注意:英国已经使用 DST多年


推荐阅读