2017-06-26 6 views
4
ZonedDateTime zdt = ZonedDateTime.of(2015, 10, 18, 0, 30, 0, 0, 
    ZoneId.of("America/Sao_Paulo")); 
System.out.println(zdt); // 2015-10-18T01:30-02:00[America/Sao_Paulo] 

können Sie sehen, die Stunde ist 1, während wir die Stunde als 0 gesetzt und der Zeitzone ist UTC-02:00 während der Sommerzeitzone UTC-03:00 sein sollte.ZonedDateTime würde die gleiche Zeitzone des Winters verwenden, wenn Sommerzeit Sommerzeit?

Aber hier ist ein anderes Beispiel:

ZonedDateTime zdt = ZonedDateTime.of(2015, 10, 18, 0, 30, 0, 0, 
    ZoneId.of("America/Los_Angeles")); 
System.out.println(zdt); //2015-10-18T00:30-07:00[America/Los_Angeles] 

Sie können die Sommerzeitzone zu sehen ist UTC-07:00 und die Stunde ist 0 wie wir eingestellt.

Warum unterscheiden sie sich?

Antwort

2

Wie bereits in @Misha's answer erklärt, es auf Grund geschieht nach Sommerzeit Regeln.

In São Paulo beginnt die Sommerzeit um Mitternacht des 2015-10-18: die Uhren bewegen sich 1 Stunde vorwärts, also "springt" sie von 23:59:59 zu 01:00:00. Es gibt eine Lücke zwischen 00:00:00 und 00:59:59, so dass die Zeit 00:30 entsprechend angepasst wird.

können Sie prüfen, ob das Datum und die Uhrzeit der Zeitzone die ZoneRules und ZoneOffsetTransition Klassen gelten:

ZoneId sp = ZoneId.of("America/Sao_Paulo"); 
ZoneRules rules = sp.getRules(); 
// check if 2015-10-18 00:30 is valid for this timezone 
LocalDateTime dt = LocalDateTime.of(2015, 10, 18, 0, 30); 
List<ZoneOffset> validOffsets = rules.getValidOffsets(dt); 
System.out.println(validOffsets.size()); // size is zero, no valid offsets at 00:30 

Die getValidOffsets method kehrt alle gültigen Offsets für den angegebenen Datum/Uhrzeit. Wenn die Liste leer ist, bedeutet dies, dass das Datum/die Zeit in dieser Zeitzone nicht existiert (normalerweise wegen der Sommerzeit springen die Uhren vorwärts).

Wenn das Datum/Zeit in einer Zeitzone vorhanden ist, wird ein Offset zurückgegeben:

ZoneId la = ZoneId.of("America/Los_Angeles"); 
rules = la.getRules(); 
validOffsets = rules.getValidOffsets(dt); 
System.out.println(validOffsets.size()); // 1 - date/time valid for this timezone 
System.out.println(validOffsets.get(0)); // -07:00 

Für Los_Angeles Zeitzone 1 gültige Offset zurückgegeben: -07:00.

PS: Offset-Änderungen treten normalerweise aufgrund von DST auf, aber das ist nicht immer der Fall. DST und Offsets werden von Regierungen und Gesetzen definiert und können sich jederzeit ändern. Eine Lücke im gültigen Offset kann also auch bedeuten, dass eine solche Änderung stattgefunden hat (einige Politiker haben sich dafür entschieden, den Standard-Offset des Landes zu ändern, so dass die Lücke nicht unbedingt mit DST zusammenhängen muss).

Sie können auch überprüfen, wenn die Änderung auftritt, und was ist der vor Offset und danach:

ZoneId sp = ZoneId.of("America/Sao_Paulo"); 
ZoneRules rules = sp.getRules(); 

// get the previous transition (the last one that occurred before 2015-10-18 00:30 in Sao_Paulo timezone 
ZoneOffsetTransition t = rules.previousTransition(dt.atZone(sp).toInstant()); 
System.out.println(t); 

Die Ausgabe lautet:

Transition [Gap bei 2015-10-18T00: 00-03: 00 bis -02: 00]

Es bedeutet, dass es eine Lücke bei 2015-10-18T00:00 (Uhren vorwärts bewegt), und die von 012 ändern versetzt wirdzu -02:00 (so bewegt sich die Uhr 1 Stunde vorwärts).

Sie können auch separat alle diese Informationen erhalten:

System.out.println(t.getDateTimeBefore() + " -> " + t.getDateTimeAfter()); 
System.out.println(t.getOffsetBefore() + " -> " + t.getOffsetAfter()); 

