Die Java 8 Instant-Klasse hat keine plusHours-Methode, obwohl sie im Beispielcode des Oracle Tutorial gezeigt wird

76

Die Oracle Tutorial- Seite für die InstantKlasse zeigt diesen Beispielcode:

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

Wenn ich versuche, diesen Code zu kompilieren, gibt der Compiler den Fehler aus:

  • Error
InstantPrint.java:6: Fehler: Symbol kann nicht gefunden werden
        Instant oneHourLater = Instant.now (). PlusHours (1);
                                            ^
  Symbol: Methode plusHours (int)
  Ort: Klasse Instant

In dieser Java-Dokumentation wird jedoch die plusHours()Methode erwähnt , aber ich überprüfe diese InstantKlasse und sie enthält keine plusHours()Methode.

Warum sollte diese plusHours()Methode danach im Beispiel erwähnt werden?

Ng Sharma
quelle
1
Link wurde nicht gefunden. Es gibt keine solche Methode docs.oracle.com/javase/8/docs/api/java/time/Instant.html
Ravi
1
Haben Sie darüber nachgedacht, es zu versuchen Instant#plus(long, TemporalUnit)
MadProgrammer
1
Überprüfen Sie erneut @ Ravi
Ng Sharma
2
Und ja, das Tutorial ist falsch: /
MadProgrammer
35
Abwärtswähler: Beachten Sie, dass diese Frage im offiziellen Oracle-Tutorial einen fehlerhaften Beispielcode entdeckt hat. Eine würdige Frage.
Basil Bourque

Antworten:

59

Das Oracle-Tutorial ist falsch

Leider ist das Oracle-Tutorial in dieser Angelegenheit falsch. Diese Zeile des Beispielcodes ist einfach falsch. Guter Fang von Ihrer Seite.

Dieser Fehler ist ziemlich unglücklich, da das Tutorial ansonsten eine gute Ressource zum Lernen und Lernen von Java ist.

Instant::plus

Die InstantKlasse verfügt weder plusHoursüber eine in Java 8 noch in Java 9 definierte Methode .

Stattdessen können Sie die plusMethode aufrufen und Stunden angeben.

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

ZonedDateTime::plusHours

Die InstantKlasse ist eine grundlegende Bausteinklasse, die einen Moment auf der Zeitachse in UTC angibt . Wenn Sie Manipulationen wie das Hinzufügen von Stunden ausführen, möchten Sie normalerweise Anomalien wie die Sommerzeit berücksichtigen , sodass Sie sich um die Zeitzone kümmern . Verwenden Sie dazu die ZonedDateTimeKlasse. Diese Klasse ist bieten eine bequemeplusHours Verfahren, eine wahrscheinliche Quelle der Verwirrung für die Tutorial Autoren.

Geben Sie einen richtigen Zeitzonennamen im Format continent/region, wie zum Beispiel America/Montreal, Africa/Casablancaoder Pacific/Auckland. Verwenden Sie niemals die Abkürzung für 3-4 Buchstaben, wie z. B. ESToder, ISTda es sich nicht um echte Zeitzonen handelt, die nicht standardisiert und nicht einmal eindeutig (!) Sind.

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 gegen ZonedDateTime

Schauen wir uns ein Beispiel für eine Anomalie beim Hinzufügen von Stunden an. In Zonen fügen wir dem jeweiligen Moment von 1 Uhr morgens am 23. März 2017 eine Stunde hinzu und erwarten natürlich 2 Uhr morgens, aber wir sind überrascht, 3 Uhr morgens zu sehen. Wenn wir jedoch denselben Moment in UTC und nicht diese bestimmte Zeitzone betrachten, verhält sich derselbe Punkt auf der Zeitachse, an dem eine Stunde hinzugefügt wird, wie erwartet.

Diese besondere Anomalie ist auf die Einführung der Sommerzeit (DST) in den meisten Teilen Nordamerikas zurückzuführen, insbesondere in der Zeitzone America/New_York. Im Frühling "springen" die Uhren eine Stunde vorwärts. Wenn die Uhren 2 Uhr morgens schlagen, springen sie auf 3 Uhr morgens. Die Zwei-Uhr-Stunde gab es an diesem Tag also nie.

// 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." ) ;

Sehen Sie diesen Code live auf IdeOne.com .

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

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

Huch! 1 Uhr plus eine Stunde ist 3 Uhr? Ja, das ist eine Anomalie, die als Sommerzeit (DST) bezeichnet wird.

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

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

Instant ist immer in UTC. Also keine Anomalien, keine Sommerzeit. Das Hinzufügen einer Stunde zu 1 Uhr morgens führt jedes Mal zu 2 Uhr morgens.

Basil Bourque
quelle
7
@ AK.Sharma @Ravi Diese Tutorial-Seite ist falsch , sowohl gemäß dem JavaDoc der InstantKlasse als auch gemäß der tatsächlichen Praxis mit Java 8 Update 144 (ich habe dies gerade getestet). Ich würde vorschlagen, einen Fehlerbericht einzureichen, aber diese Warnung oben auf den Seiten gibt mir das kranke Gefühl, dass Oracle die Wartung des Tutorials aufgibt.
Basil Bourque
"Die Instant-Klasse ist eine grundlegende Bausteinklasse, die einen Moment auf der Zeitachse in UTC angibt." Diese Aussage ist falsch. Wie viel Zeit kann in UTC sein?
abc667
@ abc667 An Instantist per Definition eine Anzahl von Sekunden plus Bruchsekunden seit dem Epochenreferenzmoment des ersten Moments von 1970 in UTC. Es Instantist also immer ein Moment in UTC. Dementsprechend toStringgeneriert das Verfahren eine Zeichenfolge, die das Datum und die Uhrzeit in UTC darstellt. In der Klassendokumentation finden Sie triviale Details, die für die praktische Verwendung in geschäftsorientierten Apps nicht relevant sind.
Basil Bourque
beides instant.plus(1, ChronoUnit.HOURS)und zdt.plushHours(1)Rückgabezeit entsprechend derselben Zeitinstanz ( later.equals(zdtLater.toInstant()))
jfs
@jfs Stimmt, aber ich bin mir nicht sicher, was Sie meinen. Eine ZonedDateTime ist nur ein Instant mit einer zugewiesenen Zeitzone. Das Hinzufügen einer Stunde zu beiden führt zum gleichen Moment auf der Zeitachse.
Basil Bourque