Conversione della stringa conforme a ISO 8601 in java.util.Date


668

Sto cercando di convertire una stringa formattata ISO 8601 in a java.util.Date.

Ho trovato il modello yyyy-MM-dd'T'HH:mm:ssZconforme a ISO8601 se utilizzato con una versione locale (confronta il campione).

Tuttavia, utilizzando il java.text.SimpleDateFormat, non riesco a convertire la stringa correttamente formattata 2010-01-01T12:00:00+01:00. Devo convertirlo prima in 2010-01-01T12:00:00+0100, senza i due punti.

Quindi, la soluzione attuale è

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));

che ovviamente non è così carino. Mi sto perdendo qualcosa o esiste una soluzione migliore?


Risposta

Grazie al commento di JuanZe, ho trovato la magia di Joda-Time , che è anche descritta qui .

Quindi, la soluzione è

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

O più semplicemente, utilizzare il parser predefinito tramite il costruttore:

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

Per me questo è carino.


243
Preparati a ricevere molte risposte "Usa JodaTime" ...
JuanZe

3
@ Ice09: se la documentazione API per DateTimeFormat è corretta (la documentazione JoDa può essere fuorviante, errata o incompleta), il modello che hai usato nella tua "risposta" non è compatibile con ISO8601.
jarnbjo,

21
Non sono sicuro quando questo è stato aggiunto, ma la "X" sembra risolvere questo problema in SimpleDateFormat. Il modello "yyyy-MM-dd'T'HH: mm: ssX" analizza correttamente l'esempio nella domanda.
mlohbihler,

12
La "X" è disponibile da Java 7.
Lars Grammel,

3
Java 8 lo rende facile! C'è una gemma nascosta di Adam nelle risposte seguenti: stackoverflow.com/a/27479533/1262901
Fabian Keller

Risposte:


477

Sfortunatamente, i formati di fuso orario disponibili per SimpleDateFormat (Java 6 e precedenti) non sono conformi a ISO 8601 . SimpleDateFormat comprende stringhe di fuso orario come "GMT + 01: 00" o "+0100", quest'ultima secondo RFC # 822 .

Anche se Java 7 ha aggiunto il supporto per i descrittori di fuso orario secondo ISO 8601, SimpleDateFormat non è ancora in grado di analizzare correttamente una stringa di data completa, poiché non supporta le parti opzionali.

Riformattare la stringa di input usando regexp è certamente una possibilità, ma le regole di sostituzione non sono così semplici come nella tua domanda:

  • Alcuni fusi orari non sono ore complete fuori UTC , quindi la stringa non termina necessariamente con ": 00".
  • ISO8601 consente solo il numero di ore da includere nel fuso orario, quindi "+01" equivale a "+01: 00"
  • ISO8601 consente l'uso di "Z" per indicare UTC invece di "+00: 00".

La soluzione più semplice è probabilmente quella di utilizzare il convertitore di tipi di dati in JAXB, poiché JAXB deve essere in grado di analizzare la stringa di data ISO8601 in base alle specifiche dello schema XML. javax.xml.bind.DatatypeConverter.parseDateTime("2010-01-01T12:00:00Z")ti darà un Calendaroggetto e puoi semplicemente usare getTime () su di esso, se hai bisogno di un Dateoggetto.

Probabilmente potresti usare anche Joda-Time , ma non so perché dovresti preoccupartene.


18
La soluzione JAXB è un approccio davvero creativo! Funziona pure, l'ho provato con il mio campione. Tuttavia, per chiunque affronti il ​​problema ed è autorizzato a utilizzare JodaTime, consiglierei di usarlo, poiché sembra più naturale. Ma la tua soluzione non richiede librerie aggiuntive (almeno con Java 6).
Ice09,

36
Ecco il contrario: Calendario c = GregorianCalendar.getInstance (); c.setTime (aDate); return javax.xml.bind.DatatypeConverter.printDateTime (c);
Alexander Ljungberg,

4
In realtà non è così semplice b / c che devi inizializzare il datatypeConverter jaxb. Alla fine ho usato DatatypeFactory come DataTypeConverterImpl ha fatto internamente. Che mal di testa.
gtrak,

3
@Simon: No, i fusi orari non sono ovviamente ignorati. Stai facendo qualcosa di sbagliato. Se digiti più di alcuni caratteri e ci dici cosa stai veramente facendo, qualcuno potrebbe spiegarti cosa.
jarnbjo,

