Java 8 的新 Java Date Time API 是否负责 DST?示例代码关于 java.time

2022-09-01 12:24:33

我正在考虑使用新的java 8 Date Time API。我用谷歌搜索了一下,发现jodaTime是Java的好选择,但仍然有兴趣看看这个新的API是如何工作的。

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

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


答案 1

这取决于您使用的类:

  • Instant是全局时间线 (UTC) 上的瞬时点,与时区无关。
  • LocalDate并且没有时区的概念,但打电话当然会给你正确的时间。LocalDateTimenow()
  • OffsetDateTime具有时区,但不支持夏令时。
  • ZonedDateTime具有完整的时区支持。

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

是的,Java 8 日期/时间可以处理 DST,如果你使用得当的话。


答案 2

安德烈亚斯的答案是正确的。

示例代码

让我们用一些代码测试它。美国和加拿大的 DST 将于 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.

现在加一个小时,看看我们得到了什么。如果忽略 DST,我们将得到凌晨 2 点。如果DST受到尊重,我们将得到凌晨1点...当达到凌晨2点时,挂钟时间跳回到凌晨1点,但与UTC有一个新的偏移量。这在秋季(秋季)俗称“回退”。

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 AM + 1 小时 = 2 AM。请记住,这些是“本地”日期时间值,而不是 UTC。它们只代表了日期时间的模糊概念,而不是时间轴上的实际时刻。

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

但是,如果在 DST 到期当天应用时区,我们会得到不同的结果。请注意一天中的时间如何保留,但与 UTC 的偏移量从 更改为 。01:00-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,也许这会更清晰,更容易验证。我们只需将 和 对象作为即时对象进行访问即可。然后,System.out.println 隐式调用 toString 方法。beforeafter

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

Table of date-time types in Java, both modern and legacy


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,如java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

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

从哪里获取 java.time 类?

ThreeTen-Extra 项目通过其他类扩展了 java.time。这个项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuarter