1

我正在尝试将 ZonedDateTime 转换为日期。看起来在转换中,它失去了时区并获得了我的当地时间。

System.out.println("zoneDate1::::::::::"+ZonedDateTime.now(ZoneId.of("America/Chicago")));
System.out.println("zoneDate1:Date::::::::::"+Date.from(ZonedDateTime.now(ZoneId.of("America/Chicago")).toInstant()));

以上输出如下:

zoneDate1::::::::::2016-04-15T17:35:06.357-05:00[America/Chicago]
zoneDate1:Date::::::::::Fri Apr 15 18:35:06 EDT 2016

这是因为这是 Date 类型吗?我将如何进行这种转换并节省分区时间?

4

3 回答 3

2

问题是什么?你期待什么?我没有看到任何不当行为。

您的 java.time 类型 ( ZonedDateTime) 被分配了一个时区America/Chicago

您的 JVM 显然有一个与北美东海岸相关的指定时区,线索是EDT在字符串输出中看到的值。java.util.Date 上的toString方法在生成日期时间值的文本表示时应用 JVM 的当前默认时区。设计不佳,此行为试图提供帮助,但实际上令人困惑,因为您实际上无法在 java.util.Date 对象上获取或设置此时区。

无论如何,北美东海岸(如America/New_York时区)比America/Chicago. 因此,您看到17:xx:xx的是芝加哥时间和18:xx:xx东部夏令时间。这些值是正确的。

您应该java.util.TimeZone.getDefault()在调查旧日期时间类的行为时调用。

java.time

更大的问题是您甚至在使用这些旧的日期时间类,例如 java.util.Date/.Calendar。它们设计不佳,令人困惑且麻烦。完全避免这些旧课程。它们在 Java 8 中被 java.time 框架取代。

此外,避免使用 3-4 个字母的区域缩写,如EDT. 这些既不是标准化的也不是唯一的。使用大陆/地区格式的正确时区名称

Instant

要在 java.time 中捕获当前日期时间,只需使用Instant. 此类在UTC时间轴上捕获一个时刻。使用 UTC 完成大部分工作。除非用户在用户界面中显示时期望时区,否则不需要时区。

Instant now = Instant.now();

数据库

要发送到您的数据库,首先确保您已将表中的列定义为符合 SQL 标准的内容TIMESTAMP WITH TIME ZONE。顺便说一句,数据库中对日期时间类型的支持各不相同,其中一些做得比其他的好得多。

希望 JDBC 驱动程序有一天会更新以直接处理 java.time 类型。在那之前,我们在向/从数据库传输数据时必须转换为 java.sql 类型。旧的 java.sql 类具有促进这些转换的新方法。

java.sql.Timestamp

对于像这样的日期时间值Instant,我们需要java.sql.Timestamp类及其from( Instant )方法。

java.sql.Timestamp ts = java.sql.Timestamp.from( now );

避免工作,java.sql.Timestamp因为它是早期 Java 日期时间类的旧设计糟糕的混乱的一部分。仅将它们用于数据库传输,然后立即转换到 java.time。

Instant instant = ts.toInstant();

如此简单,不涉及时区或与 UTC 的偏移。、Instantjava.sql.Timestamp数据库存储均采用 UTC 格式

ZonedDateTime

当您确实需要切换到某个地区的挂钟时间时,请应用时区。

ZoneId zoneId = ZoneId.of( "America/Chicago" );  // Or "America/New_York" and so on.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
于 2016-04-16T00:10:41.470 回答
0

如果您的数据库允许您将时间戳与时区一起存储,您应该继续将其保存为时间戳。

如果没有,我建议您根据您的时区(或 GMT)存储日期时间。在表中添加一个额外的列来保存用户时区的值。

当您从数据库中获取值时,您可以将其转换为用户的时区。避免只存储日期。

于 2016-04-16T03:38:56.500 回答
0

嗯?日期没有时区,所以这可能就是它失败的原因。也许这就是你要找的:

Date.from(java.time.ZonedDateTime.now().toInstant());
于 2016-04-15T22:42:41.193 回答