4
@jarnbjo sei la prima e unica persona che ho incontrato che preferisce le classi di date standard, pre 1.8, java, rispetto a joda-time. Trovo il joda-time una gioia letterale da usare, soprattutto se paragonato all'api standard che è un abominio.
NimChimpsky,

245

Il modo in cui è benedetto dalla documentazione di 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);

Puoi trovare altri esempi nella sezione Esempi in SimpleDateFormat javadoc .

UPD 13/02/2020: esiste un modo completamente nuovo per farlo in Java 8


7
La tua risposta mi ha aiutato a convertire ISODate di MongoDB in data locale. Saluti.
Blue Sky,

9
@ b.long Java ha aggiunto più di una costante per tali formati conformi a ISO 8601. Java ha ottenuto un intero nuovo framework per il lavoro data-ora che include il supporto predefinito incorporato per tali formati. Guarda il nuovo java.timeframework in Java 8, ispirato a Joda-Time , che soppianta le fastidiose classi java.util.Date, .Calendar e SimpleDateFormat.
Basil Bourque,

2
Questo non significa che devi conoscere in anticipo il formato della data? E se dovessi accettare string1e string2non sapere quale otterrai.
Timmmm,

16
"Z" deve essere tra virgolette
Kervin il

7
@kervin Se la Z è tra virgolette, il formatter non cercherà specificamente il carattere Z, non tutte le stringhe di offset che può rappresentare? Sembra che la citazione di Z funzionerebbe solo per coincidenza, se le stringhe della tua data fossero in UTC.
spaaarky21,

201

Ok, questa domanda ha già una risposta, ma lascerò comunque la mia risposta. Potrebbe aiutare qualcuno.

Ho cercato una soluzione per Android (API 7).

  • Joda era fuori discussione - è enorme e soffre di una lenta inizializzazione. Sembrava anche un grosso problema per quel particolare scopo.
  • Le risposte che coinvolgono javax.xmlnon funzioneranno su Android API 7.

