【发布时间】:2021-02-23 09:29:09
【问题描述】:
在我们的项目(Spring Boot 2.2.3、MySQL 5.7、Hibernate、Java 14)中,我们将所有与日期相关的字段作为数据类型 java.time.Instant。在我们的 MySQL 中,所有字段的类型都是 DATETIME。
当我为我的 JDBC 连接指定一个类似 jdbc:mysql://localhost/mydb?characterEncoding=UTF-8&useLegacyDatetimeCode=false&serverTimezone=Europe/Paris 的连接字符串并且我的实体中有一个 2020-07-13T00:00:00Z 的值时,数据库中的 2020-07-13T02:00:00Z 会被持久化(通过 IntelliJ/DataGrip 查看)。
当我使用 JDBC 连接再次读取它时,我使用2020-07-13T00:00:00Z 正确接收到它。
IntelliJ 表格视图中时间的显示似乎不受我设置的 serverTimeZone 的影响,所以我希望它显示存储在数据库中的纯值。
当我将我的 JDBC 连接的 connectionString 更改为 jdbc:mysql://localhost/mydb?characterEncoding=UTF-8&useLegacyDatetimeCode=false&serverTimezone=UTC 并且我的实体中的值为 2020-07-13T00:00:00Z 时,数据库中的 2020-07-13T00:00:00Z 会被持久化(通过 IntelliJ/DataGrip 查看)。
当我使用 JDBC 连接再次读取它时,我使用 2020-07-13T00:00:00Z 正确接收到它。
所以看起来我有一个 Instant,Java/MySQL 假定它是 UTC 并将其转换为连接字符串中指定的时区,因此在我的时区中添加冬季时间的一小时/夏季时间的两个小时。
我想了解的是谁执行这些时区调整以及为什么。因为我从MySQL documentation 了解到,这些适应不应该发生在类型 DATETIME 上。
MySQL 将 TIMESTAMP 值从当前时区转换为 UTC 进行存储,然后从 UTC 转换回当前时区进行检索。 (这不会发生在其他类型,例如 DATETIME。)默认情况下,每个连接的当前时区是服务器的时间。可以基于每个连接设置时区。只要时区设置保持不变,您就可以返回存储的相同值。如果您存储一个 TIMESTAMP 值,然后更改时区并检索该值,则检索到的值与您存储的值不同。
【问题讨论】:
-
我想了解的是谁执行这些时区适应 JDBC 或 Java 本身.. 我投票给 Java。