java parsing datetime java-8 iso8601

No se puede analizar la cadena en formato ISO 8601, sin dos puntos en el desplazamiento, a Java 8 Date



parsing datetime (1)

Estoy un poco frustrado con la funcionalidad de formato / análisis de fecha de Java 8. Estaba tratando de encontrar la configuración de Jackson y DateTimeFormatter para analizar la "2018-02-13T10:20:12.120+0000" a cualquier fecha de Java 8, y no lo encontré.
Este es el ejemplo de java.util.Date que funciona bien:

Date date = new SimpleDateFormat("yyyy-MM-dd''T''hh:mm:ss.SSSZZZ") .parse("2018-02-13T10:20:12.120+0000");

El mismo formato no funciona con la nueva API de fecha y hora

ZonedDateTime dateTime = ZonedDateTime.parse("2018-02-13T10:20:12.120+0000", DateTimeFormatter.ofPattern("yyyy-MM-dd''T''hh:mm:ss.SSSZZZ"));

Deberíamos poder formatear / analizar la fecha en cualquier formato adecuado para la aplicación FE UI. Tal vez no entiendo o confundo algo, pero creo que java.util.Date brinda más flexibilidad de formato y es más fácil de usar.


tl; dr

Hasta que se solucione el error:

OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" , DateTimeFormatter.ofPattern( "uuuu-MM-dd''T''HH:mm:ss.SSSX" ) )

Cuando se corrige el error:

OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" )

Detalles

Estás usando las clases equivocadas.

Evite las antiguas clases problemáticas, como Date , Calendar y SimpleDateFormat . Ahora suplantado por las clases java.time .

La clase ZonedDateTime que usó es buena, es parte de java.time. Pero está destinado a una zona horaria completa. Su cadena de entrada tiene simplemente un offset-from-UTC . Una zona horaria completa, en contraste, es una colección de compensaciones vigentes para una región en diferentes puntos en el tiempo, pasado, presente y futuro. Por ejemplo, con el horario de verano (DST) en la mayor parte de América del Norte, las compensaciones cambian dos veces al año y se vuelven más pequeñas en la primavera a medida que adelantamos los relojes una hora, y restauramos a un valor más largo en el otoño cuando los retrasamos hora.

OffsetDateTime

Para solo un desplazamiento en lugar de una zona horaria, use la clase OffsetDateTime .

Su cadena de entrada cumple con el estándar ISO 8601 . Las clases java.time utilizan los formatos estándar de forma predeterminada al analizar / generar cadenas. Por lo tanto, no es necesario especificar un patrón de formato.

OffsetDateTime odt = OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" );

Bueno, eso debería haber funcionado. Desafortunadamente, hay un error en Java 8 (al menos hasta la Actualización 121 de Java 8) en el que esa clase no puede analizar un desplazamiento omitiendo los dos puntos entre horas y minutos. Entonces el error muerde en +0000 pero no en +00:00 . Entonces, hasta que llegue una solución, tiene la opción de dos soluciones: (a) un truco, manipulando la cadena de entrada, o (b) defina un patrón de formato explícito.

El truco: manipula la cadena de entrada para insertar los dos puntos.

String input = "2018-02-13T10:20:12.120+0000".replace( "+0000" , "+00:00" ); OffsetDateTime odt = OffsetDateTime.parse( input );

DateTimeFormatter

La solución más sólida es definir y pasar un patrón de formato en un objeto DateTimeFormatter .

String input = "2018-02-13T10:20:12.120+0000" ; DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd''T''HH:mm:ss.SSSX" ); OffsetDateTime odt = OffsetDateTime.parse( input , f );

odt.toString (): 2018-02-13T10: 20: 12.120Z

Por cierto, aquí hay un consejo: descubrí que con muchos protocolos y bibliotecas, su vida es más fácil si sus desplazamientos siempre tienen dos puntos, siempre tienen horas y minutos (incluso si los minutos son cero) y siempre usan un relleno cero ( -05:00 lugar de -5 ).

DateTimeFormatterBuilder

Para un formateador más flexible, creado a través de DateTimeFormatterBuilder , vea esta excelente respuesta en una pregunta duplicada.

Instant

Si desea trabajar con valores que siempre están en UTC (y debería hacerlo), extraiga un objeto Instant .

Instant instant = odt.toInstant();

ZonedDateTime

Si desea ver ese momento a través de la lente del reloj de pared de alguna región, aplique una zona horaria.

ZoneId z = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = odt.atZoneSameInstant( z );

Vea este código en vivo en IdeOne.com .

Todo esto se ha cubierto muchas veces en muchas respuestas para muchas preguntas. Busque a fondo antes de publicar. Habría descubierto muchas docenas, si no cientos, de ejemplos.

Sobre java.time

El marco java.time está integrado en Java 8 y java.time posteriores. Estas clases suplantan a las antiguas clases problemáticas de fecha y hora legacy , como java.util.Date , Calendar y SimpleDateFormat .

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Para obtener más información, consulte el Tutorial de Oracle . Y busque para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No necesita cadenas, no necesita clases java.sql.* .

¿Dónde obtener las clases java.time?

El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval , YearWeek , YearQuarter y more .