O formato de data JSON "correto"

1137

Eu já vi muitos padrões diferentes para o formato de data JSON:

"\"\\/Date(1335205592410)\\/\""         .NET JavaScriptSerializer
"\"\\/Date(1335205592410-0500)\\/\""    .NET DataContractJsonSerializer
"2012-04-23T18:25:43.511Z"              JavaScript built-in JSON object
"2012-04-21T18:25:43-05:00"             ISO 8601

Qual é o caminho certo? Ou melhor? Existe algum tipo de padrão nisso?

Kamyar Nazeri
fonte
75
Não há formato de data no JSON, há apenas cadeias de caracteres que um de- / serializador decide mapear para valores de data.
11
strings, numbers, true, false, null, objectsEarrays
Russ Cam
12
No entanto, o objeto JSON interno do JavaScript e a ISO8601 contém todas as informações a serem compreendidas por humanos e computadores e não se baseiam no início da era do computador (1970-1-1).
poussma 23/01

Respostas:

1849

O próprio JSON não especifica como as datas devem ser representadas, mas o JavaScript sim.

Você deve usar o formato emitida por Date's toJSONmétodo:

2012-04-23T18:25:43.511Z

Aqui está o porquê:

  1. É legível por humanos, mas também sucinto

  2. Classifica corretamente

  3. Inclui segundos fracionários, que podem ajudar a restabelecer a cronologia

  4. Está em conformidade com a ISO 8601

  5. A ISO 8601 está bem estabelecida internacionalmente há mais de uma década

  6. O ISO 8601 é endossado por W3C , RFC3339 e XKCD

Dito isto , toda biblioteca de datas já escrita pode entender "milissegundos desde 1970". Portanto, para facilitar a portabilidade, o ThiefMaster está certo.

funroll
fonte
32
Esta é também a representação preferida de acordo com a ECMA :JSON.stringify({'now': new Date()}) "{"now":"2013-10-21T13:28:06.419Z"}"
Steven
11
Eu acrescentaria outro motivo importante à lista: é independente da localidade. Se você teve uma data como 02-02-2014, precisará de informações adicionais para saber se se refere a 3 de fevereiro ou 2 de março. Depende se o formato dos EUA ou outro formato é usado.
Juanal
107
voto positivo por mencionar e vincular xkcd: D @ajorquera Eu geralmente uso momentjs para isso. Eu também vi problemas com o IE a este respeito
fholzer
54
Quanto ao segundo ponto, ele não é classificado corretamente após o ano 10000. Temos quase 8000 anos para criar um novo formato, portanto, provavelmente não é um problema.
Erfa
7
Na verdade, @Erfa, já que -vem antes dos dígitos ASCII, ele ficará bem até o ano 100.000. ; P
Ben Leggiero
128

JSON não sabe nada sobre datas. O que o .NET faz é um hack / extensão não padrão.

Eu usaria um formato que possa ser facilmente convertido em um Dateobjeto em JavaScript, ou seja, um que possa ser passado para new Date(...). O formato mais fácil e provavelmente o mais portátil é o carimbo de data / hora que contém milissegundos desde 1970.

ThiefMaster
fonte
3
stackoverflow.com/questions/10286385/… - vamos ver se alguém sabe por que o FF se comporta dessa maneira.
ThiefMaster
11
Se você seguir esse caminho, verifique se não precisa lidar com datas anteriores a 1970!
Ben Dolman
8
Como o @BenDolman disse, essa "solução" não lida adequadamente com datas anteriores a 1º de janeiro de 1970 (época). Além disso, existe uma razão pela qual a ISO8601 existe em primeiro lugar. Aqui na Terra, temos coisas chamadas "fusos horários". Onde é isso em milissegundos? JSON pode não ter um padrão para datas, mas existem datas fora do JSON, e não é um padrão para isso. A resposta do funroll é a correta (consulte também: xkcd.com/1179 ).
21813 JoeLinux
5
Talvez também valha a pena mencionar que (mili) segundos de 1970 não é previsível para datas no futuro, porque temos segundos bissextos . Portanto, eu não usaria isso para comunicação entre processos e armazenamento de dados. No entanto, é bom usar internamente em um programa, pois ele pode ser armazenado em um único número inteiro, o que oferece alguns benefícios de desempenho.
Brodie Garnet #
5
O registro de data e hora do Unix é sempre UTC, você converte do fuso horário local antes de gerar o registro de data e hora e, novamente, volta para o fuso horário local em exibição, não há ambiguidade lá.
lkraider
46

