【发布时间】:2017-09-01 18:03:10
【问题描述】:
我有一个 java 应用程序,我想在其中使用 UTC 时间。目前,代码混合使用java.util.Date 和java.sql.Timestamp。为了获得UTC时间,我之前的程序员使用:
日期:
Date.from(ZonedDateTime.now(ZoneOffset.UTC)).toInstant();
对于时间戳:
Timestamp.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
但是,我自己使用此代码运行了多个测试,并且这两行都返回当前日期/时间(在我当前的时区中)。从我读过的所有内容中看来 Date/Timestamp 没有 zoneOffset 值,但我找不到具体的说明。
无论如何要在 Date 或 Timestamp 对象中保留 timeZone (UTC),还是我需要进行一些重构并在整个应用程序中使用实际的 ZonedDateTime 对象?这个 ZonedDateTime 对象还会与当前的 sql 时间戳对象兼容吗?
例子:
public static void main (String args[])
{
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);
Timestamp timestamp = Timestamp.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
Date date = Date.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant());
System.out.println("ZonedDateTime: " + zonedDateTime);
System.out.println("Timestamp: " + timestamp);
System.out.println("Date: " + date);
}
输出:
ZonedDateTime: 2017-04-06T15:46:33.099Z
Timestamp: 2017-04-06 10:46:33.109
Date: Thu Apr 06 10:46:33 CDT 2017
【问题讨论】:
-
"...返回当前日期/时间(在我当前的时区中)...",也许您刚刚在
java.util.Date上使用了toString()的方法来得出结论,但是这个方法只使用外部默认时区来打印自己。偏移量或时区绝不是java.util.Date的一部分,其真实状态由getTime()方法反映。所以请澄清你真正做了什么。 -
日期和时间戳都以格林威治标准时间存储时间。切换时区只会改变显示值。
-
Date.from(ZonedDateTime.now(ZoneOffset.UTC).toInstant())和new Date()之间没有逻辑上的区别。除了前者更令人困惑。 -
通常我不建议查看源代码,因为一个类的行为是由它的契约 (javadoc) 定义的,但是从 Java 8 开始,the source of java.util.Date 表明它只有两个实例字段:一个 long值和仅由现已弃用的方法使用的“BaseCalendar”对象(可以追溯到 Calendar 类不存在并且 Date 类试图提供所有与日历相关的功能时)。它只是包装了一个毫秒值;它不保留时区信息。