Conversión de una cadena compatible con ISO 8601 a java.util.Date


668

Estoy tratando de convertir una cadena con formato ISO 8601 a a java.util.Date.

Encontré que el patrón yyyy-MM-dd'T'HH:mm:ssZcumple con ISO8601 si se usa con una configuración regional (comparar muestra).

Sin embargo, usando java.text.SimpleDateFormat, no puedo convertir la cadena formateada correctamente 2010-01-01T12:00:00+01:00. Tengo que convertirlo primero 2010-01-01T12:00:00+0100, sin el colon.

Entonces, la solución actual es

SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.GERMANY);
String date = "2010-01-01T12:00:00+01:00".replaceAll("\\+0([0-9]){1}\\:00", "+0$100");
System.out.println(ISO8601DATEFORMAT.parse(date));

lo cual obviamente no es tan bueno. ¿Me estoy perdiendo algo o hay una solución mejor?


Responder

Gracias al comentario de JuanZe, encontré la magia de Joda-Time , también se describe aquí .

Entonces, la solución es

DateTimeFormatter parser2 = ISODateTimeFormat.dateTimeNoMillis();
String jtdate = "2010-01-01T12:00:00+01:00";
System.out.println(parser2.parseDateTime(jtdate));

O más simplemente, use el analizador predeterminado a través del constructor:

DateTime dt = new DateTime( "2010-01-01T12:00:00+01:00" ) ;

Para mí, esto es bueno.


243
Prepárese para recibir muchas respuestas de "Use JodaTime" ...
JuanZe

3
@ Ice09: si la documentación de API para DateTimeFormat es correcta (la documentación de JoDa puede ser engañosa, incorrecta o incompleta), el patrón que ha utilizado en su propia "respuesta" no es compatible con ISO8601.
jarnbjo

21
No estoy seguro de cuándo se agregó esto, pero la 'X' parece resolver este problema dentro de SimpleDateFormat. El patrón "aaaa-MM-dd'T'HH: mm: ssX" analiza con éxito el ejemplo en la pregunta.
mlohbihler

12
La 'X' está disponible desde Java 7.
Lars Grammel

3
¡Java 8 lo hace fácil! Hay una joya escondida por Adam en las respuestas a continuación: stackoverflow.com/a/27479533/1262901
Fabian Keller

Respuestas:


477

Desafortunadamente, los formatos de zona horaria disponibles para SimpleDateFormat (Java 6 y versiones anteriores) no son compatibles con ISO 8601 . SimpleDateFormat comprende cadenas de zona horaria como "GMT + 01: 00" o "+0100", esta última según RFC # 822 .

Incluso si Java 7 agregó soporte para descriptores de zona horaria de acuerdo con ISO 8601, SimpleDateFormat aún no puede analizar correctamente una cadena de fecha completa, ya que no tiene soporte para partes opcionales.

Reformatear su cadena de entrada usando regexp es ciertamente una posibilidad, pero las reglas de reemplazo no son tan simples como en su pregunta:

  • Algunas zonas horarias no tienen horas completas fuera de UTC , por lo que la cadena no termina necesariamente con ": 00".
  • ISO8601 permite que solo se incluya el número de horas en la zona horaria, por lo que "+01" es equivalente a "+01: 00"
  • ISO8601 permite el uso de "Z" para indicar UTC en lugar de "+00: 00".

La solución más fácil es posiblemente usar el convertidor de tipo de datos en JAXB, ya que JAXB debe poder analizar la cadena de fecha ISO8601 de acuerdo con la especificación del esquema XML. javax.xml.bind.DatatypeConverter.parseDateTime("2010-01-01T12:00:00Z")le dará un Calendarobjeto y simplemente puede usar getTime () en él, si necesita un Dateobjeto.

Probablemente también podrías usar Joda-Time , pero no sé por qué deberías molestarte con eso.


18
¡La solución JAXB es un enfoque realmente creativo! Funciona también, lo he probado con mi muestra. Sin embargo, para quien enfrenta el problema y se le permite usar JodaTime, recomendaría usarlo, ya que se siente más natural. Pero su solución no requiere bibliotecas adicionales (al menos con Java 6).
Ice09

36
Aquí está el reverso: Calendario c = GregorianCalendar.getInstance (); c.setTime (aDate); return javax.xml.bind.DatatypeConverter.printDateTime (c);
Alexander Ljungberg

44
En realidad, no es tan simple b / c que tiene que inicializar el convertidor de datos jaxb. Terminé usando DatatypeFactory yo mismo como DataTypeConverterImpl lo hizo internamente. Que dolor de cabeza.
gtrak

3
@ Simon: No, las zonas horarias, por supuesto, no se ignoran. Debes estar haciendo algo mal. Si escribe más de unos pocos caracteres y nos dice lo que realmente está haciendo, alguien puede explicarle qué.
jarnbjo

44
@jarnbjo, eres la primera y única persona con la que me he encontrado que prefiere las clases estándar, pre 1.8, java date, en lugar de joda-time. Encuentro que el tiempo de joda es una alegría literal de usar, especialmente cuando se compara con la API estándar que es una abominación.
NimChimpsky

245

La forma en que está bendecida por la documentación de Java 7 :

DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String string1 = "2001-07-04T12:08:56.235-0700";
Date result1 = df1.parse(string1);

DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
String string2 = "2001-07-04T12:08:56.235-07:00";
Date result2 = df2.parse(string2);

Puede encontrar más ejemplos en la sección Ejemplos en SimpleDateFormat javadoc .

UPD 13/02/2020: Hay una forma completamente nueva de hacer esto en Java 8


77
Su respuesta me ayudó a convertir el ISODate de MongoDB a la fecha local. Saludos.
Blue Sky

