为什么 java 8 现在在 LocalDateTime class 中有方法

Why java 8 has now method in LocalDateTime class

我们知道,在 java 中,我们可以使用现有的 API 来获取当前日期和时间,与新的 LocalDateTime class now() 方法。

tl;博士

  • 如果指的是 DateCalendarSimpleDateFormat,这些都是可怕的旧 类,现在是遗产。 从不使用。
  • 仅使用现代 java.time 类.
  • LocalDateTime 不能 表示一个时刻,因为它故意缺少任何时区或与 UTC 的偏移量的概念。所以LocalDateTime.now没有实际用处。
  • 使用特定时区的 Instant.now for UTC, or ZonedDateTime.now 捕捉当前时刻。

避免遗留日期时间类

如果“现有 API”是指旧日期时间 类,例如 DateCalendarSimpleDateFormat,你应该避免那些。虽然它们是在日期时间处理方面出于善意的行业领先尝试,但事实证明它们设计不佳、令人困惑且麻烦。他们现在 legacy.

使用java.time

而是使用 java.time 类。添加到 Java 8 及更高版本。许多功能也被反向移植到 Java 6 & 7 & Android。

Local… 类型

“本地...”类 没有任何 offset-from-UTC or time zone 的概念。因此,它们只是关于可能时刻的模糊概念。如果没有偏移量或区域,则没有实际意义。

本地日期时间的一个例子是圣诞节开始的时间,2016-12-25T00:00:00。在我们应用偏移量或区域之前,这不会确定时间线上的特定点。圣诞节在东部开始得比较早。这就是为什么 Santa 在太平洋地区开始交付,例如在新西兰奥克兰的午夜,并在午夜较晚时向亚洲进发,然后在午夜开始后将驯鹿运往印度,依此类推。

LocalDateTime不经常使用

所以虽然可能有调用 now on LocalDateTime 的用例,但我无法想象。

LocalDateTime 的主要用途是解析缺少任何偏移量或区域指示的字符串。此类字符串设计不佳,因为它们不完整。您会在不指定货币的情况下传达价格吗?同样,指定日期和时间而不指定 offset/zone 也是不明智的。无论如何,当您确实有缺少 offset/zone 的字符串时,请使用 LocalDateTime.

进行解析
LocalDateTime ldt = LocalDateTime.parse( "2016-01-23T12:34:56.789" );

如果您知道给定场景的预期偏移量,请应用它。

ZoneOffset offset = ZoneOffset.ofHours( -7 );
OffsetDateTime odt = ldt.atOffset( offset );  // Now we have a moment, a specific point on the timeline.

更好的是,如果您因为给定的场景而知道时区,请使用时区而不是偏移量。区域是一个偏移量 加上 处理异常的规则集,例如夏令时 (DST)。

ZoneId zone = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zone );  // Now we have a moment, a specific point on the timeline.

在常见的商业应用程序中,我们往往关心精确的时刻:发票何时到达、合同何时到期、预约开始时间等。对于此类时间轴上的点值,我们使用 Instant, OffsetDateTime, and ZonedDateTime。搜索 Stack Overflow 以获取更多示例和更多讨论。其中每一个都提供了一个 now 方法。调用他们的 now 方法可以在捕获当前时刻的同时保留重要的 offset/zone 信息。相反,调用 LocalDateTime.now 会故意丢弃 offset/zone 信息,很少是你想要的。

提示:始终将可选的偏移量或区域参数传递给now
如果省略,则隐式依赖于 JVM 当前的默认时区被应用。这个默认值可以在运行时的任何时候通过该 JVM 中任何应用程序上的任何代码更改。最好明确指定您的 desired/expected 偏移量或区域。恕我直言,应该要求那个可选参数来提醒程序员他们必须始终有意识地了解时区。

当前时刻

使用 Instant 以 UTC 格式捕获当前时刻。

根据您的 JVM 实现、主机硬件时钟和主机 OS 的限制,可能会以纳秒级的分辨率捕获,但更可能是微秒级或毫秒级。

Instant instant = Instant.now() ;  // Capture current moment in UTC.

从 UTC 调整为特定地区(时区)人们使用的挂钟时间。

ZoneId z = ZoneId.of( "Africa/Casablanca" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

或者,作为快捷方式,跳过 Instant 部分。

ZonedDateTime zdt = ZonedDateTime.now( z ) ;

如果省略时区参数,则隐式应用 JVM 当前的默认时区。最好指定您的 desired/expected 时区。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些 类 取代了麻烦的旧 legacy 日期时间 类,例如 java.util.DateCalendar, & 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.