Formatieren Sie LocalDateTime mit Timezone in Java8

121

Ich habe diesen einfachen Code:

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
LocalDateTime.now().format(FORMATTER)

Dann bekomme ich folgende Ausnahme:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds
at java.time.LocalDate.get0(LocalDate.java:680)
at java.time.LocalDate.getLong(LocalDate.java:659)
at java.time.LocalDateTime.getLong(LocalDateTime.java:720)
at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
at java.time.format.DateTimeFormatterBuilder$OffsetIdPrinterParser.format(DateTimeFormatterBuilder.java:3315)
at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2182)
at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1745)
at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1719)
at java.time.LocalDateTime.format(LocalDateTime.java:1746)

Wie kann ich dieses Problem beheben?

Carfield
quelle

Antworten:

212

LocalDateTimeist eine Datums- und Uhrzeit ohne Zeitzone. Sie haben das Symbol für das Zeitzonenversatzformat im Format angegeben, LocalDateTimeverfügen jedoch nicht über solche Informationen. Deshalb ist der Fehler aufgetreten.

Wenn Sie Zeitzoneninformationen wünschen, sollten Sie diese verwenden ZonedDateTime.

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
ZonedDateTime.now().format(FORMATTER);
=> "20140829 14:12:22.122000 +09"
ntalbs
quelle
3
Super hilfreich. Ich bin mir nicht sicher, ob ich das Zeitzonenstück so leicht gefangen hätte. Gute Antwort. Danke dir!
Laran Evans
40

Das Präfix "Local" in JSR-310 (auch bekannt als java.time-package in Java-8) gibt nicht an, dass sich im internen Status dieser Klasse Zeitzoneninformationen befinden (hier :) LocalDateTime. Trotz des oft irreführenden Namens mögen LocalDateTimeoder LocalTimehaben solche Klassen KEINE Zeitzoneninformationen oder Offset .

Sie haben versucht, einen solchen zeitlichen Typ (der keinen Versatz enthält) mit Versatzinformationen (angezeigt durch das Mustersymbol Z) zu formatieren. Der Formatierer versucht also, auf nicht verfügbare Informationen zuzugreifen, und muss die von Ihnen beobachtete Ausnahme auslösen.

Lösung:

Verwenden Sie einen Typ mit solchen Offset- oder Zeitzoneninformationen. In JSR-310 ist dies entweder OffsetDateTime(das einen Offset, aber keine Zeitzone einschließlich DST-Regeln enthält) oder ZonedDateTime. Sie können alle unterstützten Felder eines solchen Typs durch Nachschlagen der Methode isSupported (TemporalField) überwachen. . Das Feld OffsetSecondswird in OffsetDateTimeund ZonedDateTime, aber nicht in unterstützt LocalDateTime.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
String s = ZonedDateTime.now().format(formatter);
Meno Hochschild
quelle
Mit welchem ​​Präfix hätten Sie das Präfix "Lokal" ersetzt, um Verwechslungen zu vermeiden?
Matthew
@Matthew Es gab auch eine Debatte, die von der Bank Credit Suisse initiiert wurde und den Namen PlainDateTimeusw. vorschlug . Wahrscheinlich besser, weil das Präfix "plain" anzeigt, dass es nicht mehr als nur Datum und Uhrzeit gibt. Wenn wir noch vor Java v1.0 wären, wäre kein Präfix besser gewesen, aber Namen wie Dateusw. sind bereits vom alten JDK reserviert.
Meno Hochschild
-4

LocalDateTime.now (). Format (DateTimeFormatter.ofPattern ("yyyyMMdd HH: mm: ss.SSSSSS Z"));

karthik r
quelle