Convertendo String compatível com ISO 8601 para java.util.Date


668

Estou tentando converter uma seqüência de caracteres formatada em ISO 8601 para um java.util.Date.

Achei que o padrão yyyy-MM-dd'T'HH:mm:ssZera compatível com ISO8601 se usado com um Local (compare amostra).

No entanto, usando o java.text.SimpleDateFormat, não consigo converter a String formatada corretamente 2010-01-01T12:00:00+01:00. Eu tenho que convertê-lo primeiro para 2010-01-01T12:00:00+0100, sem os dois pontos.

Então, a solução atual é

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

o que obviamente não é legal. Estou faltando alguma coisa ou há uma solução melhor?


Responda

Graças ao comentário de JuanZe, encontrei a magia Joda-Time , que também é descrita aqui .

Então, a solução é

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

Ou, mais simplesmente, use o analisador padrão por meio do construtor:

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

Para mim, isso é legal.


243
Esteja pronto para receber um monte de "Use JodaTime" respostas ...
JuanZe

3
@ Ice09: Se a documentação da API para DateTimeFormat estiver correta (a documentação do JoDa pode ser enganosa, errada ou incompleta), o padrão que você usou na sua "resposta" não é compatível com a ISO8601.
22410 jarnbjo

21
Não tenho certeza de quando isso foi adicionado, mas o 'X' parece resolver esse problema no SimpleDateFormat. O padrão "aaaa-MM-dd'T'HH: mm: ssX" analisa com êxito o exemplo na pergunta.
Mlohbihler 18/07/2012

12
O 'X' está disponível desde o Java 7.
Lars Grammel

3
O Java 8 facilita! Não é uma jóia escondida por Adam nas respostas abaixo: stackoverflow.com/a/27479533/1262901
Fabian Keller

Respostas:


477

Infelizmente, os formatos de fuso horário disponíveis para SimpleDateFormat (Java 6 e versões anteriores) não são compatíveis com ISO 8601 . SimpleDateFormat entende seqüências de fuso horário como "GMT + 01: 00" ou "+0100", este último de acordo com a RFC # 822 .

Mesmo que o Java 7 tenha adicionado suporte para descritores de fuso horário de acordo com a ISO 8601, o SimpleDateFormat ainda não poderá analisar adequadamente uma sequência de datas completa, pois não possui suporte para partes opcionais.

Reformatar sua string de entrada usando o regexp é certamente uma possibilidade, mas as regras de substituição não são tão simples quanto na sua pergunta:

  • Alguns fusos horários não são horas completas fora do UTC ; portanto, a sequência não termina necessariamente com ": 00".
  • A ISO8601 permite que apenas o número de horas seja incluído no fuso horário, portanto "+01" é equivalente a "+01: 00"
  • A ISO8601 permite o uso de "Z" para indicar UTC em vez de "+00: 00".

A solução mais fácil é possivelmente usar o conversor de tipo de dados no JAXB, pois o JAXB deve poder analisar a sequência de datas ISO8601 de acordo com a especificação do Esquema XML. javax.xml.bind.DatatypeConverter.parseDateTime("2010-01-01T12:00:00Z")lhe dará um Calendarobjeto e você pode simplesmente usar getTime (), se precisar de um Dateobjeto.

Você provavelmente poderia usar o Joda-Time também, mas não sei por que você deveria se preocupar com isso.


18
A solução JAXB é uma abordagem realmente criativa! Também funciona, eu testei com a minha amostra. No entanto, para quem enfrenta o problema e tem permissão para usar o JodaTime, aconselho a usá-lo, pois parece mais natural. Mas sua solução não requer bibliotecas adicionais (pelo menos com Java 6).
09

36
Aqui está o contrário: Calendário c = GregorianCalendar.getInstance (); c.setTime (aDate); retorne javax.xml.bind.DatatypeConverter.printDateTime (c);
Alexander Ljungberg

4
Na verdade, não é tão simples porque você precisa inicializar o conversor de dados jaxb. Acabei usando o DatatypeFactory como o DataTypeConverterImpl fez internamente. Que dor de cabeça.
gtrak

3
@ Simon: Não, é claro que os fusos horários não são ignorados. Você deve estar fazendo algo errado. Se você digitar mais do que alguns caracteres e nos contar o que realmente está fazendo, alguém poderá lhe explicar o que é.
22412 jarnbjo