99
@ b.long Java agregó más de una constante para dichos formatos compatibles con ISO 8601. Java obtuvo un marco completamente nuevo para el trabajo de fecha y hora que incluye soporte predeterminado incorporado para dichos formatos. Vea el nuevo java.timemarco en Java 8, inspirado en Joda-Time , suplantando las problemáticas clases java.util.Date, .Calendar y SimpleDateFormat.
Basil Bourque

2
¿No significa esto que necesita saber el formato de fecha de antemano? ¿Qué sucede si tiene que aceptar string1y string2no sabe cuál obtendrá?
Timmmm

16
'Z' debe estar entre comillas
kervin

77
@kervin Si la Z está entre comillas, ¿el formateador no buscará específicamente el carácter Z, no todas las cadenas de desplazamiento que puede representar? Parece que citar Z solo funcionaría por coincidencia, si las cadenas de fecha están en UTC.
spaaarky21

201

De acuerdo, esta pregunta ya está respondida, pero de todos modos dejaré mi respuesta. Podría ayudar a alguien.

He estado buscando una solución para Android (API 7).

  • Joda estaba fuera de la cuestión: es enorme y sufre una lenta inicialización. También parecía una exageración importante para ese propósito en particular.
  • Las respuestas relacionadas javax.xmlno funcionarán en Android API 7.

Terminé implementando esta clase simple. Cubre solo la forma más común de cadenas ISO 8601, pero esto debería ser suficiente en algunos casos (cuando esté seguro de que la entrada estará en este formato).

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * Helper class for handling a most common subset of ISO 8601 strings
 * (in the following format: "2008-03-01T13:00:00+01:00"). It supports
 * parsing the "Z" timezone, but many other less-used features are
 * missing.
 */
public final class ISO8601 {
    /** Transform Calendar to ISO 8601 string. */
    public static String fromCalendar(final Calendar calendar) {
        Date date = calendar.getTime();
        String formatted = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
            .format(date);
        return formatted.substring(0, 22) + ":" + formatted.substring(22);
    }

    /** Get current date and time formatted as ISO 8601 string. */
    public static String now() {
        return fromCalendar(GregorianCalendar.getInstance());
    }

    /** Transform ISO 8601 string to Calendar. */
    public static Calendar toCalendar(final String iso8601string)
            throws ParseException {
        Calendar calendar = GregorianCalendar.getInstance();
        String s = iso8601string.replace("Z", "+00:00");
        try {
            s = s.substring(0, 22) + s.substring(23);  // to get rid of the ":"
        } catch (IndexOutOfBoundsException e) {
            throw new ParseException("Invalid length", 0);
        }
        Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(s);
        calendar.setTime(date);
        return calendar;
    }
}

Nota de rendimiento: cada vez que instalo un nuevo SimpleDateFormat para evitar un error en Android 2.1. Si estás tan asombrado como yo, mira este acertijo . Para otros motores Java, puede almacenar en caché la instancia en un campo estático privado (usando ThreadLocal, para ser seguro para subprocesos).


2
¿Quizás esto debería haberse convertido en una pregunta propia, con su propia respuesta?
Thorbear

55
Esta fue la primera página en la que me encontré cuando estaba buscando la respuesta, por lo que me pareció adecuada. Para la mayoría de los desarrolladores de Java, Android no es exactamente Java. Sin embargo, en la mayoría de los casos, uno funciona igual que el otro, por lo que muchos desarrolladores de Android buscarán "java" cuando lo busquen.
wrygiel

1
Tenga en cuenta que esto no tiene en cuenta la resolución de milisegundos. Esto es fácil de agregar.
Sky Kelsey

66
Tuve que agregar .SSS durante segundos fraccionarios, pero funciona muy bien. ¿Por qué lo haces s = s.substring(0, 22) + s.substring(23);? No veo el punto en esto
Dori

1
input = input.replaceAll ("[Zz]", "+0000"); funcionará también y se puede evitar la operación de subcadenas.
Javanator

115

java.time

La API java.time (integrada en Java 8 y posterior) hace esto un poco más fácil.

Si sabe que la entrada está en UTC , como Z(para Zulu) al final, la Instantclase puede analizar.

java.util.Date date = Date.from( Instant.parse( "2014-12-12T10:39:40Z" ));

Si su entrada puede ser otros valores de desplazamiento de UTC en lugar de UTC indicado por Z(Zulu) al final, use la OffsetDateTimeclase para analizar.

OffsetDateTime odt = OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" );

Luego extraiga un Instant, y convierta a un java.util.Datellamando from.

Instant instant = odt.toInstant();  // Instant is always in UTC.
java.util.Date date = java.util.Date.from( instant );

8
Esta respuesta está trabajando muy duro. Un java.util.Date por definición no tiene zona horaria. Por lo tanto, no es necesario todo ese código relacionado con la zona horaria: el LocalDateTimey ZoneIdy atZone. Esta línea simple hará:java.util.Date date = Date.from( ZonedDateTime.parse( "2014-12-12T10:39:40Z" ).toInstant() );
Basil Bourque

55
@BasilBourque Esto es innecesariamente complicado: Date.from(Instant.parse("2014-12-12T10:39:40Z" ));es suficiente.
Assylias

3
@assylias tiene razón, pero eso solo funcionará cuando la cadena de fecha sea zona UTC, ISO8601 permite cualquier zona horaria ...
Adam

2
@ Adam Mi mal: no me había dado cuenta de que la pregunta era más general que tu ejemplo. Como comentario OffsetDateTimeadicional, sería suficiente analizar ISO8601 (que no contiene información de zona horaria sino solo un desplazamiento).
Assylias

1
@assylias Gracias por tu comentario sobre dejar que se Instantrealice el análisis. Si bien no es suficiente para esta pregunta en particular, es una distinción importante que vale la pena señalar. Entonces agregué un segundo ejemplo de código. Vaya, acabo de notar que esta no es originalmente mi respuesta; Espero que Adam lo apruebe.
Basil Bourque

