2014-08-29 6 views
52

Ich habe die diesen einfachen Code:Format Local mit Zeitzone in Java8

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

Dann werde ich folgende Ausnahme erhalten:

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 dieses Problem zu lösen?

+0

nicht sicher, ich denke Z braucht einfache Anführungszeichen um ihn herum. – msknapp

Antwort

88

LocalDateTime ist eine Datum-Uhrzeit ohne Zeitzone. Sie haben das Zeitzonen-Offset-Format-Symbol im Format angegeben, jedoch enthält LocalDateTime keine solche Information. Deshalb ist der Fehler aufgetreten.

Wenn Sie Zeitzone Informationen möchten, sollten Sie ZonedDateTime verwenden.

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z"); 
ZonedDateTime.now().format(FORMATTER) 
=> "20140829 14:12:22.122000 +09" 
+2

Super hilfreich. Ich bin mir nicht sicher, ob ich das Timezone-Stück so einfach gefangen hätte. Gute Antwort. Vielen Dank! –

29

Das Präfix "Local" in JSR-310 (auch bekannt als java.time-Paket in Java-8) bedeutet nicht, dass es eine Zeitzoneninformation in internem Zustand dieser Klasse ist (hier: LocalDateTime). Trotz des oft irreführenden Namens haben solche Klassen wie LocalDateTime oder LocalTime KEINE Zeitzoneninformation oder Offset.

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

Lösung:

Verwenden einer Art, die einen solchen Versatz oder Zeitzone Informationen hat. In JSR-310 ist dies entweder OffsetDateTime (enthält einen Offset, aber keine Zeitzone mit DST-Regeln) oder ZonedDateTime. Sie können sich alle unterstützten Felder eines solchen Typs ansehen, indem Sie nach der Methode isSupported(TemporalField). suchen. Das Feld OffsetSeconds wird in OffsetDateTime und ZonedDateTime unterstützt, jedoch nicht in LocalDateTime.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z"); 
String s = ZonedDateTime.now().format(formatter); 
+0

Mit welchem ​​Präfix hätten Sie das Präfix "Local" ersetzt, um Verwechslungen zu vermeiden? – Matthew

+0

@Matthew Es gab auch eine [Debatte] (https://sourceforge.net/p/threeten/mailman/message/29960633/) initiiert von der Bank Credit Suisse, die den Namen 'PlainDateTime' etc. vorschlägt. Wahrscheinlich besser, weil das Präfix" plain "zeigt an, 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 "Date" usw. sind bereits vom alten JDK reserviert. –