4
@jarnbjo, você é a primeira e única pessoa que encontrei que prefere as classes padrão, pré-1.8, java date e joda-time. Acho o joda-time uma alegria literal de usar, especialmente quando comparado à API padrão, que é uma abominação.
NimChimpsky

245

A maneira que é abençoada pela documentação do 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);

Você pode encontrar mais exemplos na seção Exemplos em javadoc SimpleDateFormat .

UPD 13/02/2020: Existe uma maneira completamente nova de fazer isso no Java 8


7
Sua resposta me ajudou a converter o ISODate do MongoDB para a data local. Saudações.
Blue Sky

9
@ b.long Java adicionou mais do que uma constante para esses formatos compatíveis com ISO 8601. O Java recebeu uma estrutura totalmente nova para o trabalho de data e hora que inclui suporte padrão interno para esses formatos. Veja a nova java.timeestrutura no Java 8, inspirada no Joda-Time , substituindo as problemáticas classes java.util.Date, .Calendar e SimpleDateFormat.
Basil Bourque

2
Isso não significa que você precisa conhecer o formato da data com antecedência? E se você tiver que aceitar string1e string2não souber qual será o seu?
Timmmm

16
'Z' precisa estar entre aspas
kervin

7
@kervin Se o Z estiver entre aspas, o formatador não procurará especificamente o caractere Z, nem todas as seqüências de deslocamento que ele pode representar? Parece que citar Z só funcionaria por coincidência, se as strings de data estivessem no UTC.
spaaarky21

201

Ok, esta pergunta já foi respondida, mas deixarei minha resposta de qualquer maneira. Isso pode ajudar alguém.

Estou procurando uma solução para Android (API 7).

  • Joda estava fora de questão - é enorme e sofre de inicialização lenta. Também parecia um grande exagero para esse fim específico.
  • As respostas que envolvem javax.xmlnão funcionarão na API do Android 7.