Ho finito per implementare questa semplice classe. Copre solo la forma più comune di stringhe ISO 8601, ma in alcuni casi dovrebbe essere sufficiente (quando si è abbastanza sicuri che l'input sarà in questo 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 sulle prestazioni: ho istanziato il nuovo SimpleDateFormat ogni volta come mezzo per evitare un bug in Android 2.1. Se sei stupito quanto me, vedi questo indovinello . Per altri motori Java, è possibile memorizzare nella cache l'istanza in un campo statico privato (usando ThreadLocal, per essere thread-safe).


2
Forse questo avrebbe dovuto essere trasformato in una domanda a sé stante, con una sua risposta?
Thorbear

5
Questa è stata la prima pagina su cui mi sono imbattuto mentre cercavo la risposta, quindi mi è sembrata adatta. Per la maggior parte degli sviluppatori Java, Android non è esattamente Java. Tuttavia, nella maggior parte dei casi, uno funziona allo stesso modo dell'altro, quindi molti sviluppatori Android cercheranno "java" quando lo cercano.
wrygiel,

1
Si noti che ciò non tiene conto della risoluzione in millisecondi. Questo è facile da aggiungere.
Sky Kelsey

6
ho dovuto aggiungere .SSS per secondi frazionari ma funziona benissimo grazie. Perché lo fai s = s.substring(0, 22) + s.substring(23);- non vedo il punto in questo
Dori,

1
input = input.replaceAll ("[Zz]", "+0000"); funzionerà anche e l'operazione di sottostringa può essere evitata.
Javanator,

115

java.time

L' API java.time (integrata in Java 8 e versioni successive) rende questo un po 'più semplice.

Se sai che l'input è in UTC , come il Z(per Zulu) alla fine, la Instantclasse può analizzare.

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

Se il tuo input può essere un altro offset rispetto ai valori UTC anziché UTC indicato da Z(Zulu) alla fine, usa la OffsetDateTimeclasse per analizzare.

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

Quindi estrarre un Instante convertirlo in a java.util.Datechiamando from.

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

8
Questa risposta sta lavorando troppo duramente. Un java.util.Date per definizione non ha fuso orario. Quindi non c'è bisogno di tutto quel codice relativo al fuso orario: il LocalDateTimee ZoneIde atZone. Questo semplice one-liner farà:java.util.Date date = Date.from( ZonedDateTime.parse( "2014-12-12T10:39:40Z" ).toInstant() );
Basil Bourque il

5
@BasilBourque Questo è inutilmente complicato: Date.from(Instant.parse("2014-12-12T10:39:40Z" ));è abbastanza.
Assylias,

3
@assylias hai ragione, ma funzionerà solo quando la stringa della data è la zona UTC, ISO8601 consente qualsiasi fuso orario ...
Adam

2
@Adam Mio cattivo - Non avevo capito che la domanda era più generale del tuo esempio. Come commento laterale, OffsetDateTimebasterebbe analizzare ISO8601 (che non contiene informazioni sul fuso orario ma solo un offset).
Assylias,

1
@assylias Grazie per il tuo commento su come Instantfare l'analisi. Sebbene non sia sufficiente per questa particolare domanda, è una distinzione importante che vale la pena sottolineare. Quindi ho aggiunto un secondo esempio di codice. Oops, ho appena notato che questa non è originariamente la mia risposta; Spero che Adam approvi.
Basil Bourque,

67

La libreria Jackson-databind ha anche la classe ISO8601DateFormat che lo fa (implementazione effettiva in ISO8601Utils .

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

Non riesce a analizzare questa data: 2015-08-11T13:10:00. Ho capito String index out of range: 19. Guardando il codice sembra che sia necessario specificare i millisecondi e il fuso orario. Quelli dovrebbero essere facoltativi.
Timmmm,

2
Per citare la documentazione, il formato di analisi è il seguente: [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]. In altre parole, i millisecondi sono facoltativi ma il fuso orario è obbligatorio.
david_p,

2
Ah sì, in realtà sembra che tu abbia ragione. Tuttavia, sono abbastanza sicuro che ISO8601 ti consente di omettere il fuso orario, quindi è ancora sbagliato. JodaTime funziona però:new DateTime("2015-08-11T13:10:00").toDate()
Timmmm

3
Quella classe è ora obsoleta, quella nuova è StdDateFormat. Altrimenti funziona allo stesso modo.
JohnEye,

51

tl; dr

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

Utilizzando java.time

Il nuovo pacchetto java.time in Java 8 e versioni successive è stato ispirato da Joda-Time.

La OffsetDateTimeclasse rappresenta un momento sulla sequenza temporale con un offset da UTC ma non un fuso orario.

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

La chiamata toStringgenera una stringa nel formato standard ISO 8601:

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

Per vedere lo stesso valore attraverso l'obiettivo di UTC, estrarre Instanto regolare l'offset da +01:00a 00:00.

Instant instant = odt.toInstant();  

…o…

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

Se lo si desidera, regolare in un fuso orario. Un fuso orario è una cronologia dei valori offset da UTC per una regione, con un insieme di regole per la gestione di anomalie come l'ora legale (DST). Quindi, quando possibile, applica un fuso orario anziché un semplice offset.

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

Informazioni su java.time

Il framework java.time è integrato in Java 8 e versioni successive. Queste classi soppiantare la vecchia fastidiosi legacy classi data-time come java.util.Date, Calendar, e SimpleDateFormat.

Il progetto Joda-Time , ora in modalità manutenzione , consiglia la migrazione alle classi java.time .

Per saperne di più, consulta il tutorial Oracle . E cerca Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310 .

Puoi scambiare oggetti java.time direttamente con il tuo database. Utilizzare un driver JDBC conforme a JDBC 4.2 o successivo. Non c'è bisogno di stringhe, non c'è bisogno di java.sql.*classi.

Dove ottenere le classi java.time?

Il progetto ThreeTen-Extra estende java.time con classi aggiuntive. Questo progetto è un banco di prova per possibili aggiunte future a java.time. Si possono trovare alcune classi utili, come per esempio Interval, YearWeek, YearQuartere altro .



27

Per Java versione 7

Puoi seguire la documentazione Oracle: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

X: viene utilizzato per il fuso orario 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);

Ciò significa che è richiesto il fuso orario . Secondo ISO 8601 è facoltativo. Come i secondi, ecc. Quindi questo analizza solo un sottoinsieme specifico di ISO 8601.
Timmmm

1
Funziona alla grande con Java 1.8
Thiago Pereira,

20

La soluzione DatatypeConverter non funziona in tutte le macchine virtuali. Per me funziona quanto segue:

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

Ho scoperto che joda non funziona immediatamente (in particolare per l'esempio che ho fornito sopra con il fuso orario in una data, che dovrebbe essere valido)


15

Penso che dovremmo usare

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

per data 2010-01-01T12:00:00Z


5
Perché questa è una risposta migliore delle altre, inclusa la risposta accettata con 76 voti positivi?
Erick Robertson,

3
@ErickRobertson: è semplice, pronto all'uso, flessibile, senza conversioni e alla maggior parte delle persone non interessano i fusi orari.
TWiStErRob,

7
non ha senso lavorare con i tempi se non ti importa dei fusi orari!
Dori,

16
Questo IGNORA completamente il fuso orario. Lo usavo fino a quando non ho capito che stava succedendo, quindi sono passato a JodaTime.
Joshua Pinter,

3
Eliminare il fuso orario comporterà semplicemente errori ad un certo punto.
Bart van Kuik,

11

A partire da Java 8, esiste un modo completamente nuovo ufficialmente supportato per farlo:

    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
Se la stringa è nel formato istantaneo, con il trailing Zcome offset, non è necessario specificarlo esplicitamente. Basta Instant i = Instant.parse(s);. La stringa nella domanda aveva +01:00, nel qual caso DateTimeFormatter.ISO_INSTANTnon funziona (almeno non sul mio Java 11).
Ole VV,

3
@ OleV.V. È possibile utilizzare ISO_OFFSET_DATE_TIMEper formattare le date con offset, come +01:00( docs.oracle.com/javase/8/docs/api/java/time/format/… )
Lucas Basquerotto

1
È vero, @LucasBasquerotto. Pur non menzionando esplicitamente quel formattatore, le risposte di Adam e di Basil Bourque fanno già qualcosa di simile.
Ole VV

Questo non può analizzare "2020-06-01T14: 34: 00-05: 00" che è una stringa prodotta dal metodo toISOString () di Javascript.
Jose Solorzano

10

Un altro modo molto semplice per analizzare i timestamp ISO8601 è usare 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

Si noti che in Java 8 è possibile utilizzare la classe java.time.ZonedDateTime e il suo parse(CharSequence text)metodo statico .


Le stringhe di input nella Domanda hanno solo un offset da UTC, non un fuso orario completo. Quindi Instante ZonedDateTimesono appropriati qui, no ZonedDateTime.
Basil Bourque,

6

La soluzione alternativa per Java 7+ sta usando SimpleDateFormat:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);

Questo codice può analizzare il formato ISO8601 come:

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

Ma su Java6, SimpleDateFormatnon capisce il Xcarattere e verrà lanciato
IllegalArgumentException: Unknown pattern character 'X'
Dobbiamo normalizzare la data ISO8601 nel formato leggibile in Java 6 conSimpleDateFormat .

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);
    }
}

