asieira
Por lo tanto, espero que este código funcione con el nuevo paquete de fecha/hora de Java 8, ya que todo lo que hace es convertir un ZonedDateTime determinado en una cadena y viceversa utilizando la misma instancia integrada de DateTimeFormatter (ISO_INSTANT):
ZonedDateTime now = ZonedDateTime.now();
System.out.println(ZonedDateTime.parse(
now.format(DateTimeFormatter.ISO_INSTANT),
DateTimeFormatter.ISO_INSTANT));
Pero aparentemente no:
Exception in thread "main" java.time.format.DateTimeParseException: Text '2014-09-01T19:37:48.549Z' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {MilliOfSecond=549, NanoOfSecond=549000000, MicroOfSecond=549000, InstantSeconds=1409600268},ISO of type java.time.format.Parsed
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1918)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1853)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
Ya he visto esta entrada, pero no me ayudó porque necesito un objeto ZonedDateTime y no uno local y también porque ya tengo 8u20 instalado: No se puede obtener ZonedDateTime de TemporalAccessor usando DateTimeFormatter y ZonedDateTime en Java 8
¿Alguien tiene idea de lo que está pasando aquí?
jodastephen
los ISO_INSTANT
el formateador está documentado aquí – “Este es un formateador de casos especiales destinado a permitir una forma legible por humanos de un Instant”. Como tal, este formateador está diseñado para usarse con un Instant
No un ZonedDateTime
.
Formateo
Al formatear, ISO_INSTANT
puede formatear cualquier objeto temporal que pueda proporcionar ChronoField.INSTANT_SECONDS
y ChronoField.NANO_OF_SECOND
. Ambas cosas Instant
y ZonedDateTime
puede proporcionar estos dos campos, por lo que ambos funcionan:
// works with Instant
Instant instant = Instant.now();
System.out.println(DateTimeFormatter.ISO_INSTANT.format(instant));
// works with ZonedDateTime
ZonedDateTime zdt = ZonedDateTime.now();
System.out.println(zdt.format(DateTimeFormatter.ISO_INSTANT));
// example output
2014-09-02T08:05:23.653Z
análisis
Al analizar, ISO_INSTANT
solo producirá ChronoField.INSTANT_SECONDS
y ChronoField.NANO_OF_SECOND
. Un Instant
se puede construir a partir de esos dos campos, pero ZonedDateTime
requiere un ZoneId
también:
para analizar un ZonedDateTime
es esencial que una zona horaria ZoneId
está presente. La zona horaria se puede (a) analizar desde la cadena, o (b) especificar al formateador (usando JDK 8u20):
// option a - parsed from the string
DateTimeFormatter f = DateTimeFormatter.ISO_DATE_TIME;
ZonedDateTime zdt = ZonedDateTime.parse("2014-09-02T08:05:23.653Z", f);
// option b - specified in the formatter - REQUIRES JDK 8u20 !!!
DateTimeFormatter f = DateTimeFormatter.ISO_INSTANT.withZone(ZoneId.systemDefault());
ZonedDateTime zdt = ZonedDateTime.parse("2014-09-02T08:05:23.653Z", f);
Consulte la documentación para ISO_ZONED_DATE_TIME
, ISO_OFFSET_DATE_TIME
y ISO_DATE_TIME
(cualquiera de estos tres se puede utilizar para analizar un ZonedDateTime
sin especificar withZone()
).
Resumen
los ISO_INSTANT
formatter es un formateador de casos especiales diseñado para trabajar con Instant
. Si está usando un ZonedDateTime
debe usar un formateador diferente, como ISO_DATE_TIME
o ISO_ZONED_DATE_TIME
.
-
Lo extraño de esto es que la Z final en la cadena generada es un indicador de zona horaria para UTC, por lo que la cadena contiene un indicador de zona horaria (en.wikipedia.org/wiki/ISO_8601#Time_zone_designators). Sin embargo, la documentación establece que esto solo funcionará por instantes, por lo que tiene toda la razón. Gracias.
– asieira
02/09/2014 a las 13:31
No estoy seguro, pero esto podría ser un error en Java 8. Tal vez tenía la intención de comportarse de esta manera, pero creo que la solución alternativa que voy a proponerle debería ser el comportamiento predeterminado (cuando no hay ZoneId especificado, simplemente tome el valor predeterminado del sistema):
ZonedDateTime now = ZonedDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT
.withZone(ZoneId.systemDefault());
System.out
.println(ZonedDateTime.parse(now.format(formatter), formatter));
Hay un error similar que se solucionó en OpenJDK: JDK-8033662 – pero es solo similar, no exactamente igual.
asilias
No sé si es el comportamiento esperado o no (probablemente lo sea), pero técnicamente el ISO_INSTANT
formateador no incluye una zona horaria. Si intentas con un DateTimeFormatter.ISO_ZONED_DATE_TIME
formateador en su lugar obtendrá lo que espera.
si estás usando org.threeten.bp
de java 1.8Aquí está un Hoja de trucos sobre cómo tratar con String to Date y viceversa.
Fecha para cadena
val date = Date()
val calendar = Calendar.getInstance().apply { time = date }
val zonedDateTime = DateTimeUtils.toZonedDateTime(calendar)
val formattedDate = DateTimeFormatter.ISO_INSTANT.format(zonedDateTime)
Cadena hasta la fecha
val dateString = "2020-03-04T09:04:43.835Z"
val dateInstant = Instant.from(DateTimeFormatter.ISO_INSTANT.parse(dateString))
DateTimeUtils.toDate(dateInstant)