Acabou implementando essa classe simples. Ele cobre apenas a forma mais comum de seqüências ISO 8601, mas isso deve ser suficiente em alguns casos (quando você tiver certeza de que a entrada estará nesse 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 desempenho: eu instanciao sempre o novo SimpleDateFormat como forma de evitar um bug no Android 2.1. Se você está tão surpreso quanto eu, veja este enigma . Para outros mecanismos Java, você pode armazenar em cache a instância em um campo estático privado (usando ThreadLocal, para ser seguro para threads).


2
Talvez isso devesse ter sido transformado em uma pergunta própria, com sua própria resposta?
Thorbear

5
Esta foi a primeira página que publiquei quando procurava a resposta, por isso parecia adequada. Para a maioria dos desenvolvedores Java, o Android não é exatamente Java. No entanto, na maioria dos casos, um funciona da mesma forma que o outro, muitos desenvolvedores do Android pesquisam "java" ao procurar por isso.
Wrygiel

1
Observe que isso não representa a resolução de milissegundos. Isso é fácil de adicionar.
Sky Kelsey

6
Eu tive que adicionar .SSS por segundos fracionários, mas funciona muito bem. Por que você faz s = s.substring(0, 22) + s.substring(23);- eu não ver o ponto em este
Dori

1
input = input.replaceAll ("[Zz]", "+0000"); também funcionará e a operação de substring pode ser evitada.
Javanator

115

java.time

A API java.time (incorporada no Java 8 e posterior) facilita um pouco isso.

Se você souber que a entrada está no UTC , como o Z(para Zulu) no final, a Instantclasse poderá analisar.

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

Se a sua entrada puder ser outro valor de deslocamento do UTC em vez do UTC indicado pelo Z(Zulu) no final, use a OffsetDateTimeclasse para analisar.

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

Em seguida, extraia um Instante converta para um java.util.Datechamando from.

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

8
Esta resposta está trabalhando demais. Um java.util.Date por definição não possui fuso horário. Portanto, não há necessidade de todo esse código relacionado ao fuso horário: the LocalDateTimee ZoneIdand atZone. Este simples comentário de uma linha fará:java.util.Date date = Date.from( ZonedDateTime.parse( "2014-12-12T10:39:40Z" ).toInstant() );
Basil Bourque

5
@BasilBourque Isso é desnecessariamente complicado: Date.from(Instant.parse("2014-12-12T10:39:40Z" ));basta.
Assilias

3
@assylias você está correto, mas que só vai funcionar quando a seqüência de data é a zona UTC, ISO8601 permite que qualquer fuso horário ...
Adam

2
@ Adam Meu mal - eu não tinha percebido que a pergunta era mais geral do que o seu exemplo. Como um comentário lateral, OffsetDateTimeseria suficiente analisar o ISO8601 (que não contém informações de fuso horário, mas apenas um deslocamento).
Assilias

1
@assylias Obrigado pelo seu comentário sobre como deixar Instanta análise. Embora não seja suficiente para esta questão em particular, é uma distinção importante que vale a pena destacar. Então eu adicionei um segundo exemplo de código. Opa, acabei de notar que essa não é originalmente minha resposta; Espero que Adam aprove.
Basil Bourque

67

A biblioteca Jackson-databind também possui a classe ISO8601DateFormat que faz isso (implementação real em ISO8601Utils .

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

Ela não consegue analisar esta data: 2015-08-11T13:10:00. Eu entendo String index out of range: 19. Observando o código, parece que ele exige que os milissegundos sejam especificados e o fuso horário. Esses devem ser opcionais.
Timmmm

2
Para citar a documentação, o formato de análise é: [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]. Em outras palavras, os milissegundos são opcionais, mas o fuso horário é obrigatório.
David_p 12/08/2015

2
Ah sim, na verdade, parece que você está certo. Ainda assim, tenho certeza de que a ISO8601 permite que você omita o fuso horário, para que ainda esteja errado. O JodaTime funciona:new DateTime("2015-08-11T13:10:00").toDate()
Timmmm 12/08/2015

3
Essa classe agora está obsoleta, a nova é StdDateFormat. Caso contrário, funciona da mesma maneira.
JohnEye

51

tl; dr

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

Usando java.time

O novo pacote java.time no Java 8 e posterior foi inspirado no Joda-Time.

A OffsetDateTimeclasse representa um momento na linha do tempo com um deslocamento do UTC, mas não um fuso horário.

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

A chamada toStringgera uma sequência no formato ISO 8601 padrão:

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

Para ver o mesmo valor pela lente do UTC, extraia Instantou ajuste o deslocamento de +01:00para 00:00.

Instant instant = odt.toInstant();  

…ou…

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

Ajuste para um fuso horário, se desejar. Um fuso horário é um histórico de valores de deslocamento do UTC para uma região, com um conjunto de regras para lidar com anomalias, como horário de verão (DST). Portanto, aplique um fuso horário em vez de um mero deslocamento sempre que possível.

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

Sobre java.time

A estrutura java.time é integrada ao Java 8 e posterior. Essas classes suplantar os velhos problemáticos legados aulas de data e hora, como java.util.Date, Calendar, e SimpleDateFormat.

O projeto Joda-Time , agora em modo de manutenção , aconselha a migração para as classes java.time .

Para saber mais, consulte o Tutorial do Oracle . E procure Stack Overflow para muitos exemplos e explicações. A especificação é JSR 310 .

Você pode trocar objetos java.time diretamente com seu banco de dados. Use um driver JDBC compatível com JDBC 4.2 ou posterior. Não há necessidade de strings, não há necessidade de java.sql.*classes.

Onde obter as classes java.time?

  • Java SE 8 , Java SE 9 , Java SE 10 e posterior
    • Construídas em.
    • Parte da API Java padrão com uma implementação em pacote configurável.
    • O Java 9 adiciona alguns recursos e correções menores.
  • Java SE 6 e Java SE 7
    • Grande parte da funcionalidade java.time é portada para Java 6 e 7 no ThreeTen-Backport .
  • Android
    • Versões posteriores das implementações de pacote configurável do Android das classes java.time.
    • Para anteriormente Android (<26), o ThreeTenABP projeto adapta ThreeTen-Backport (mencionados acima). Consulte Como usar o ThreeTenABP… .

O projeto ThreeTen-Extra estende o java.time com classes adicionais. Este projeto é um campo de prova para possíveis adições futuras ao java.time. Você pode encontrar algumas classes úteis aqui, como Interval, YearWeek, YearQuarter, e mais .



27

Para Java versão 7

Você pode seguir a documentação do Oracle: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

X - é usado para o fuso horário 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);

Isso significa que o fuso horário é necessário . De acordo com a ISO 8601, é opcional. Como são os segundos, etc. Então, isso só analisa um subconjunto específico de ISO 8601.
Timmmm

1
Funciona muito bem com Java 1.8
Thiago Pereira

20

A solução DatatypeConverter não funciona em todas as VMs. O seguinte funciona para mim:

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

Descobri que o joda não funciona imediatamente (especificamente para o exemplo que eu dei acima com o fuso horário em uma data, que deve ser válida)


15

Acho que deveríamos usar

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

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


5
Por que essa é uma resposta melhor do que as outras, incluiu a resposta aceita com 76 votos positivos?
Erick Robertson

3
@ErickRobertson: É simples, pronto para uso, flexível, sem conversões, e a maioria das pessoas não se importa com fusos horários.
TWiStErRob

7
Não adianta trabalhar com horários se você não se importa com fusos horários!
DORI

16
Isso ignora completamente o fuso horário. Estava usando isso até perceber que isso estava acontecendo, então mudei para o JodaTime.
Joshua Pinter

3
Descartar o fuso horário simplesmente resultará em erros em algum momento.
Bart van Kuik

11

A partir do Java 8, existe uma maneira completamente nova e oficialmente suportada de fazer isso:

    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 a sequência estiver no formato instantâneo, com a finalização Zcomo deslocamento, não precisamos especificar isso explicitamente. Apenas Instant i = Instant.parse(s);. A string na pergunta tinha +01:00, nesse caso DateTimeFormatter.ISO_INSTANT, não funciona (pelo menos não no meu Java 11).
Ole VV

3
@ OleV.V. Você pode usar ISO_OFFSET_DATE_TIMEpara formatar datas com deslocamentos, como +01:00( docs.oracle.com/javase/8/docs/api/java/time/format/… )
Lucas Basquerotto

1
Isso é verdade, @ LucasBasquerotto. Apesar de não mencionar explicitamente esse formatador, as respostas de Adam e Basil Bourque já fazem algo semelhante.
Ole VV

Isso não pode analisar "2020-06-01T14: 34: 00-05: 00", que é uma sequência produzida pelo método toISOString () do Javascript.
Jose Solorzano

10

Outra maneira muito simples de analisar os carimbos de data / hora ISO8601 é 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

Observe que no Java 8, você pode usar a classe java.time.ZonedDateTime e seu parse(CharSequence text)método estático .


As seqüências de entrada na pergunta têm apenas um deslocamento em relação ao UTC, não um fuso horário completo. Então, Instante ZonedDateTimesão apropriados aqui, não ZonedDateTime.
Basil Bourque

6

A solução alternativa para Java 7+ está usando SimpleDateFormat:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);