Die Ausgabe lautet:

2015-10-18T00: 00 -> 2015-10-18T01: 00
-03 : 00 -> -02: 00

Es zeigt, dass bei 00:00 die Uhr direkt auf 01:00 bewegt (so 00:30 kann nicht existieren). In der zweiten Zeile die Offsets vor und nach dem Wechsel.


Wenn Sie die Übergänge in Los_Angeles Zeitzone zu überprüfen, werden Sie sehen, dass seine DST beginnt und endet an einem anderen Datum:

ZoneId la = ZoneId.of("America/Los_Angeles"); 
rules = la.getRules(); 

// 2015-10-18 00:30 in Los Angeles 
Instant instant = dt.atZone(la).toInstant(); 
System.out.println(rules.previousTransition(instant)); 
System.out.println(rules.nextTransition(instant)); 

Die Ausgabe lautet:

Transition [Gap bei 2015-03-08T02: 00-08: 00 bis -07: 00]
Transition [Überlappung bei 2015-11-01T02: 00-07: 00 bis -08: 00]

Also, in Los_Angeles Zeitzone, startet DST um 2015-03-08 und endet um 2015-11-01. Deshalb sind unter 2015-10-18 alle Stunden gültig (es gibt keine Anpassung, wie es in der Zeitzone Sao_Paulo geschieht).


Einige Zeitzonen haben Übergangsregeln (wie „DST beginnt am dritten Sonntag im Oktober“) anstelle von Transitionen nur (wie „DST beginnt an diesem speziellen Datum und Uhrzeit“), und Sie können auch sie verwenden, sofern vorhanden:

ZoneId sp = ZoneId.of("America/Sao_Paulo"); 
ZoneRules rules = sp.getRules(); 

// hardcoded: Sao_Paulo timezone has 2 transition rules, the second one is relative to October 
// but you should always check if the list is not empty 
ZoneOffsetTransitionRule tr = rules.getTransitionRules().get(1); 
// get the transition for year 2015 
ZoneOffsetTransition t = tr.createTransition(2015); 
// use t the same way as above (the output will be the same) 

eine weitere Möglichkeit, zu überprüfen, ob ein Datum und Zeit gültig ist für einige Zeitzone die ZonedDateTime.ofStrict Methode zu verwenden ist, wirft die eine Ausnahme, wenn die da te und die Zeit ist ungültig für eine Zeitzone:

ZoneId sp = ZoneId.of("America/Sao_Paulo"); 
ZoneId la = ZoneId.of("America/Los_Angeles"); 
LocalDateTime dt = LocalDateTime.of(2015, 10, 18, 0, 30); 

System.out.println(ZonedDateTime.ofStrict(dt, ZoneOffset.ofHours(-7), la)); // OK 
System.out.println(ZonedDateTime.ofStrict(dt, ZoneOffset.ofHours(-3), sp)); // throws java.time.DateTimeException 

Der erste Fall in Ordnung ist, weil ein von -7 Offset gilt für Los Angeles, für die angegebene Datum/Zeit.Der zweite Fall löst eine Ausnahme aus, da ein Versatz von -3 für São Paulo zum angegebenen Datum/Uhrzeit ungültig ist.

+0

Vielen Dank, @Hugo. –

6

Dies passiert, weil die Zeit, die Sie ausgewählt haben, in der Nacht zwischen Mitternacht und 01:00 fällt, wenn Brasilien in die Sommerzeit wechselt. Diese Zeit tatsächlich unmöglich ist, und Sie das Verhalten in den documentation beschrieben, so erhalten:

Im Fall einer Lücke, wenn die Uhren vorwärts springen, gibt es keine gültige Offset. Stattdessen wird das lokale Datum und die Uhrzeit später durch die Länge der Lücke angepasst. Bei einer typischen einstündigen Änderung der Sommerzeit wird das lokale Datum um eine Stunde später in den Offset verschoben, der normalerweise "Sommer" entspricht.

Sie können das gleiche Verhalten in Los_Angeles Zone beobachten, indem eine Zeit von 2.00 bis 03.00 auf der entsprechenden Nacht März Kommissionierung:

zdt = ZonedDateTime.of(2015, 3, 8, 2, 30, 0, 0, 
     ZoneId.of("America/Los_Angeles")); 
System.out.println(zdt); 
+0

danke für mein Missverständnis anzupassen. nach oben abstimmen. –

+0

Danke, @Misha. –