Java 8 的新 Java 日期时间 API 是否处理夏令时?

Does Java 8's new Java Date Time API take care of DST?

我正在考虑使用新的 java 8 日期时间 API。我在谷歌上搜索了一下,发现 jodaTime 是 java 的不错选择,但仍然有兴趣了解这个新的 API 是如何工作的。

我将所有时间存储在我的数据存储中的 UTC 值中,并将根据用户的时区将它们转换为本地时区特定值。我可以找到许多介绍如何使用新 Java 日期时间 API 的文章。但是我不确定 API 是否会处理 DST 更改? 或者我们有更好的方法来处理 Date 吗?

我刚刚学习新的日期 API ,所以想听听您对处理 DateTime 并在用户时区的基础上显示它的想法。

是的,Java API 将考虑 DST 更改。

本教程很好地解释了如何在时区之间转换日期以及如何选择正确的 class 来表示日期: https://docs.oracle.com/javase/tutorial/datetime/iso/timezones.html

你也可以看看这个class,它代表了每个区域的规则: http://docs.oracle.com/javase/8/docs/api/java/time/zone/ZoneRules.html

特别是,此方法可以告诉您特定时刻是否处于夏令时: http://docs.oracle.com/javase/8/docs/api/java/time/zone/ZoneRules.html#isDaylightSavings-java.time.Instant-

这取决于您使用的class:

  • Instant 是全球时​​间线 (UTC) 上的瞬时点,与时区无关。
  • LocalDateLocalDateTime 没有时区的概念,但是调用 now() 当然会给你正确的时间。
  • OffsetDateTime 有时区,但不支持夏令时。
  • ZonedDateTime 具有完整的时区支持。

它们之间的转换通常需要一个时区,所以回答你的问题:

是的,Java 8 Date/Time 可以处理夏令时,如果你使用得当。

by Andreas 准确无误。

示例代码

让我们用一些代码来测试它。 DST in the United States & 加拿大今年将于 2015 年 11 月 1 日 02:00 到期。

让我们从“本地”日期时间的凌晨 1 点开始,这意味着不受时间轴的束缚并忽略时区问题。添加一个小时,我们得到凌晨 2 点。有道理。

LocalDateTime localDateTime = LocalDateTime.of( 2015 , Month.NOVEMBER , 1 , 1 , 0 ); // 1 AM anywhere. Not tied the timeline nor to any time zone.
LocalDateTime localDateTimeOneHourLater = localDateTime.plusHours( 1 ); // 2 AM anywhere, in no particular time zone, ignoring DST.

接下来我们将具体到特定的时区。我们将凌晨 1 点带到任何地方,并将其置于 America/Los_Angeles(美国西海岸)的时区。

ZoneId zoneId_LosAngeles = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime before = localDateTime.atZone( zoneId_LosAngeles ); // Assign a time zone, tying this vague date-time idea/generality to an actual moment on the time line.

现在加一个小时,看看我们得到了什么。如果忽略夏令时,我们将得到凌晨 2 点。如果遵守夏令时,我们会得到凌晨 1 点……当到达凌晨 2 点时,秋天(秋天)的 wall-clock time jumps back to 1 AM but with a new offset-from-UTC. This is colloquially known as "fall back"

ZonedDateTime after = before.plusHours( 1 ); // 2 AM? Nope, 1 AM because DST Daylight Saving Time expires at 2 AM Nov 1, 2015.

转储到控制台。

System.out.println( "localDateTime : " + localDateTime );
System.out.println( "localDateTimeOneHourLater : " + localDateTimeOneHourLater );
System.out.println( "before : " + before );
System.out.println( "after : " + after );

当运行时,我们得到这个输出。没有时区,凌晨 1 点 + 1 小时 = 凌晨 2 点。请记住,这些是 "local" 日期时间值, 不是 UTC。它们仅代表日期时间的模糊概念,而不是时间轴上的实际时刻。

localDateTime : 2015-11-01T01:00
localDateTimeOneHourLater : 2015-11-01T02:00

但是在 DST 到期日应用时区,我们得到不同的结果。请注意时间如何保持 01:00offset-from-UTC-07:00 变为 -08:00

before : 2015-11-01T01:00-07:00[America/Los_Angeles]
after : 2015-11-01T01:00-08:00[America/Los_Angeles]

如果我们调整为 UTC,也许这会更清楚、更容易验证。我们可以简单地通过访问 beforeafter 对象作为 Instant objects. The System.out.println then implicitly calls the toString 方法来做到这一点。

System.out.println( "before.toInstant : " + before.toInstant() );
System.out.println( "after.toInstant : " + after.toInstant() );

当运行.

before.toInstant : 2015-11-01T08:00:00Z
after.toInstant : 2015-11-01T09:00:00Z


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与您的数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 类.

在哪里获取java.time类?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.