Este código pode analisar o formato ISO8601 como:

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

Mas no Java6, SimpleDateFormatnão entende o Xcaractere e lançará
IllegalArgumentException: Unknown pattern character 'X'
. Precisamos normalizar a data ISO8601 para o formato legível no Java 6 com 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 acima para substituir [ Zwith +0000] ou [ +01:00with +0100] quando ocorrer um erro no Java 6 (você pode detectar a versão Java e substituir try / catch pela instrução if).


Não, as classes antigas de data e hora problemáticas como Datee SimpleDateFormatsão mal projetadas, confusas e com falhas. Agora eles são herdados, substituídos pelas classes java.time incorporadas no Java 8 e posterior. Para Java 6 e Java 7, grande parte da funcionalidade java.time é portada no projeto ThreeTen-Backport . É muito melhor adicionar essa biblioteca ao seu aplicativo do que usar essas classes herdadas. Solução one-line em java.time:OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" )
Basil Bourque

5

Eu enfrentei o mesmo problema e resolvi-o pelo código a seguir.

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

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

Mas depois descobri que a principal causa da exceção foi a yyyy-MM-dd'T'HH:mm:ss.SSSZ,

Então eu usei

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

Funcionou bem para mim .


Exatamente o que eu precisava sem ter que usar joda-time, api XML ou qualquer outra coisa. Apenas o padrão correto.
Philippe Gioseffi


4

Java tem uma dúzia de maneiras diferentes de analisar uma data e hora, como demonstram as excelentes respostas aqui. Surpreendentemente, nenhuma das classes de tempo do Java implementa totalmente a ISO 8601!

Com o Java 8, eu recomendaria:

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

Isso manipulará exemplos no UTC e com um deslocamento, como "2017-09-13T10: 36: 40Z" ou "2017-09-13T10: 36: 40 + 01: 00". Isso servirá para a maioria dos casos de uso.