Não há formato certo ; A especificação JSON não especifica um formato para troca de datas e é por isso que existem tantas maneiras diferentes de fazer isso.

O melhor formato é sem dúvida uma data representada no formato ISO 8601 ( consulte a Wikipedia ); é um formato bem conhecido e amplamente usado e pode ser manipulado em vários idiomas diferentes, tornando-o muito adequado para interoperabilidade. Se você tiver controle sobre o json gerado, por exemplo, forneça dados para outros sistemas no formato json, escolhendo 8601 como o formato de troca de datas é uma boa opção.

Se você não tem controle sobre o json gerado, por exemplo, é consumidor de json de vários sistemas existentes diferentes, a melhor maneira de lidar com isso é ter uma função de utilitário de análise de data para lidar com os diferentes formatos esperados.

Russ Cam
fonte
2
@mlissner, mas essa é uma opinião sobre qual é o melhor. ISO-8601 é um padrão, mas não é o padrão para JSON (mesmo que eu esteja inclinado a usá-lo); por exemplo, a Microsoft decidiu não usá-lo ( msdn.microsoft.com/en-us/library/… ). A melhor prática é manter uma convenção (sensata), qualquer que seja. Como afirmei na resposta, a melhor maneira de lidar com isso é definir uma função do utilitário de análise de data que possa lidar com os formatos esperados. Se você se integrar a sistemas que usam formatos diferentes, a função deve tratar de cada caso.
Russ Cam
1
@RussCam, podemos ir e voltar, mas se alguém está perguntando a melhor maneira de codificar datas no JSON, está perguntando como formatar datas quando cria o JSON (e a resposta geralmente é ISO-8601). Você está respondendo à pergunta oposta: como consumir datas JSON depois que elas já foram feitas (embora seu conselho seja válido).
mlissner
1
A especificação do esquema JSON realmente diz que as datas verificadas por um esquema devem estar no formato 8601.
gnasher729
3
@ gnasher729 você tem um link?
Russ Cam
@vallismortis - Esse é um rascunho de especificação para definir um esquema para uma determinada estrutura json trocada entre as partes, não o formato para datas na especificação json. Vou revisar minha resposta com base nos comentários, não parece que eu deixei claro o suficiente #
Russ Cam
27

Do RFC 7493 (o formato de mensagem I-JSON) :

I-JSON significa Internet JSON ou Interoperable JSON, dependendo de quem você perguntar.

Os protocolos geralmente contêm itens de dados projetados para conter registros de data e hora ou durações de tempo. É RECOMENDADO que todos esses itens de dados sejam expressos como valores de sequência no formato ISO 8601, conforme especificado na RFC 3339 , com as restrições adicionais de que letras maiúsculas e não minúsculas sejam usadas, que o fuso horário seja incluído como não padrão e que os segundos finais opcionais ser incluído mesmo quando o valor for "00". Também é RECOMENDADO que todos os itens de dados que contêm durações de tempo estejam em conformidade com a produção de "duração" no Apêndice A da RFC 3339, com as mesmas restrições adicionais.

Bryan Larsen
fonte
2
Esse também é o formato produzido por Date().toISOString()e Date().toJSON(), com a limitação que Datenão controla um valor de fuso horário e, portanto, sempre emite os carimbos de data e hora no Zfuso horário UTC ( ). O valor pode ser analisado usando new Date("...")e Date.parseDate.
Søren Løvborg 21/09/2015
15

Apenas para referência, vi este formato usado:

Date.UTC(2017,2,22)

Funciona com JSONP, que é suportado pela $.getJSON()função Não tenho certeza se eu recomendaria essa abordagem ... apenas lançá-la como uma possibilidade, porque as pessoas estão fazendo dessa maneira.

FWIW: nunca use segundos desde a época em um protocolo de comunicação, nem milissegundos desde a época, porque eles são perigosos graças à implementação aleatória de segundos bissextos (você não tem idéia se o emissor e o receptor implementam corretamente os segundos bissextos UTC).

Um tipo de ódio por animais de estimação, mas muitas pessoas acreditam que o UTC é apenas o novo nome para GMT - errado! Se o seu sistema não implementar segundos bissextos, você estará usando o GMT (geralmente chamado de UTC, apesar de incorreto). Se você implementar totalmente os segundos bissextos, estará realmente usando o UTC. Os segundos bissextos futuros não podem ser conhecidos; eles são publicados pelo IERS conforme necessário e exigem atualizações constantes. Se você estiver executando um sistema que tenta implementar segundos bissextos, mas contém uma tabela de referência desatualizada (mais comum do que você imagina), não possui GMT nem UTC, mas um sistema instável que finge ser UTC.