67

La biblioteca Jackson-databind también tiene la clase ISO8601DateFormat que hace eso (implementación real en ISO8601Utils .

ISO8601DateFormat df = new ISO8601DateFormat();
Date d = df.parse("2010-07-28T22:25:51Z");

Que no puede analizar esta fecha: 2015-08-11T13:10:00. Consigo String index out of range: 19. Al mirar el código, parece que requiere que se especifiquen los milisegundos y la zona horaria. Esos deberían ser opcionales.
Timmmm

2
Para citar la documentación, el formato de análisis es: [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]. En otras palabras, los milisegundos son opcionales, pero la zona horaria es obligatoria.
david_p

2
Ah sí, en realidad parece que tienes razón. Aún así, estoy bastante seguro de que ISO8601 le permite omitir la zona horaria, por lo que todavía está mal. Sin embargo, JodaTime funciona:new DateTime("2015-08-11T13:10:00").toDate()
Timmmm

3
Esa clase ahora está en desuso, la nueva es StdDateFormat. De lo contrario, funciona igual.
JohnEye

51

tl; dr

OffsetDateTime.parse ( "2010-01-01T12:00:00+01:00" )

Usando java.time

El nuevo paquete java.time en Java 8 y posterior se inspiró en Joda-Time.

La OffsetDateTimeclase representa un momento en la línea de tiempo con un desplazamiento desde UTC pero no una zona horaria.

OffsetDateTime odt = OffsetDateTime.parse ( "2010-01-01T12:00:00+01:00" );

Las llamadas toStringgeneran una cadena en formato estándar ISO 8601:

2010-01-01T12: 00 + 01: 00

Para ver el mismo valor a través de la lente de UTC, extraiga Instanto ajuste el desplazamiento de +01:00a 00:00.

Instant instant = odt.toInstant();  

…o…

OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC );

Ajústelo a una zona horaria si lo desea. Una zona horaria es un historial de valores de compensación de UTC para una región, con un conjunto de reglas para manejar anomalías como el horario de verano (DST). Por lo tanto, aplique una zona horaria en lugar de un simple desplazamiento siempre que sea posible.

ZonedDateTime zonedDateTimeMontréal = odt.atZoneSameInstant( ZoneId.of( "America/Montreal" ) );

Sobre java.time

El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora 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 Stack Overflow 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 hay necesidad de cadenas, no hay necesidad de java.sql.*clases.

¿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. Usted puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuarter, y más .



27

Para Java versión 7

Puede seguir la documentación de Oracle: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

X: se utiliza para la zona horaria ISO 8601

TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());

System.out.println(nowAsISO);

DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
//nowAsISO = "2013-05-31T00:00:00Z";
Date finalResult = df1.parse(nowAsISO);

System.out.println(finalResult);

Esto significa que se requiere la zona horaria . De acuerdo con ISO 8601 es opcional. Como son los segundos, etc. Así que esto solo analiza un subconjunto específico de ISO 8601.
Timmmm

1
Funciona muy bien con Java 1.8
Thiago Pereira

20

La solución DatatypeConverter no funciona en todas las máquinas virtuales. Lo siguiente funciona para mí:

javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar("2011-01-01Z").toGregorianCalendar().getTime()

Descubrí que joda no funciona fuera de la caja (específicamente para el ejemplo que di arriba con la zona horaria en una fecha, que debería ser válida)


15

Creo que deberíamos usar

DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")

para la fecha 2010-01-01T12:00:00Z


55
¿Por qué es esta una mejor respuesta que las otras, incluida la respuesta aceptada con 76 votos a favor?
Erick Robertson

3
@ErickRobertson: es simple, listo para usar, flexible, sin conversiones, y a la mayoría de las personas no les importan las zonas horarias.
TWiStErRob

77
¡No tiene mucho sentido trabajar con tiempos si no te importan las zonas horarias!
Dori

16
Esto ignora la zona horaria por completo. Estaba usando esto hasta que me di cuenta de que esto estaba sucediendo, así que cambié a JodaTime.
Joshua Pinter

3
Tirar la zona horaria simplemente provocará errores en algún momento.
Bart van Kuik

11

A partir de Java 8, hay una forma completamente nueva oficialmente compatible de hacer esto:

    String s = "2020-02-13T18:51:09.840Z";
    TemporalAccessor ta = DateTimeFormatter.ISO_INSTANT.parse(s);
    Instant i = Instant.from(ta);
    Date d = Date.from(i);

2
Si la cadena está en formato instantáneo, con el final Zcomo desplazamiento, no necesitamos especificar esto explícitamente. Justo Instant i = Instant.parse(s);. La cadena en la pregunta tenía +01:00, en cuyo caso DateTimeFormatter.ISO_INSTANTno funciona (al menos no en mi Java 11).
Ole VV

3
@ OleV.V. Puede usar ISO_OFFSET_DATE_TIMEpara formatear fechas con desplazamientos, como +01:00( docs.oracle.com/javase/8/docs/api/java/time/format/… )
Lucas Basquerotto

1
Eso es cierto, @LucasBasquerotto. Aunque no menciona explícitamente ese formateador, las respuestas de Adam y de Basil Bourque ya hacen algo similar.
Ole VV

Esto no puede analizar "2020-06-01T14: 34: 00-05: 00", que es una cadena producida por el método toISOString () de Javascript.
José Solórzano

10

Otra forma muy simple de analizar las marcas de tiempo ISO8601 es usar org.apache.commons.lang.time.DateUtils:

import static org.junit.Assert.assertEquals;

import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang.time.DateUtils;
import org.junit.Test;

