Formatear LocalDateTime con Timezone en Java8

121

Tengo este código simple:

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

Entonces obtendré la siguiente excepción:

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)

Cómo resolver este problema?

carfield
fuente

Respuestas:

212

LocalDateTimees una fecha y hora sin zona horaria. Sin embargo, especificó el símbolo de formato de compensación de zona horaria en el formato, pero LocalDateTimeno tiene dicha información. Por eso ocurrió el error.

Si desea información sobre la zona horaria, debe usar ZonedDateTime.

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
ZonedDateTime.now().format(FORMATTER);
=> "20140829 14:12:22.122000 +09"
ntalbs
fuente
3
Muy útil. No estoy seguro de haber captado la pieza de la zona horaria tan fácilmente. Gran respuesta. ¡Gracias!
Laran Evans
40

El prefijo "Local" en JSR-310 (también conocido como java.time-package en Java-8) no indica que haya información de zona horaria en el estado interno de esa clase (aquí:) LocalDateTime. A pesar del nombre a menudo engañoso, clases comoLocalDateTime o LocalTimeNO tienen información de zona horaria o compensación .

Intentó formatear un tipo temporal de este tipo (que no contiene ningún desplazamiento) con información de desplazamiento (indicado por el símbolo de patrón Z). Entonces, el formateador intenta acceder a una información no disponible y debe lanzar la excepción que usted observó.

Solución:

Utilice un tipo que tenga dicha información de desplazamiento o zona horaria. En JSR-310, esto es OffsetDateTime(que contiene un desplazamiento pero no una zona horaria, incluidas las reglas de DST) o ZonedDateTime. Puede vigilar todos los campos admitidos de este tipo buscando en el método isSupported (TemporalField). . El campo OffsetSecondsse admite en OffsetDateTimey ZonedDateTime, pero no en LocalDateTime.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss.SSSSSS Z");
String s = ZonedDateTime.now().format(formatter);
Meno Hochschild
fuente
¿Con qué prefijo habría reemplazado el prefijo "Local" para evitar confusiones?
Mateo
@Matthew También hubo un debate iniciado por Bank Credit Suisse sugiriendo el nombre, PlainDateTimeetc. Probablemente mejor porque el prefijo "simple" indica que no hay nada más que solo fecha y hora. Si todavía estuviéramos antes de Java v1.0, ningún prefijo habría sido mejor, pero los nombres como Dateetc. ya están reservados por el antiguo JDK.
Meno Hochschild
-4

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

karthik r
fuente