Metodo sopra per sostituire [ Zcon +0000] o [ +01:00con +0100] quando si verifica un errore in Java 6 (è possibile rilevare la versione Java e sostituire try / catch con l'istruzione if).


No, le vecchie e problematiche classi di data e ora come Datee SimpleDateFormatsono progettate male, confuse e imperfette. Ora sono legacy, soppiantati dalle classi java.time integrate in Java 8 e versioni successive. Per Java 6 e Java 7, gran parte della funzionalità java.time è trasferita nel progetto ThreeTen-Backport . Molto meglio aggiungere quella libreria alla tua app piuttosto che usare quelle classi legacy. Soluzione a una riga in java.time:OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" )
Basil Bourque,

5

Ho affrontato lo stesso problema e risolto con il seguente codice.

 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;
}

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

Ma più tardi ho scoperto che la causa principale dell'eccezione era la yyyy-MM-dd'T'HH:mm:ss.SSSZ,

Quindi ho usato

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

Ha funzionato bene per me .


Proprio quello di cui avevo bisogno senza dover usare joda-time, API XML o qualsiasi altra cosa. Solo il modello corretto.
Philippe Gioseffi,


4

Java ha una dozzina di modi diversi per analizzare una data-ora, come dimostrano le eccellenti risposte qui. Ma un po 'sorprendentemente, nessuna delle classi di tempo di Java implementa pienamente ISO 8601!

Con Java 8, consiglierei:

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

Che gestirà esempi sia in UTC che con un offset, come "2017-09-13T10: 36: 40Z" o "2017-09-13T10: 36: 40 + 01: 00". Lo farà per la maggior parte dei casi d'uso.

Ma non gestirà esempi come "2017-09-13T10: 36: 40 + 01", che è una data-ora ISO 8601 valida.
Inoltre non gestirà solo la data, ad esempio "2017-09-13".

Se devi gestirli, ti suggerisco di usare prima una regex per annusare la sintassi.