public class ISO8601TimestampFormatTest {
  @Test
  public void parse() throws ParseException {
    Date date = DateUtils.parseDate("2010-01-01T12:00:00+01:00", new String[]{ "yyyy-MM-dd'T'HH:mm:ssZZ" });
    assertEquals("Fri Jan 01 12:00:00 CET 2010", date.toString());
  }
}

6

java.time

Tenga en cuenta que en Java 8, puede usar la clase java.time.ZonedDateTime y su parse(CharSequence text)método estático .


Las cadenas de entrada en la pregunta solo tienen un desplazamiento desde UTC, no una zona horaria completa. Entonces, Instanty ZonedDateTimeson apropiados aquí, no ZonedDateTime.
Basil Bourque

6

La solución para Java 7+ está usando SimpleDateFormat:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);

Este código puede analizar el formato ISO8601 como:

  • 2017-05-17T06:01:43.785Z
  • 2017-05-13T02:58:21.391+01:00

Pero en Java6, SimpleDateFormatno entiende el Xcarácter y arrojará
IllegalArgumentException: Unknown pattern character 'X'
Necesitamos normalizar la fecha ISO8601 al formato legible en Java 6 con SimpleDateFormat.

public static Date iso8601Format(String formattedDate) throws ParseException {
    try {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);
        return df.parse(formattedDate);
    } catch (IllegalArgumentException ex) {
        // error happen in Java 6: Unknown pattern character 'X'
        if (formattedDate.endsWith("Z")) formattedDate = formattedDate.replace("Z", "+0000");
        else formattedDate = formattedDate.replaceAll("([+-]\\d\\d):(\\d\\d)\\s*$", "$1$2");
        DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
        return df1.parse(formattedDate);
    }
}

Método anterior para reemplazar [ Zcon +0000] o [ +01:00con +0100] cuando se produce un error en Java 6 (puede detectar la versión de Java y reemplazar la declaración try / catch con if).


No, las viejas clases problemáticas de fecha y hora, como Datey SimpleDateFormatestán mal diseñadas, confusas y defectuosas. Ahora son heredados, suplantados por las clases java.time integradas en Java 8 y posteriores. Para Java 6 y Java 7, gran parte de la funcionalidad java.time se transfiere en el proyecto ThreeTen-Backport . Es mucho mejor agregar esa biblioteca a su aplicación que usar esas clases heredadas. Solución de una línea en java.time:OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" )
Basil Bourque

5

Me enfrenté al mismo problema y lo resolví con el siguiente código.

 public static Calendar getCalendarFromISO(String datestring) {
    Calendar calendar = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault()) ;
    SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
    try {
        Date date = dateformat.parse(datestring);
        date.setHours(date.getHours() - 1);
        calendar.setTime(date);

        String test = dateformat.format(calendar.getTime());
        Log.e("TEST_TIME", test);

    } catch (ParseException e) {
        e.printStackTrace();
    }

    return calendar;
}

Anteriormente estaba usando SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault());

Pero después encontré la causa principal de la excepción fue el yyyy-MM-dd'T'HH:mm:ss.SSSZ,

Entonces solía

SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());

Funcionó bien para mí.


Justo lo que necesitaba sin tener que usar joda-time, XML api o cualquier otra cosa. Solo el patrón correcto.
Philippe Gioseffi


4

Java tiene una docena de formas diferentes de analizar una fecha y hora, como demuestran las excelentes respuestas aquí. ¡Pero de manera sorprendente, ninguna de las clases de tiempo de Java implementa completamente ISO 8601!

Con Java 8, recomendaría:

ZonedDateTime zp = ZonedDateTime.parse(string);
Date date = Date.from(zp.toInstant());

Eso manejará ejemplos tanto en UTC como con un desplazamiento, como "2017-09-13T10: 36: 40Z" o "2017-09-13T10: 36: 40 + 01: 00". Lo hará para la mayoría de los casos de uso.

Pero no manejará ejemplos como "2017-09-13T10: 36: 40 + 01", que es una fecha y hora ISO 8601 válida.
Tampoco manejará solo la fecha, por ejemplo, "2017-09-13".

Si tiene que manejarlos, sugeriría usar una expresión regular primero para oler la sintaxis.

Aquí hay una buena lista de ejemplos de ISO 8601 con muchos casos de esquina: https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/ I'm no conoce ninguna clase de Java que pueda hacer frente a todas ellas.


OffsetDateTimehará y conceptualmente coincide con una fecha y hora con un desplazamiento mejor.
Ole VV

Hola @ OleV.V. Gracias por la sugerencia. Lamentablemente no: OffsetDateTime.parse () arrojará una excepción para varias cadenas válidas ISO 8601, por ejemplo, "2017-09-13T10: 36: 40 + 01" o "2017-09-13"
Daniel Winterstein

Solo quise decir que OffsetDateTimemaneja los ejemplos con los que manejas ZonedDateTime. Creo que no maneja ninguno de los ejemplos que ZonedDateTimeno lo hace. En ese sentido no es una mejora (pero tampoco peor). Lo siento, no estaba perfectamente claro.
Ole VV

1
Esta debería ser la respuesta aceptada en 2020, dado el estado de las cosas.
slashCoder


3

Como otros han mencionado, Android no tiene una buena manera de admitir el análisis / formateo de fechas ISO 8601 utilizando las clases incluidas en el SDK. He escrito este código varias veces, así que finalmente creé un Gist que incluye una clase DateUtils que admite el formato y el análisis de las fechas ISO 8601 y RFC 1123. The Gist también incluye un caso de prueba que muestra lo que admite.

https://gist.github.com/mraccola/702330625fad8eebe7d3


2

SimpleDateFormat para JAVA 1.7 tiene un patrón genial para el formato ISO 8601.

Clase SimpleDateFormat

