Java8Instant 类没有 plusHours 方法,尽管如 Oracle 教程示例代码所示

Instant类编写的 < em > Oracle 教程 页面显示了以下示例代码:

Instant oneHourLater = Instant.now().plusHours(1);

当我尝试编译这段代码时,编译器会抛出错误:

  • 错误
InstantPrint.java:6: error: cannot find symbol
Instant oneHourLater = Instant.now().plusHours(1);
^
symbol:   method plusHours(int)
location: class Instant

但是这个 Java 文档提到了 plusHours()方法,但是我检查了这个 Instant类,它不包含 plusHours()方法。

此后,为什么在示例中提到这个 plusHours()方法?

3536 次浏览

The Oracle Tutorial is incorrect

Unfortunately, the Oracle Tutorial is incorrect on this matter. That line of example code is simply wrong. Good catch on your part.

This error is quite unfortunate as the Tutorial is otherwise a fine resource for learning and studying Java.

Instant::plus

The Instant class has no such method as plusHours defined in either Java 8 or Java 9.

Instead, you can call the plus method, and specify hours.

Instant later = instant.plus( 1 , ChronoUnit.HOURS ) ;

ZonedDateTime::plusHours

The Instant class is a basic building-block class, indicating a moment on the timeline in UTC. Usually when performing manipulations such as adding hours, you’ll likely want to account for anomalies such as Daylight Saving Time, and so you will care about time zone. For that, use the ZonedDateTime class. That class does offer a convenient plusHours method, a likely source of the confusion for the ZonedDateTime0 authors.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same moment, but viewed through the lens of a region’s wall-clock time.
ZonedDateTime zdtLater = zdt.plusHours( 1 ) ;

Instant versus ZonedDateTime

Let's look at an example of an anomaly in adding hours. When zoned, we add an hour to the particular moment of 1 AM on March 23, 2017 and of course expect 2 AM, but we are surprised to see 3 AM. Yet when we consider the very same moment in UTC rather than that particular time zone, the very same point on the timeline, adding an hour behaves as expected.

This particular anomaly is due to the adoption of Daylight Saving Time (DST) in most of North America, in particular here, the time zone America/New_York. In the Spring, the clocks "spring-forward" an hour. As the clocks strike 2 AM, they jump to 3 AM. So the hour of two o’clock never existed on that day.

// ZonedDateTime
LocalDate ld = LocalDate.of( 2017 , Month.MARCH , 12 ) ;
LocalTime lt = LocalTime.of( 1 , 0 ) ;
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
ZonedDateTime zdtOneHourLater = zdt.plusHours( 1 ) ;


System.out.println( "zdt: " + zdt ) ;
System.out.println( "zdtOneHourLater: " + zdtOneHourLater ) ;
System.out.println( "Yikes! 1 AM plus an hour is 3 AM? Yes, that is an anomaly known as Daylight Saving Time (DST)." ) ;
System.out.println( "" ) ;


// Instant
Instant instant = zdt.toInstant() ;  // Adjust into UTC. Same moment, same point on the timeline, but viewed by a different wall-clock.
Instant instantOneHourLater = instant.plus( 1 , ChronoUnit.HOURS ) ;


System.out.println( "instant: " + instant ) ;
System.out.println( "instantOneHourLater: " + instantOneHourLater ) ;
System.out.println( "Instant is always in UTC. So no anomalies, no DST. Adding an hour to 1 AM results in 2 AM every time." ) ;

See this code run live at IdeOne.com.

zdt: 2017-03-12T01:00-05:00[America/New_York]

zdtOneHourLater: 2017-03-12T03:00-04:00[America/New_York]

Yikes! 1 AM plus an hour is 3 AM? Yes, that is an anomaly known as Daylight Saving Time (DST).

instant: 2017-03-12T06:00:00Z

instantOneHourLater: 2017-03-12T07:00:00Z

Instant is always in UTC. So no anomalies, no DST. Adding an hour to 1 AM results in 2 AM every time.