Mas ele não trata exemplos como "2017-09-13T10: 36: 40 + 01", que é uma data / hora ISO 8601 válida.
Ele também não trata apenas da data, por exemplo, "13/09/2017".

Se você precisar lidar com isso, sugiro usar um regex primeiro para farejar a sintaxe.

Há uma boa lista de ISO 8601 exemplos aqui com muitos casos de canto: https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/ eu sou não conhece nenhuma classe Java que possa lidar com todas elas.


OffsetDateTimefará e combina conceitualmente uma data e hora com um deslocamento melhor.
Ole VV

Hey @ OleV.V. Obrigado pela sugestão. Infelizmente não: OffsetDateTime.parse () irá lançar uma exceção para vários válidos ISO 8601 cordas, por exemplo, "2017-09-13T10: 36: 40 + 01" ou "2017/09/13"
Daniel Winterstein

Eu só quis dizer que OffsetDateTimelida com os exemplos com os quais você lida ZonedDateTime. Eu acredito que ele não lida com nenhum dos exemplos que ZonedDateTimenão. Nesse sentido, não há melhora (mas também não é pior). Desculpe, eu não estava perfeitamente claro.
Ole VV

1
Essa deve ser a resposta aceita em 2020, dado o estado das coisas.
slashCoder


3

Como outros usuários mencionaram, o Android não tem uma boa maneira de oferecer suporte à análise / formatação de datas ISO 8601 usando as classes incluídas no SDK. Eu escrevi esse código várias vezes, então finalmente criei um Gist que inclui uma classe DateUtils que oferece suporte à formatação e análise de datas ISO 8601 e RFC 1123. O Gist também inclui um caso de teste mostrando o que ele suporta.

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


2

SimpleDateFormat para JAVA 1.7 possui um padrão legal para o formato ISO 8601.

Classe SimpleDateFormat

Aqui está o que eu fiz:

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

2
Zna cadeia de formato não é ISO 8601 fuso horário, você deve usar X(ou XXou XXX) se quiser ISO 8601 fuso horário
Vojta

d é do tipo String
Tim Child

1

Faça isso deste modo:

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

}

Aqui está a saída:

Qua 19 de outubro 15:15:36 CST 2016


1

Use string como LocalDate.parse(((String) data.get("d_iso8601")),DateTimeFormatter.ISO_DATE)


1

Estou surpreso que nem mesmo uma biblioteca Java suporte todos os formatos de data ISO 8601, conforme https://en.wikipedia.org/wiki/ISO_8601 . O Joda DateTime estava suportando a maioria deles, mas não todos, e, portanto, adicionei uma lógica personalizada para lidar com todos eles. Aqui está a minha implementação.

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

Um pequeno teste que mostra como analisar uma data na ISO8601 e que LocalDateTime não processa DSTs.

 @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
FYI, os terrivelmente problemáticas aulas de data e hora, como java.util.Date, java.util.Calendar, e java.text.SimpleDateFormatsão agora legado , suplantado pelos java.time classes internas em Java 8 e posterior. Consulte o Tutorial da Oracle .
Basil Bourque

Você está certo que LocalDateTimenão lida com horário de verão (DST), pois não lida com um fuso horário. Para isso precisamos ZonedDateTime. Propondo Datee SimpleDateFormaté - IMHO ruim.
Ole VV

1
Na verdade, o ZonedDateTime funciona. E java.time.Instant também é uma boa alternativa para lidar com o horário de verão. Eu sei que java.util.Date é obsoleto e não deve ser usado, mas eu estava apenas respondendo a pergunta original: Como converter uma String em 8601 para java.util.date ....
ddtxra

0

Eu tinha uma necessidade semelhante: precisava ser capaz de analisar qualquer data compatível com ISO8601 sem conhecer o formato exato com antecedência e queria uma solução leve que também funcionasse no Android.

Quando pesquisei minhas necessidades, deparei-me com essa pergunta e notei que o AFAIU, nenhuma resposta se encaixava completamente nas minhas necessidades. Então, desenvolvi o jISO8601 e o empurrei na maven central.

Basta adicionar você pom.xml:

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

e então você está pronto para ir:

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

Espera que ajude.



-1

Cortesia da função base: @wrygiel.