Aquí esta lo que hice:

Date d = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
         Locale.ENGLISH).format(System.currentTimeMillis());

2
Zen formato de cadena no es zona horaria ISO 8601, debe usar X( XXo XXX) si desea zona horaria ISO 8601
Vojta

d es de tipo String
Tim Child

1

Hazlo asi:

public static void main(String[] args) throws ParseException {

    String dateStr = "2016-10-19T14:15:36+08:00";
    Date date = javax.xml.bind.DatatypeConverter.parseDateTime(dateStr).getTime();

    System.out.println(date);

}

Aquí está la salida:

Mié 19 oct 15:15:36 CST 2016


1

Usar cadena como LocalDate.parse(((String) data.get("d_iso8601")),DateTimeFormatter.ISO_DATE)


1

Me sorprende que ni una sola biblioteca de Java sea compatible con todos los formatos de fecha ISO 8601 según https://en.wikipedia.org/wiki/ISO_8601 . Joda DateTime era compatible con la mayoría de ellos, pero no con todos y, por lo tanto, agregué una lógica personalizada para manejarlos a todos. Aquí está mi implementación.

import java.text.ParseException;
import java.util.Date;

import org.apache.commons.lang3.time.DateUtils;
import org.joda.time.DateTime;

public class ISO8601DateUtils {
	
	/**
	 * It parses all the date time formats from https://en.wikipedia.org/wiki/ISO_8601 and returns Joda DateTime.
	 * Zoda DateTime does not support dates of format 20190531T160233Z, and hence added custom logic to handle this using SimpleDateFormat.
	 * @param dateTimeString ISO 8601 date time string
	 * @return
	 */
	public static DateTime parse(String dateTimeString) {
		try {
			return new DateTime( dateTimeString );
		} catch(Exception e) {
			try {
				Date dateTime = DateUtils.parseDate(dateTimeString, JODA_NOT_SUPPORTED_ISO_DATES);
				return new DateTime(dateTime.getTime());
			} catch (ParseException e1) {
				throw new RuntimeException(String.format("Date %s could not be parsed to ISO date", dateTimeString));
			}
		}
	}
  
  	private static String[] JODA_NOT_SUPPORTED_ISO_DATES = new String[] {
			// upto millis
			"yyyyMMdd'T'HHmmssSSS'Z'",
			"yyyyMMdd'T'HHmmssSSSZ",
			"yyyyMMdd'T'HHmmssSSSXXX",
			
			"yyyy-MM-dd'T'HHmmssSSS'Z'",
			"yyyy-MM-dd'T'HHmmssSSSZ",
			"yyyy-MM-dd'T'HHmmssSSSXXX",
			
			// upto seconds
			"yyyyMMdd'T'HHmmss'Z'",
			"yyyyMMdd'T'HHmmssZ",
			"yyyyMMdd'T'HHmmssXXX",
			
			"yyyy-MM-dd'T'HHmmss'Z'", 
			"yyyy-MM-dd'T'HHmmssZ",
			"yyyy-MM-dd'T'HHmmssXXX",
			
			// upto minutes
			"yyyyMMdd'T'HHmm'Z'",
			"yyyyMMdd'T'HHmmZ",
			"yyyyMMdd'T'HHmmXXX",

			"yyyy-MM-dd'T'HHmm'Z'",
			"yyyy-MM-dd'T'HHmmZ",
			"yyyy-MM-dd'T'HHmmXXX",
			
			//upto hours is already supported by Joda DateTime
	};
}


1

Una pequeña prueba que muestra cómo analizar una fecha en ISO8601 y que LocalDateTime no maneja los DST.

 @Test
    public void shouldHandleDaylightSavingTimes() throws ParseException {

        //ISO8601 UTC date format
        SimpleDateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");

        // 1 hour of difference between 2 dates in UTC happening at the Daylight Saving Time
        Date d1 = utcFormat.parse("2019-10-27T00:30:00.000Z");
        Date d2 = utcFormat.parse("2019-10-27T01:30:00.000Z");

        //Date 2 is before date 2
        Assert.assertTrue(d1.getTime() < d2.getTime());
        // And there is 1 hour difference between the 2 dates
        Assert.assertEquals(1000*60*60, d2.getTime() - d1.getTime());

        //Print the dates in local time
        SimpleDateFormat localFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm z Z", Locale.forLanguageTag("fr_CH"));
        localFormat.setTimeZone(TimeZone.getTimeZone("Europe/Zurich"));

        //Both dates are at 02h30 local time (because of DST), but one is CEST +0200 and the other CET +0100 (clock goes backwards)
        Assert.assertEquals("2019-10-27 02:30 CEST +0200", localFormat.format(d1));
        Assert.assertEquals("2019-10-27 02:30 CET +0100", localFormat.format(d2));

        //Small test that shows that LocalDateTime does not handle DST (and should not be used for storing timeseries data)
        LocalDateTime ld1 = LocalDateTime.ofInstant(d1.toInstant(), ZoneId.of("Europe/Zurich"));
        LocalDateTime ld2 = LocalDateTime.ofInstant(d2.toInstant(), ZoneId.of("Europe/Zurich"));

        //Note that a localdatetime does not handle DST, therefore the 2 dates are the same
        Assert.assertEquals(ld1, ld2);

        //They both have the following local values
        Assert.assertEquals(2019, ld1.getYear());
        Assert.assertEquals(27, ld1.getDayOfMonth());
        Assert.assertEquals(10, ld1.getMonthValue());
        Assert.assertEquals(2, ld1.getHour());
        Assert.assertEquals(30, ld1.getMinute());
        Assert.assertEquals(0, ld1.getSecond());

    }