C'è un bel elenco di esempi ISO 8601 qui con molti casi angolari: https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/ I'm non a conoscenza di alcuna classe Java in grado di far fronte a tutti loro.


OffsetDateTimefarà e concettualmente abbina una data-ora con un offset migliore.
Ole VV,

Ehi @ OleV.V. grazie per il suggerimento. Purtroppo no: OffsetDateTime.parse () genererà un'eccezione per diverse stringhe ISO 8601 valide, ad esempio "2017-09-13T10: 36: 40 + 01" o "2017-09-13"
Daniel Winterstein

Intendevo solo dire che OffsetDateTimegestisce gli esempi con cui gestisci ZonedDateTime. Credo che non gestisca nessuno degli esempi che ZonedDateTimenon lo fanno. In questo senso non è un miglioramento (ma anche niente di peggio). Scusa, non ero perfettamente chiaro.
Ole VV,

1
Questa dovrebbe essere la risposta accettata nel 2020, dato lo stato delle cose.
slashCoder


3

Come altri hanno già detto, Android non ha un buon modo per supportare l'analisi / formattazione delle date ISO 8601 utilizzando le classi incluse nell'SDK. Ho scritto questo codice più volte, quindi ho finalmente creato un Gist che include una classe DateUtils che supporta la formattazione e l'analisi delle date ISO 8601 e RFC 1123. The Gist include anche un caso di test che mostra ciò che supporta.

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


2

SimpleDateFormat per JAVA 1.7 ha un modello interessante per il formato ISO 8601.

Classe SimpleDateFormat

Ecco cosa ho fatto:

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

2
Znella stringa di formato non è il fuso orario ISO 8601, dovresti usare X(o XXo XXX) se vuoi il fuso orario ISO 8601
Vojta

d è di tipo String
Tim Child il

1

Fai cosi:

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);

}

Ecco l'output:

Mer 19 ott 15:15:36 CST 2016


1

Usa una stringa come LocalDate.parse(((String) data.get("d_iso8601")),DateTimeFormatter.ISO_DATE)


1

Sono sorpreso che nemmeno una libreria Java supporti tutti i formati di data ISO 8601 secondo https://en.wikipedia.org/wiki/ISO_8601 . Joda DateTime supportava la maggior parte di essi, ma non tutti e quindi ho aggiunto una logica personalizzata per gestirli tutti. Ecco la mia implementazione.

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

Un piccolo test che mostra come analizzare una data in ISO8601 e che LocalDateTime non gestisce l'ora legale.

 @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
Cordiali saluti, le classi data-ora terribilmente fastidiose come java.util.Date, java.util.Calendare java.text.SimpleDateFormatora sono legacy , soppiantate dalle classi java.time integrate in Java 8 e versioni successive. Vedi Tutorial di Oracle .
Basil Bourque,

Hai ragione che LocalDateTimenon gestisce l'ora legale (DST) poiché non gestisce affatto un fuso orario. Per questo abbiamo bisogno ZonedDateTime. Proporre Dateed SimpleDateFormatè - IMHO male.
Ole VV,

1
In effetti ZonedDateTime funziona. E java.time.Instant è anche una buona alternativa per gestire l'ora legale. So che java.util.Date è obsoleto e non dovrebbe essere usato, ma stavo solo rispondendo alla domanda originale: Come convertire una stringa in 8601 in java.util.date ....
ddtxra

0

Avevo un'esigenza simile: dovevo essere in grado di analizzare qualsiasi data conforme a ISO8601 senza conoscere in anticipo il formato esatto e volevo una soluzione leggera che funzionasse anche su Android.

Quando ho cercato su Google i miei bisogni, mi sono imbattuto in questa domanda e ho notato che AFAIU, nessuna risposta adattava completamente ai miei bisogni. Quindi ho sviluppato jISO8601 e l' ho spinto su Maven Central.

Aggiungi solo in te pom.xml:

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

e poi sei a posto:

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

Spero che sia d'aiuto.



-1

Funzione di base Per gentile concessione: @wrygiel.

Questa funzione può convertire il formato ISO8601 in Java Date in grado di gestire i valori di offset. Secondo la definizione di ISO 8601 l'offset può essere menzionato in diversi formati.