Esses contadores de datas são compatíveis apenas quando expressos em um formato dividido (y, m, d, etc). NUNCA são compatíveis em um formato de época. Tenha isso em mente.

Tel
fonte
4
Eu não usaria esse formato, mas o restante das informações que você forneceu é muito útil, obrigado!
Robert Mikes
9

Em caso de dúvida, basta acessar o console da web javascript de um navegador moderno pressionando F12 (Ctrl + K no Firefox) e escreva o seguinte:

new Date().toISOString()

Saída:

"2019-07-04T13: 33: 03.969Z"

Ta-da !!

Shayan Ahmad
fonte
3

Acredito que o melhor formato para interoperabilidade universal não é a string ISO-8601, mas o formato usado pela EJSON:

{ "myDateField": { "$date" : <ms-since-epoch> } }

Conforme descrito aqui: https://docs.meteor.com/api/ejson.html

Benefícios

  1. Analisando o desempenho: se você armazena datas como sequências ISO-8601, isso é ótimo se você espera um valor de data nesse campo específico, mas se você possui um sistema que deve determinar os tipos de valor sem contexto, está analisando cada sequência Formato de data.
  2. Não há necessidade de validação de data: você não precisa se preocupar com a validação e a verificação da data. Mesmo que uma sequência corresponda ao formato ISO-8601, pode não ser uma data real; isso nunca pode acontecer com uma data EJSON.
  3. Declaração de tipo inequívoca: no que diz respeito aos sistemas de dados genéricos, se você deseja armazenar uma sequência ISO como uma sequência em um caso e uma data real do sistema em outra, os sistemas genéricos que adotam o formato de sequência ISO-8601 não permitirão isso mecanicamente (sem truques de fuga ou soluções terríveis semelhantes).

Conclusão

Entendo que um formato legível por humanos (string ISO-8601) é útil e mais conveniente para 80% dos casos de uso e, de fato, ninguém deve ser instruído a não armazenar suas datas como strings ISO-8601, se esse for o seu aplicativo. Entenda, mas para um formato de transporte universalmente aceito que garanta que certos valores sejam com certeza datas, como podemos permitir ambiguidade e necessidade de tanta validação?

Ciabaros
fonte
Veja esta resposta no início da rosca para o porquê milissegundos desde época tem ressalvas, como computação incorreto de segundos bissextos etc: stackoverflow.com/a/42480073/190476
Sudhanshu Mishra
@SudhanshuMishra As advertências mencionadas são dicas gerais para preocupações extremamente acadêmicas de carimbos de data e hora unix, principalmente relacionadas à geração de carimbos de data e hora. Isso é ainda menos preocupante com a resolução de milissegundos. Como foi destacado em outro comentário, a maioria das datas dos computadores são representadas internamente como carimbos de data e hora unix, mesmo que sejam expostos e formatados de outra forma. No entanto, não há nada de errado com a representação em milissegundos de qualquer data e hora, especialmente quando comparadas com outras abordagens, que podem ser facilmente afetadas pelas mesmas advertências de nano-impacto sob o capô.
Ciabaros
Apenas para adicionar preocupações com datas "fora do intervalo" para registros de data e hora unix: esses são problemas de armazenamento do sistema, que devem ser abordados em um contexto muito mais amplo que o formato de transporte. Por exemplo, esse formato não precisa se limitar a números inteiros que cabem em 32 bits, nem números estritamente positivos, mas ninguém resolverá o "problema do ano 2038" eliminando os carimbos de data / hora no nível do sistema / arquitetura ; eles só precisam ser expandidos (por exemplo, para 64 bits ou mais) e isso não afeta o formato de transporte proposto.
Ciabaros
3

O JSON em si não tem formato de data, não importa como alguém armazena datas. No entanto, como essa pergunta está marcada com javascript, suponho que você queira saber como armazenar datas javascript em JSON. Você pode simplesmente passar uma data para o JSON.stringifymétodo, que será usado Date.prototype.toJSONpor padrão, que por sua vez usa Date.prototype.toISOString( MDN em Date.toJSON ):

const json = JSON.stringify(new Date());
const parsed = JSON.parse(json); //2015-10-26T07:46:36.611Z
const date = new Date(parsed); // Back to date object