3
Para su información, las clases de fecha y hora terriblemente problemáticas como java.util.Date, java.util.Calendary java.text.SimpleDateFormatahora son heredadas , suplantadas por las clases java.time integradas en Java 8 y posteriores. Ver Tutorial de Oracle .
Basil Bourque

Estás en lo correcto LocalDateTimey no maneja el horario de verano (DST) ya que no maneja una zona horaria en absoluto. Para eso necesitamos ZonedDateTime. Proponiendo Datey SimpleDateFormates - en mi humilde opinión.
Ole VV

1
De hecho, ZonedDateTime funciona. Y java.time.Instant también es una buena alternativa para manejar DST. Sé que java.util.Date está en desuso y no debe usarse, pero estaba respondiendo la pregunta original: Cómo convertir una cadena en 8601 a java.util.date ....
ddtxra

0

Tenía una necesidad similar: necesitaba poder analizar cualquier fecha compatible con ISO8601 sin conocer el formato exacto de antemano, y quería una solución ligera que también funcionara en Android.

Cuando busqué en Google mis necesidades, me topé con esta pregunta y noté que AFAIU, ninguna respuesta se ajustaba completamente a mis necesidades. Así que desarrollé jISO8601 y lo presioné en Maven Central.

Solo agrega en ti pom.xml:

<dependency>
  <groupId>fr.turri</groupId>
  <artifactId>jISO8601</artifactId>
  <version>0.2</version>
</dependency>

y entonces estás listo para ir:

import fr.turri.jiso8601.*;
...
Calendar cal = Iso8601Deserializer.toCalendar("1985-03-04");
Date date = Iso8601Deserializer.toDate("1985-03-04T12:34:56Z");

Espera que ayude.



-1

Cortesía de la función base: @wrygiel.

Esta función puede convertir el formato ISO8601 a Java Date, que puede manejar los valores de desplazamiento. Según la definición de ISO 8601, el desplazamiento puede mencionarse en diferentes formatos.

±[hh]:[mm]
±[hh][mm]
±[hh]

Eg:  "18:30Z", "22:30+04", "1130-0700", and "15:00-03:30" all mean the same time. - 06:30PM UTC

Esta clase tiene métodos estáticos para convertir

  • Cadena ISO8601 al objeto Date (Local TimeZone)
  • Fecha para la cadena ISO8601
  • El horario de verano se calcula automáticamente

Cadenas de muestra ISO8601

/*       "2013-06-25T14:00:00Z";
         "2013-06-25T140000Z";
         "2013-06-25T14:00:00+04";
         "2013-06-25T14:00:00+0400";
         "2013-06-25T140000+0400";
         "2013-06-25T14:00:00-04";
         "2013-06-25T14:00:00-0400";
         "2013-06-25T140000-0400";*/


public class ISO8601DateFormatter {

private static final DateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
private static final DateFormat DATE_FORMAT_2 = new SimpleDateFormat("yyyy-MM-dd'T'HHmmssZ");
private static final String UTC_PLUS = "+";
private static final String UTC_MINUS = "-";

public static Date toDate(String iso8601string) throws ParseException {
    iso8601string = iso8601string.trim();
    if(iso8601string.toUpperCase().indexOf("Z")>0){
        iso8601string = iso8601string.toUpperCase().replace("Z", "+0000");
    }else if(((iso8601string.indexOf(UTC_PLUS))>0)){
        iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_PLUS));
        iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_PLUS), UTC_PLUS);
    }else if(((iso8601string.indexOf(UTC_MINUS))>0)){
        iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_MINUS));
        iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_MINUS), UTC_MINUS);
    }

    Date date = null;
    if(iso8601string.contains(":"))
        date = DATE_FORMAT_1.parse(iso8601string);
    else{
        date = DATE_FORMAT_2.parse(iso8601string);
    }
    return date;
}

public static String toISO8601String(Date date){
    return DATE_FORMAT_1.format(date);
}

private static String replaceColon(String sourceStr, int offsetIndex){
    if(sourceStr.substring(offsetIndex).contains(":"))
        return sourceStr.substring(0, offsetIndex) + sourceStr.substring(offsetIndex).replace(":", "");
    return sourceStr;
}

private static String appendZeros(String sourceStr, int offsetIndex, String offsetChar){
    if((sourceStr.length()-1)-sourceStr.indexOf(offsetChar,offsetIndex)<=2)
        return sourceStr + "00";
    return sourceStr;
}

}


2
Cuidado: ¡DateFormat y las clases derivadas no son compatibles con subprocesos múltiples! El uso de objetos estáticos SimpleDateFormat como DATE_FORMAT_1 y DATE_FORMAT_2 significa que múltiples hilos que llaman a las funciones ISO8601DateFormatter compartirán el mismo objeto DateFormat. Esto conduce a la corrupción de datos y la devolución de fechas incorrectas de las llamadas de DateFormat. Para solucionar esto, solo debe hacer constantes las cadenas de patrones y crear variables locales SimpleDateFormat cuando sea necesario. Esto asegurará que cada objeto sea utilizado por un solo hilo.
Theo

Una mejor solución para la seguridad de subprocesos es utilizar una biblioteca de fecha y hora creada para la seguridad de subprocesos. En Java, ese mundo puede ser Joda-Time o java.time.
Basil Bourque

-1

Esto pareció funcionar mejor para mí:

public static Date fromISO8601_( String string ) {

    try {
            return new SimpleDateFormat ( "yyyy-MM-dd'T'HH:mm:ssXXX").parse ( string );
    } catch ( ParseException e ) {
        return Exceptions.handle (Date.class, "Not a valid ISO8601", e);
    }


}

Necesitaba convertir a / para cadenas de fecha JavaScript a Java. Encontré que lo anterior funciona con la recomendación. Hubo algunos ejemplos usando SimpleDateFormat que estaban cerca pero no parecían ser el subconjunto recomendado por:

http://www.w3.org/TR/NOTE-datetime

y soportado por PLIST y JavaScript Strings y tal que es lo que necesitaba.

Esta parece ser la forma más común de cadena ISO8601, y un buen subconjunto.

Los ejemplos que dan son:

1994-11-05T08:15:30-05:00 corresponds 
November 5, 1994, 8:15:30 am, US Eastern Standard Time.

 1994-11-05T13:15:30Z corresponds to the same instant.

También tengo una versión rápida:

final static int SHORT_ISO_8601_TIME_LENGTH =  "1994-11-05T08:15:30Z".length ();
                                            // 01234567890123456789012
final static int LONG_ISO_8601_TIME_LENGTH = "1994-11-05T08:15:30-05:00".length ();


public static Date fromISO8601( String string ) {
    if (isISO8601 ( string )) {
        char [] charArray = Reflection.toCharArray ( string );//uses unsafe or string.toCharArray if unsafe is not available
        int year = CharScanner.parseIntFromTo ( charArray, 0, 4 );
        int month = CharScanner.parseIntFromTo ( charArray, 5, 7 );
        int day = CharScanner.parseIntFromTo ( charArray, 8, 10 );
        int hour = CharScanner.parseIntFromTo ( charArray, 11, 13 );

        int minute = CharScanner.parseIntFromTo ( charArray, 14, 16 );

        int second = CharScanner.parseIntFromTo ( charArray, 17, 19 );

        TimeZone tz ;

         if (charArray[19] == 'Z') {

             tz = TimeZone.getTimeZone ( "GMT" );
         } else {

             StringBuilder builder = new StringBuilder ( 9 );
             builder.append ( "GMT" );
             builder.append( charArray, 19, LONG_ISO_8601_TIME_LENGTH - 19);
             String tzStr = builder.toString ();
             tz = TimeZone.getTimeZone ( tzStr ) ;

         }
         return toDate ( tz, year, month, day, hour, minute, second );

    }   else {
        return null;
    }

}

...

