Formatta LocalDateTime con Timezone in Java8


121

Ho questo semplice codice:

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

Quindi otterrò la seguente eccezione:

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)

Come risolvere questo problema?

Risposte:


212

LocalDateTimeè una data-ora senza un fuso orario. Hai specificato il simbolo del formato di offset del fuso orario nel formato, tuttavia, LocalDateTimenon dispone di tali informazioni. Ecco perché si è verificato l'errore.

Se vuoi informazioni sul fuso orario, dovresti usare ZonedDateTime.

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

3
Super utile. Non sono sicuro che avrei catturato il pezzo del fuso orario così facilmente. Bella risposta. Grazie!
Laran Evans,

40

Il prefisso "Local" in JSR-310 (aka java.time-package in Java-8) non indica che ci sono informazioni sul fuso orario nello stato interno di quella classe (qui :) LocalDateTime. Nonostante il nome spesso fuorviante tali classi come LocalDateTimeoLocalTime hanno NESSUNA informazione o offset sul fuso orario .

Si è tentato di formattare un tipo temporale di questo tipo (che non contiene alcun offset) con informazioni di offset (indicate dal simbolo del pattern Z). Quindi il formattatore tenta di accedere a informazioni non disponibili e deve lanciare l'eccezione che hai osservato.

Soluzione:

Utilizzare un tipo che abbia una tale differenza o informazioni sul fuso orario. In JSR-310 questo è OffsetDateTime(che contiene un offset ma non un fuso orario che include le regole DST) o ZonedDateTime. È possibile controllare tutti i campi supportati di questo tipo cercando il metodo isSupported (TemporalField). . Il campo OffsetSecondsè supportato in OffsetDateTimee ZonedDateTime, ma non in LocalDateTime.

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

Con quale prefisso avresti sostituito il prefisso "Locale" per evitare confusione?
Matteo

@Matthew C'è stato anche un dibattito avviato da Bank Credit Suisse suggerendo il nome PlainDateTimeecc. Probabilmente meglio perché il prefisso "plain" indica che non c'è niente di più che solo data e ora. Se fossimo ancora prima di Java v1.0, nessun prefisso sarebbe stato migliore, ma nomi come Dateecc. Sono già riservati dal vecchio JDK.
Meno Hochschild

-4

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.