将“没有时区的时间戳”加载到 LocalDateTime 时,会考虑 JVM 时区,这会导致时间戳发生偏移。
数据库专栏:
some_timestamp timestamp without time zone
JPA 实体:
@Column(name = "some_timestamp ", columnDefinition = "TIMESTAMP")
private LocalDateTime someTimestamp;
如果数据是通过例如加载的pgAdmin 你会得到实际的时间戳。但是,如果通过 pgjdbc 驱动程序加载数据,则时间戳会根据 JVM/系统时区进行修改。
示例:
system timezone: UTC+01:00 Amsterdam, Berlin, ...
database value: '2018-03-25 02:00:00'
pgAdmin select result: '2018-03-25 02:00:00'
pgjdbc driver result: '2018-03-25 03:00:00'
我读到 pgjdbc 驱动程序中存在另一个方向的错误修复(用于从 LocalDateTime 转换为“无时区的时间戳”)。 请参阅 https://github.com/pgjdbc/pgjdbc/issues/2850 以及 2852 中的实际修复。
但是,我的问题是“没有时区的时间戳”到 LocalDateTime 的方向。
有谁知道如何防止jdbc驱动程序考虑JVM/系统时区?
好吧,根据您指定的票证,并进一步阅读,这是预期的行为。
JDBC 2.1 指定驱动程序使用默认日历 时间戳不提供时区。第 10.5 节关于日期, 时间和时间戳。
由于没有显式向 getDate() 提供日历,因此 默认 时区(实际上是默认日历)由 JDBC 驱动程序使用 内部创建适当的毫秒值假设 底层数据库不存储时区信息。
所以,除非我们提供默认的 java.util.Calendar,否则 PostgreSQL 将使用默认值,它会回退到底层 JVM 时区。
Vlad Mihalcea 参考:
传统上,为了解决这个问题,应该设置 JVM 时区 至 UTC:
声明式:
java -Duser.timezone=UTC ...
或以编程方式:
TimeZone.setDefault( TimeZone.getTimeZone( "UTC" ) );
或者如果使用 Hibernate:
hibernate.jdbc.time_zone SessionFactory-level configuration property
请参阅以下 2 个链接以帮助进一步澄清这一点。
https://github.com/pgjdbc/pgjdbc/issues/1108#issuecomment-559508740
https://in.relation.to/2016/09/12/jdbc-time-zone-configuration-property/