public static int parseIntFromTo ( char[] digitChars, int offset, int to ) {
    int num = digitChars[ offset ] - '0';
    if ( ++offset < to ) {
        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
        if ( ++offset < to ) {
            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
            if ( ++offset < to ) {
                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                if ( ++offset < to ) {
                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                    if ( ++offset < to ) {
                        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                        if ( ++offset < to ) {
                            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                            if ( ++offset < to ) {
                                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                if ( ++offset < to ) {
                                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return num;
}


public static boolean isISO8601( String string ) {
      boolean valid = true;

      if (string.length () == SHORT_ISO_8601_TIME_LENGTH) {
          valid &=  (string.charAt ( 19 )  == 'Z');

      } else if (string.length () == LONG_ISO_8601_TIME_LENGTH) {
          valid &=  (string.charAt ( 19 )  == '-' || string.charAt ( 19 )  == '+');
          valid &=  (string.charAt ( 22 )  == ':');

      } else {
          return false;
      }

    //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
    // "1 9 9 4 - 1 1 - 0 5 T 0 8 : 1 5 : 3 0 - 0 5 : 0 0

    valid &=  (string.charAt ( 4 )  == '-') &&
                (string.charAt ( 7 )  == '-') &&
                (string.charAt ( 10 ) == 'T') &&
                (string.charAt ( 13 ) == ':') &&
                (string.charAt ( 16 ) == ':');

    return valid;
}

No lo he comparado, pero supongo que será bastante rápido. Parece funcionar. :)

@Test
public void testIsoShortDate() {
    String test =  "1994-11-05T08:15:30Z";

    Date date = Dates.fromISO8601 ( test );
    Date date2 = Dates.fromISO8601_ ( test );

    assertEquals(date2.toString (), date.toString ());

    puts (date);
}

@Test
public void testIsoLongDate() {
    String test =  "1994-11-05T08:11:22-05:00";

    Date date = Dates.fromISO8601 ( test );
    Date date2 = Dates.fromISO8601_ ( test );

    assertEquals(date2.toString (), date.toString ());

    puts (date);
}

-2

Creo que lo que mucha gente quiere hacer es analizar cadenas de fechas JSON. Si viene a esta página, es muy probable que desee convertir una fecha JSON de JavaScript en una fecha Java.

Para mostrar cómo se ve una cadena de fecha JSON:

    var d=new Date();
    var s = JSON.stringify(d);

    document.write(s);
    document.write("<br />"+d);


    "2013-12-14T01:55:33.412Z"
    Fri Dec 13 2013 17:55:33 GMT-0800 (PST)

La cadena de fecha JSON es 2013-12-14T01: 55: 33.412Z.

Las fechas no están cubiertas por la especificación JSON por ejemplo, pero lo anterior es un formato ISO 8601 muy específico, mientras que ISO_8601 es mucho más grande y ese es un mero subconjunto, aunque muy importante.

Ver http://www.json.org Ver http://en.wikipedia.org/wiki/ISO_8601 Ver http://www.w3.org/TR/NOTE-datetime

Resulta que escribí un analizador JSON y un analizador PLIST que usan ISO-8601 pero no los mismos bits.

/*
    var d=new Date();
    var s = JSON.stringify(d);

    document.write(s);
    document.write("<br />"+d);


    "2013-12-14T01:55:33.412Z"
    Fri Dec 13 2013 17:55:33 GMT-0800 (PST)


 */
@Test
public void jsonJavaScriptDate() {
    String test =  "2013-12-14T01:55:33.412Z";

    Date date = Dates.fromJsonDate ( test );
    Date date2 = Dates.fromJsonDate_ ( test );

    assertEquals(date2.toString (), "" + date);

    puts (date);
}

Escribí dos formas de hacer esto para mi proyecto. Un estándar, uno rápido.

Nuevamente, la cadena de fecha JSON es una implementación muy específica de ISO 8601 ...

(Publiqué el otro en la otra respuesta que debería funcionar para las fechas PLIST, que son un formato ISO 8601 diferente).

La fecha JSON es la siguiente:

public static Date fromJsonDate_( String string ) {

    try {

        return new SimpleDateFormat ( "yyyy-MM-dd'T'HH:mm:ss.SSSXXX").parse ( string );
    } catch ( ParseException e ) {
        return Exceptions.handle (Date.class, "Not a valid JSON date", e);
    }


}

Los archivos PLIST (ASCII no GNUNext) también usan ISO 8601 pero no milisegundos, así que ... no todas las fechas ISO-8601 son iguales. (Al menos aún no he encontrado uno que use milis y el analizador que he visto omite la zona horaria OMG).

Ahora para la versión rápida (puedes encontrarla en Boon).

public static Date fromJsonDate( String string ) {

    return fromJsonDate ( Reflection.toCharArray ( string ), 0, string.length () );

}

Tenga en cuenta que Reflection.toCharArray usa inseguro si está disponible, pero por defecto es string.toCharArray si no.

(Puede sacarlo del ejemplo reemplazando Reflection.toCharArray (string) con string.toCharArray ()).

public static Date fromJsonDate( char[] charArray, int from, int to ) {

    if (isJsonDate ( charArray, from, to )) {
        int year = CharScanner.parseIntFromTo ( charArray, from + 0, from + 4 );
        int month = CharScanner.parseIntFromTo ( charArray,  from +5,  from +7 );
        int day = CharScanner.parseIntFromTo ( charArray,  from +8,  from +10 );
        int hour = CharScanner.parseIntFromTo ( charArray,  from +11,  from +13 );

        int minute = CharScanner.parseIntFromTo ( charArray,  from +14,  from +16 );

        int second = CharScanner.parseIntFromTo ( charArray,  from +17,  from +19 );

        int miliseconds = CharScanner.parseIntFromTo ( charArray,  from +20,  from +23 );

        TimeZone tz = TimeZone.getTimeZone ( "GMT" );


        return toDate ( tz, year, month, day, hour, minute, second, miliseconds );

    }   else {
        return null;
    }

}

El isJsonDate se implementa de la siguiente manera:

public static boolean isJsonDate( char[] charArray, int start, int to ) {
    boolean valid = true;
    final int length = to -start;

    if (length != JSON_TIME_LENGTH) {
        return false;
    }

    valid &=  (charArray [ start + 19 ]  == '.');

    if (!valid) {
        return false;
    }


    valid &=  (charArray[  start +4 ]  == '-') &&
            (charArray[  start +7 ]  == '-') &&
            (charArray[  start +10 ] == 'T') &&
            (charArray[  start +13 ] == ':') &&
            (charArray[  start +16 ] == ':');

    return valid;
}

De todos modos ... supongo que algunas personas que vienen aquí ... podrían estar buscando la cadena de fecha JSON y, aunque es una fecha ISO-8601, es muy específica y necesita un análisis muy específico.

public static int parseIntFromTo ( char[] digitChars, int offset, int to ) {
    int num = digitChars[ offset ] - '0';
    if ( ++offset < to ) {
        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
        if ( ++offset < to ) {
            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
            if ( ++offset < to ) {
                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                if ( ++offset < to ) {
                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                    if ( ++offset < to ) {
                        num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                        if ( ++offset < to ) {
                            num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                            if ( ++offset < to ) {
                                num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                if ( ++offset < to ) {
                                    num = ( num * 10 ) + ( digitChars[ offset ] - '0' );
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return num;
}

Consulte https://github.com/RichardHightower/boon Boon tiene un analizador PLIST (ASCII) y un analizador JSON.

El analizador JSON es el analizador Java JSON más rápido que conozco.

Verificado independientemente por los muchachos de Gatling Performance.

https://github.com/gatling/json-parsers-benchmark

Benchmark                               Mode Thr     Count  Sec         Mean   Mean error        Units
BoonCharArrayBenchmark.roundRobin      thrpt  16        10    1   724815,875    54339,825    ops/s
JacksonObjectBenchmark.roundRobin      thrpt  16        10    1   580014,875   145097,700    ops/s
JsonSmartBytesBenchmark.roundRobin     thrpt  16        10    1   575548,435    64202,618    ops/s
JsonSmartStringBenchmark.roundRobin    thrpt  16        10    1   541212,220    45144,815    ops/s
GSONStringBenchmark.roundRobin         thrpt  16        10    1   522947,175    65572,427    ops/s
BoonDirectBytesBenchmark.roundRobin    thrpt  16        10    1   521528,912    41366,197    ops/s
JacksonASTBenchmark.roundRobin         thrpt  16        10    1   512564,205   300704,545    ops/s
GSONReaderBenchmark.roundRobin         thrpt  16        10    1   446322,220    41327,496    ops/s
JsonSmartStreamBenchmark.roundRobin    thrpt  16        10    1   276399,298   130055,340    ops/s
JsonSmartReaderBenchmark.roundRobin    thrpt  16        10    1    86789,825    17690,031    ops/s

Tiene el analizador JSON más rápido para secuencias, lectores, bytes [], char [], CharSequence (StringBuilder, CharacterBuffer) y String.

Ver más puntos de referencia en:

https://github.com/RichardHightower/json-parsers-benchmark


Esta respuesta sobre JSON está fuera del tema de la pregunta. Además, esta pregunta es incorrecta ya que no existe una "fecha JSON" entre los muy pocos tipos de datos JSON . Y hoy en día, todo este código se puede reemplazar con una llamada de una sola línea a la función Java incorporada:Instant.parse( "2013-12-14T01:55:33.412Z" )
Basil Bourque
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.