±[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

Questa classe ha metodi statici per la conversione

  • Stringa ISO8601 all'oggetto Date (Local TimeZone)
  • Data alla stringa ISO8601
  • L'ora legale viene calcolata automaticamente

Stringhe ISO8601 di esempio

/*       "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
Attenzione: DateFormat e le classi derivate non sono compatibili con il multithread! L'uso di oggetti SimpleDateFormat statici come DATE_FORMAT_1 e DATE_FORMAT_2 significa che più thread che chiamano le funzioni ISO8601DateFormatter condivideranno lo stesso oggetto DateFormat. Ciò comporta il danneggiamento dei dati e la restituzione di date errate dalle chiamate DateFormat. Per risolvere questo problema, dovresti solo rendere costanti le stringhe di pattern e creare variabili SimpleDateFormat locali ogni volta che è necessario. Questo assicurerà che ogni oggetto sia usato da un solo thread.
Theo,

Una soluzione migliore per la sicurezza dei thread è invece utilizzare una libreria data-ora creata per la sicurezza dei thread. In Java quel mondo può essere Joda-Time o java.time.
Basil Bourque,

-1

Questo sembrava funzionare meglio per me:

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);
    }


}

Avevo bisogno di convertire in / fro stringhe di date JavaScript in Java. Ho trovato quanto sopra funziona con la raccomandazione. Alcuni esempi di utilizzo di SimpleDateFormat erano vicini ma non sembravano essere il sottoinsieme come raccomandato da:

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

e supportato da PLIST e JavaScript Strings e simili che è ciò di cui avevo bisogno.

Questa sembra essere la forma più comune di stringa ISO8601 e un buon sottoinsieme.

Gli esempi che danno sono:

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.

Ho anche una versione veloce:

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;
}

Non l'ho confrontato, ma credo che sarà abbastanza veloce. Sembra funzionare :)

@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

Penso che molte persone vogliano analizzare le stringhe di date JSON. C'è una buona possibilità se vieni in questa pagina che potresti voler convertire una data JSON JavaScript in una data Java.

Per mostrare l'aspetto di una stringa di date 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 stringa di data JSON è 2013-12-14T01: 55: 33.412Z.

Le date non sono coperte dalle specifiche JSON per dire, ma quanto sopra è un formato ISO 8601 molto specifico, mentre ISO_8601 è molto più grande e questo è un semplice sottoinsieme anche se molto importante.

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

Accade di aver scritto un parser JSON e un parser PLIST che usano entrambi ISO-8601 ma non gli stessi bit.

/*
    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);
}

Ho scritto due modi per farlo per il mio progetto. Uno standard, uno veloce.

Ancora una volta, la stringa di date JSON è un'implementazione molto specifica di ISO 8601 ....

(Ho pubblicato l'altro nell'altra risposta che dovrebbe funzionare per le date PLIST, che sono in un diverso formato ISO 8601).

La data di JSON è la seguente:

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);
    }


}

Anche i file PLIST (ASCII non GNUNext) usano ISO 8601 ma nessun millisecondo quindi ... non tutte le date ISO-8601 sono uguali. (Almeno non ne ho ancora trovato uno che usi milis e il parser che ho visto salta del tutto il fuso orario OMG).

Ora per la versione veloce (la puoi trovare in Boon).

public static Date fromJsonDate( String string ) {

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

}

Si noti che Reflection.toCharArray utilizza non sicuro se disponibile, ma per impostazione predefinita è string.toCharArray in caso contrario.

(È possibile estrarlo dall'esempio sostituendo Reflection.toCharArray (stringa) 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;
    }

}

IsJsonDate è implementato come segue:

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;
}

Comunque ... la mia ipotesi è che un bel po 'di persone che vengono qui potrebbero cercare la stringa di date JSON e sebbene sia una data ISO-8601, è molto specifica che necessita di un'analisi molto specifica.

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;
}

Vedi https://github.com/RichardHightower/boon Boon ha un parser PLIST (ASCII) e un parser JSON.

Il parser JSON è il parser Java JSON più veloce che io conosca.

Verificato indipendentemente dai ragazzi di 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

Ha il parser JSON più veloce per stream, lettori, byte [], char [], CharSequence (StringBuilder, CharacterBuffer) e String.

Vedi altri benchmark su:

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


Questa risposta su JSON è fuori tema dalla domanda. Inoltre, questa domanda non è corretta in quanto non esiste una "data JSON" tra i pochissimi tipi di dati JSON . E al giorno d'oggi, tutto questo codice può essere sostituito con una chiamata a linea singola alla funzione Java integrata:Instant.parse( "2013-12-14T01:55:33.412Z" )
Basil Bourque,
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.