Também achei útil usar o reviverparâmetro JSON.parse( MDN no JSON.parse ) para converter automaticamente cadeias ISO de volta a datas javascript sempre que leio cadeias JSON.

const isoDatePattern = new RegExp(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/);

const obj = {
 a: 'foo',
 b: new Date(1500000000000) // Fri Jul 14 2017, etc...
}
const json = JSON.stringify(obj);

// Convert back, use reviver function:
const parsed = JSON.parse(json, (key, value) => {
    if (typeof value === 'string' &&  value.match(isoDatePattern)){
        return new Date(value); // isostring, so cast to js date
    }
    return value; // leave any other value as-is
});
console.log(parsed.b); // // Fri Jul 14 2017, etc...
Justus Romijn
fonte
2

A maneira preferida é usar 2018-04-23T18:25:43.511Z...

A figura abaixo mostra por que essa é a maneira preferida:

Data JSON

Então, como você vê, o Date tem um método nativo toJSON, que returnneste formato pode ser facilmente convertido em Datenovamente ...

Alireza
fonte
2
Corrigir! A sintaxe do JSON Data Interchange não especifica o padrão: ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf, mas, na prática, os formatos compatíveis com ISO 8601 são mais desejáveis ​​em plataformas, incluindo o tempo de execução JavaScript.
Kamyar Nazeri 31/01/19
1

No Sharepoint 2013, obtendo dados em JSON, não há formato para converter data em formato somente data, porque nessa data deve estar no formato ISO

yourDate.substring(0,10)

Isso pode ser útil para você

raghava arr
fonte
0

"2014-01-01T23: 28: 56.782Z"

A data é representada em um formato padrão e classificável que representa uma hora UTC (indicada pelo Z). O ISO 8601 também suporta fusos horários, substituindo o Z por um valor + ou - para o deslocamento do fuso horário:

"2014-02-01T09: 28: 56.321-10: 00"

Existem outras variações da codificação de fuso horário na especificação ISO 8601, mas o formato –10: 00 é o único formato TZ que os analisadores JSON atuais suportam. Em geral, é melhor usar o formato baseado em UTC (Z), a menos que você tenha uma necessidade específica de descobrir o fuso horário em que a data foi produzida (possível apenas na geração no servidor).

NB: var date = nova data (); console.log (data); // Qua 01/01/2014 13:28:56 GMT- 1000 (Horário padrão do Havaí)

var json = JSON.stringify(date);
console.log(json);  // "2014-01-01T23:28:56.782Z"

para lhe dizer que é a maneira preferida, mesmo que o JavaScript não tenha um formato padrão para ele

// JSON encoded date
var json = "\"2014-01-01T23:28:56.782Z\"";

var dateStr = JSON.parse(json);  
console.log(dateStr); // 2014-01-01T23:28:56.782Z
Pedro JR
fonte
0

Se você estiver usando o Kotlin, isso resolverá o seu problema. (Formato MS Json)

val dataString = "/Date(1586583441106)/"
val date = Date(Long.parseLong(dataString.substring(6, dataString.length - 2)))
suhas sasuke
fonte
-3

é trabalho para mim com o servidor de análise

{
    "ContractID": "203-17-DC0101-00003-10011",
    "Supplier":"Sample Co., Ltd",
    "Value":12345.80,
    "Curency":"USD",
    "StartDate": {
                "__type": "Date",
                "iso": "2017-08-22T06:11:00.000Z"
            }
}
Kemal Karadag
fonte
-6

Existe apenas uma resposta correta para isso e a maioria dos sistemas entende errado. Número de milissegundos desde a época, também conhecido como número inteiro de 64 bits. O fuso horário é uma preocupação da interface do usuário e não tem negócios na camada de aplicativo ou na camada de banco de dados. Por que seu banco de dados se importa com o fuso horário de algo, quando você sabe que ele será armazenado como um número inteiro de 64 bits, faça os cálculos de transformação.

Retire os bits estranhos e apenas trate as datas como números até a interface do usuário. Você pode usar operadores aritméticos simples para fazer consultas e lógica.