Esta função pode converter o formato ISO8601 em Data Java, que pode manipular os valores de deslocamento. De acordo com a definição da ISO 8601, o deslocamento pode ser mencionado em 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 classe possui métodos estáticos para converter

  • String ISO8601 para o objeto Date (Local TimeZone)
  • Data para a sequência ISO8601
  • O horário de verão é calculado automaticamente

Amostras de cordas 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 e classes derivadas não são compatíveis com multithread! O uso de objetos estáticos SimpleDateFormat, como DATE_FORMAT_1 e DATE_FORMAT_2, significa que vários encadeamentos que chamam as funções ISO8601DateFormatter compartilharão o mesmo objeto DateFormat. Isso leva a corrupção de dados e datas incorretas sendo retornadas das chamadas DateFormat. Para corrigir isso, você deve apenas fazer constantes as seqüências de caracteres padrão e criar variáveis ​​locais SimpleDateFormat sempre que necessário. Isso garantirá que cada objeto seja usado apenas por um thread.
Theo

Uma correção melhor para a segurança de threads é usar uma biblioteca de data e hora criada para segurança de threads. Em Java, esse mundo é Joda-Time ou java.time.
Basil Bourque

-1

Isso pareceu funcionar melhor para mim:

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


}

Eu precisava converter para / para seqüências de datas JavaScript em Java. Eu encontrei os trabalhos acima com a recomendação. Havia alguns exemplos usando SimpleDateFormat próximos, mas eles não pareciam ser o subconjunto conforme recomendado por:

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

e suportado por PLIST e JavaScript Strings e é isso que eu precisava.

Essa parece ser a forma mais comum de cadeia de caracteres ISO8601, e um bom subconjunto.

Os exemplos que eles dão são:

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.

Eu também tenho uma versão 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;
}

Eu não o comparei, mas acho que será bem 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

Eu acho que o que muita gente quer fazer é analisar as seqüências de datas JSON. Existe uma boa chance de você vir para esta página converter uma data JSON JavaScript em uma data Java.

Para mostrar a aparência de uma sequência de datas 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)

A sequência de datas JSON é 2013-12-14T01: 55: 33.412Z.

As datas não são cobertas pelas especificações JSON, por exemplo, mas o acima é um formato ISO 8601 muito específico, enquanto o ISO_8601 é muito maior e esse é um mero subconjunto, embora muito importante.

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

Por acaso, escrevi um analisador JSON e um analisador PLIST, que usam ISO-8601, mas não os mesmos 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);
}

Eu escrevi duas maneiras de fazer isso no meu projeto. Um padrão, um rápido.

Novamente, a sequência de datas JSON é uma implementação muito específica da ISO 8601 ....

(Postei a outra na outra resposta, que deve funcionar para datas PLIST, que são um formato ISO 8601 diferente).

A data JSON é a seguinte:

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


}

Os arquivos PLIST (ASCII não GNUNext) também usam a ISO 8601, mas não milissegundos, portanto ... nem todas as datas da ISO-8601 são iguais. (Pelo menos ainda não encontrei um que use milis e o analisador que vi pular o fuso horário OMG).

Agora, a versão rápida (você pode encontrá-la no Boon).

public static Date fromJsonDate( String string ) {

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

}

Observe que Reflection.toCharArray usa inseguro, se disponível, mas o padrão é string.toCharArray, se não estiver.

(Você pode tirá-lo do exemplo substituindo Reflection.toCharArray (string) por 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;
    }

}

O isJsonDate é implementado da seguinte maneira:

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

Enfim ... meu palpite é que muitas pessoas que vêm aqui .. podem estar procurando a JSON Date String e, embora seja uma data ISO-8601, é uma data muito específica que precisa de uma análise muito específica.

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 O Boon possui um analisador PLIST (ASCII) e um analisador JSON.

O analisador JSON é o analisador Java JSON mais rápido que eu conheço.

Independentemente verificado pelos caras 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

Possui o analisador JSON mais rápido para fluxos, leitores, bytes [], char [], CharSequence (StringBuilder, CharacterBuffer) e String.

Veja mais benchmarks em:

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


Esta resposta sobre JSON está fora de tópico da pergunta. Além disso, esta pergunta está incorreta, pois não existe uma "data JSON" entre os poucos tipos de dados JSON . Hoje em dia, todo esse código pode ser substituído por uma chamada de linha única para o recurso Java embutido:Instant.parse( "2013-12-14T01:55:33.412Z" )
Basil Bourque
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.