在我的应用程序开始时,我已经使用 "Spring Data JPA "将默认时区设置为AustraliaPerth。Timezone.setDefaultTimezone()
方法。我正试图在 created_date
栏目。当 save
在调用Spring data JPA的方法时,时间戳是澳大利亚时区下午4点。但是,在DB中,它被存储为下午4点的UTC。我们的Spring配置没有强制JDBC使用UTC时区。没有指定这样的配置。事实上,在版本库中根本就没有UTC。
问题:我知道JDBC驱动决定了时区。问题:我知道JDBC驱动是决定时区的,那么它是不是应该总是使用JVM默认的时区,在这种情况下是澳大利亚?问:无论我在代码中设置什么时区(无论是作为默认时区还是在日期列中),在DB中总是UTC。但是时间戳的数字部分是正确的。Q) JDBC使用的是哪个时区--JVM的默认时区还是DB的 "DBtimezone"(在本例中,恰好是后者)?或者可以是任何时区?
信息:DB的Dbtimezone - select dbtimezone from dual - UTCSessiontimezone of DB - AsiaCalcuttaCreated_date列的类型是'TIMESTAMP WITH TIMEZONE'。
注:我试过用java.time类。OffsetdateTime和ZonedDateTime,但是没有成功。
永远不要设置默认时区。这样做会立即影响在该JVM内运行的所有应用程序的所有线程中运行的所有其他代码。而任何其他代码都可以再次重置它。
所以永远不要编写依赖于JVM当前默认时区的代码。明确地指定你想要的预期时区。
我试图在created_date列中插入一个澳大利亚时区的时间戳。
(A) 请确定你的数据库列的类型类似于SQL标准的类型 TIMESTAMP WITH TIME ZONE
.
(B) 只使用现代 java.time 类型。
(C) 使用符合JDBC 4.2及以上的JDBC驱动程序。
我不使用JPA。但我可以直接给你看JDBC。
ZoneId z = ZoneId.of( "Australia/Perth" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;
你可能会被一些工具和中间件所迷惑,这些工具和中间件有一个不幸的反功能,那就是在从数据库中获取值后,但在显示给你之前,动态地应用一个默认时区。这就造成了一个并不存在的时区的假象。试着用Java从数据库中检索你的值。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
用这个答案上的代码就不会出现时区问题了 根据我的经验 JDBC驱动程序 对于 Postgres 和 H2在服务器或客户端上,没有与任何默认时区的交互。坚持(a)使用java.time类,(b)总是指定你所期望的预期时区,而不是隐含地依赖一个默认时区。我没有使用Spring或Hibernate,所以我不知道它们是否可能在途中注入一个时区。
试着用一些直接的JDBC来消除Spring和JPAHibernate的影响,同时调试一下你的情况。
对了,时区 Asia/Calcutta
已改名为 Asia/Kolkata
. 确保 tz数据 在您的操作系统、数据库引擎和Java实现中,所有这些都是最新的。