Chad Wilson
fonte
Os comentários foram movidos para o bate-papo .
Jon Clements
5
Agora você tem 2 problemas: qual época você deve escolher e quais milissegundos você deve contar? Provavelmente, a escolha mais comum é a hora do Unix (1970-01-01T00: 00: 00 UTC e SI milissegundos, exceto aqueles que ficam dentro de um salto de segundo), mas é claro que isso torna os tempos futuros indefinidos.
aij
2
Então, como você representa microssegundos? O RFC3339 funciona bem com qualquer precisão, você terá um leitor que analisa o fuso horário e fornece o carimbo de hora correto, além de informações adicionais. Os aplicativos de calendário geralmente se preocupam com fusos horários.
precisa saber é o seguinte
11
O fuso horário não é uma preocupação da interface do usuário, a menos que você não se importe de perder seu próximo voo. Os voos são publicados no horário local e seguem regras específicas para alterações no horário de verão. Perder os meios compensar a perda de informações de negócios importantes
Panagiotis Kanavos
1
Alguns contra-argumentos adicionais incluem a capacidade de representar tempos antes de 1970 (assumindo essa época específica) e a tendência dos JSONs a serem algo legíveis por humanos.
Timo
-8

O código a seguir funcionou para mim. Este código imprimirá a data no formato DD-MM-AAAA .

DateValue=DateValue.substring(6,8)+"-"+DateValue.substring(4,6)+"-"+DateValue.substring(0,4);

caso contrário, você também pode usar:

DateValue=DateValue.substring(0,4)+"-"+DateValue.substring(4,6)+"-"+DateValue.substring(6,8);
Aniket Kumar Shrivastava
fonte
-19

Eu acho que isso realmente depende do caso de uso. Em muitos casos, pode ser mais benéfico usar um modelo de objeto adequado (em vez de renderizar a data em uma string), da seguinte maneira:

{
"person" :
      {
 "name" : {
   "first": "Tom",
   "middle": "M",
  ...
}
 "dob" :  {
         "year": 2012,
         "month": 4,
         "day": 23,
         "hour": 18,
         "minute": 25,
         "second": 43,
         "timeZone": "America/New_York"
    }   
   }
}

É certo que isso é mais detalhado que o RFC 3339, mas:

  • é legível por humanos também
  • implementa um modelo de objeto adequado (como em OOP, na medida em que o JSON permite)
  • suporta fusos horários (não apenas o deslocamento UTC na data e hora especificadas)
  • pode suportar unidades menores, como milissegundos, nanossegundos, ... ou simplesmente segundos fracionários
  • não requer uma etapa de análise separada (para analisar a cadeia de data e hora), o analisador JSON fará tudo por você
  • criação fácil com qualquer estrutura de data e hora ou implementação em qualquer idioma
  • pode ser facilmente estendido para suportar outras escalas de calendário (hebraico, chinês, islâmico ...) e eras (AD, BC, ...)
  • é ano 10000 seguro ;-) (a RFC 3339 não é)
  • suporta datas o dia inteiro e horários flutuantes (o Javascript Date.toJSON()não)

Não acho que a classificação correta (como observado pelo funroll da RFC 3339) seja um recurso realmente necessário ao serializar uma data para JSON. Isso também é válido para datas e horários com o mesmo deslocamento de fuso horário.

Marta
fonte
7
Duvido que alguém esteja usando json no ano 10000, ou mesmo que nessa época o ano 10000 ainda seja o ano 10000. Mas se essas duas coisas ainda são verdadeiras, o formato pode ser simplesmente expandido para conter 3 dígitos componente do século. Então eu diria que as pessoas podem ficar em segurança com RFC 3339, pelo menos até o ano 9900
memória de um sonho
8
@ downvoters: De acordo com Por que a votação é importante? você deve votar se a post contains wrong information, is poorly researched, or fails to communicate information. Por favor, explique por qual desses motivos você recusou esta resposta.
Marten
5
@Marten Duas coisas. 1. Você nunca deve uma explicação para votos negativos, embora eu entenda que isso pode ser útil. 2. Não neguei sua resposta, mas acho que as pessoas não gostam da sua resposta porque pensam que é a maneira errada de fazer isso. Isso seria qualificá-lo como "informação errada", já que a questão está procurando a melhor maneira de fazer alguma coisa
Kevin Wells
7
Não diminuí a votação, mas certamente posso entender como "inventar outro formato mal especificado" (que é basicamente o que você está dizendo) seria visto como errado ou mal pesquisado.
aij
2
@ Phil, o UTC não é realmente um fuso horário (não há nenhum lugar no mundo que use "UTC" como seu fuso horário oficial), é um padrão de tempo . As compensações de fuso horário também são imprevisíveis. Não há como dizer se em 2025 a "12:00 hora de Moscou" ainda é "9:00 UTC", como é hoje, foi alterada algumas vezes nos últimos 30 anos . Se você deseja expressar uma hora local futura, precisa de fusos horários verdadeiros.
Marten