gpt4 book ai didi

java.time.Instant -> java.sql.Timestamp 在 Windows 和 *nix 上表现不同(与时区相关)

转载 作者:行者123 更新时间:2023-11-30 08:52:19 25 4
gpt4 key购买 nike

在代码的某处,我有 Timestamp ts = Timestamp.from(instant);,顾名思义,instant 是 java.time.Instant。 (为什么?为了让 Hibernate 4.x 持久化,通过 UserType,JDK8 时间类型,在 Hibernate 5 之前尚不支持)。

事实上,让我把代码放上去,这样就清楚了。日志语句就是针对这个问题的。

public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
if (value != null){
Timestamp ts = Timestamp.from((Instant) value);
log.info("nullSafeSet from " + value + " (as long: " + ((Instant) value).toEpochMilli() + ") to " + ts + " (as long: " + ts.getTime() + ")");
StandardBasicTypes.TIMESTAMP.nullSafeSet(st, ts, index, session);
} else {
st.setNull(index, Types.TIMESTAMP);
}
}

这就是问题所在。在 Windows(7、64 位,尽管无关紧要)上,时间戳的字符串表示对应于 UTC 值。

From: 2015-05-12T19:00:08.191Z (as long: 1431457208191) 
to: 2015-05-12 19:00:08.191 (as long: 1431457208191)

在 *nix(Linux、OS X)上,字符串表示对应于本地(EST,或准确地说是 EDT)时间:

From: 2015-05-12T19:16:54.488Z (as long: 1431458214488) 
to: 2015-05-12 15:16:54.488 (as long: 1431458214488)

绝对时间和可以看到的一样。问题是 JDBC 驱动程序发送到 Oracle 数据库到 TIMESTAMP 字段中的是字符串表示或等价物(我查看了网络流量,参数是二进制格式,所以不容易弄清楚到底发送了什么)。 相同的代码在从 Windows 执行时插入 UTC 等效时间,在从 Unix 执行时插入本地时间。

我已经检查了 user.timezone 系统属性,在这两种情况下都是 America/New York。机器本身也是如此。相同的 JDK8 版本、相同的应用服务器、相同的代码。

我对这种行为以及如何解决它感到困惑。

最佳答案

好吧,最终我找到了原因,它和我想的不一样。感谢@JBNizet 给我的提示让我走上了正确的道路。

如评论中所述,在执行特定方法时,一个系统 TimeZone.getDefault() 在 Windows 上返回“UTC”,在 Windows 上返回“America/New York”在 Unix 机器上。尽管两个系统都以 user.timezone="America/New York" 开始,但已通过日志记录确认。

真正的原因是在 Windows 机器上,我还在同一台服务器上部署了一个不同的 Web 应用程序。该应用程序是用 Grails 编写的,它正在调用 TimeZone.setDefault("UTC"),从而覆盖在 JVM 级别通过我的应用程序中的属性设置的时区。我通过 TimeZone.setDefault() 中的断点确认了这一点。

关于java.time.Instant -> java.sql.Timestamp 在 Windows 和 *nix 上表现不同(与时区相关),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30199962/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com