【问题标题】:java.time.Instant -> java.sql.Timestamp behaving differently on Windows vs *nix (timezone-related)java.time.Instant -> java.sql.Timestamp 在 Windows 和 *nix 上的行为不同(时区相关)
【发布时间】:2015-07-23 20:43:34
【问题描述】:

在我有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 执行的时间和从 Unix 执行的本地时间的 UTC。

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

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

【问题讨论】:

  • 打印 TimeZone.getDefault() 的值:你可能会有不同的值。
  • @JBNizet 谢谢,确实如此!目前还不清楚为什么,但至少我有解释。

标签: java hibernate timestamp jodatime java-time


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 2017-08-03
    • 1970-01-01
    • 2022-01-09
    • 2018-09-23
    • 2012-06-27
    • 2021-04-26
    • 2019-05-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多