Il formato di data JSON "giusto"


1138

Ho visto tanti standard diversi per il formato 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 è quello giusto? O meglio? C'è qualche tipo di standard su questo?


75
Non esiste un formato data in JSON, esistono solo stringhe che un de- / serializzatore decide di mappare ai valori data.

11
strings, numbers, true, false, null, objectsEarrays
Russ Cam

12
Tuttavia, l' oggetto JSON incorporato JavaScript e ISO8601 contengono tutte le informazioni che devono essere comprese dall'uomo e dal computer e non si basano sull'inizio dell'era del computer (1970-1-1).
Poussma,

Risposte:


1850

JSON stesso non specifica come debbano essere rappresentate le date, ma JavaScript lo fa.

Si consiglia di utilizzare il formato emessa da Date's toJSONmetodo:

2012-04-23T18:25:43.511Z

Ecco perché:

  1. È leggibile dall'uomo ma anche succinto

  2. Si ordina correttamente

  3. Include secondi frazionari, che possono aiutare a ristabilire la cronologia

  4. È conforme a ISO 8601

  5. La ISO 8601 è affermata a livello internazionale da oltre un decennio

  6. ISO 8601 è approvato da W3C , RFC3339 e XKCD

Detto questo , ogni libreria di date mai scritta può capire "millisecondi dal 1970". Quindi, per una facile portabilità, ThiefMaster ha ragione.


32
Questa è anche la rappresentazione preferita secondo l' ECMA :JSON.stringify({'now': new Date()}) "{"now":"2013-10-21T13:28:06.419Z"}"
Steven,

11
Vorrei aggiungere un altro motivo importante all'elenco: è indipendente dalla locale. Se hai avuto una data come il 02-03-2014, avresti bisogno di ulteriori informazioni per sapere se si riferisce al 3 febbraio o al 2 marzo. Dipende dall'uso del formato USA o di altro formato.
Juanal,

107
voto per menzionare e collegare xkcd: D @ajorquera Di solito uso momentjs per questo. Ho anche visto problemi con IE in questo senso
fholzer,

54
Per quanto riguarda il secondo punto, non si ordina correttamente dopo l'anno 10000. Abbiamo quasi 8000 anni per elaborare un nuovo formato, quindi probabilmente non è un problema.
Erfa,

7
In realtà, @Erfa, dato che -arriva prima delle cifre ASCII, andrà bene fino all'anno 100.000. ; P
Ben Leggiero,

128

JSON non sa nulla delle date. Quello che fa .NET è un hack / estensione non standard.

Vorrei utilizzare un formato che può essere facilmente convertito in un Dateoggetto in JavaScript, ovvero uno a cui è possibile passare new Date(...). Il formato più semplice e probabilmente più portatile è il timestamp contenente millisecondi dal 1970.


3
stackoverflow.com/questions/10286385/… - vediamo se qualcuno sa perché FF si comporta così.
ThiefMaster,

11
Se segui questa strada, assicurati di non dover affrontare date precedenti al 1970!
Ben Dolman,

8
Come diceva @BenDolman, questa "soluzione" non tratta in modo appropriato le date precedenti al 1 ° gennaio 1970 (epoca). Inoltre, c'è un motivo per cui ISO8601 esiste in primo luogo. Qui sulla Terra abbiamo cose chiamate "fusi orari". Dov'è quello in millisecondi? JSON non può avere uno standard per le date, ma esistono date al di fuori di JSON, e non v'è uno standard per questo. la risposta di funroll è quella corretta (vedi anche: xkcd.com/1179 ).
JoeLinux,

5
Vale forse anche la pena ricordare che (milli) secondi dal 1970 non sono prevedibili per le date future perché abbiamo secondi saltati . Quindi non userei se per la comunicazione tra processi e la memorizzazione dei dati. È comunque piacevole utilizzarlo internamente in un programma poiché può essere memorizzato in un unico numero intero che offre alcuni vantaggi in termini di prestazioni.
Brodie Garnet,

5
Il timestamp di Unix è sempre UTC, si converte dal fuso orario locale prima di generare il timestamp e di nuovo al fuso orario locale in mostra, non vi è alcuna ambiguità lì.
Lkraider,

46

Non esiste un formato corretto ; La specifica JSON non specifica un formato per lo scambio di date, motivo per cui ci sono molti modi diversi per farlo.

Il miglior formato è probabilmente una data rappresentata nel formato ISO 8601 ( vedi Wikipedia ); è un formato ben noto e ampiamente utilizzato e può essere gestito in molte lingue diverse, rendendolo molto adatto all'interoperabilità. Se si ha il controllo sul json generato, ad esempio, si forniscono dati ad altri sistemi in formato json, scegliendo 8601 come formato di scambio data è una buona scelta.

Se non si ha il controllo sul json generato, ad esempio, si è il consumatore di json da diversi sistemi esistenti, il modo migliore per gestirlo è disporre di una funzione di utilità di analisi della data per gestire i diversi formati previsti.


2
@mlissner ma questa è un'opinione su quale sia la migliore. ISO-8601 è uno standard, ma non è lo standard per JSON (anche se sarei propenso a usarlo); ad esempio, Microsoft ha deciso di non usarlo ( msdn.microsoft.com/en-us/library/… ). La migliore pratica è attenersi a una (ragionevole) convenzione, qualunque essa sia. Come ho affermato nella risposta, il modo migliore di gestirlo è definire una funzione di utilità di analisi della data in grado di gestire i formati previsti. Se ti integri con sistemi che utilizzano formati diversi, la funzione dovrebbe gestire ogni caso.
Russ Cam

1
@RussCam, possiamo andare avanti e indietro, ma se qualcuno sta chiedendo il modo migliore per codificare le date in JSON, stanno chiedendo come formattare le date quando creano JSON (e la risposta è generalmente ISO-8601). Stai rispondendo alla domanda opposta: come consumare le date JSON una volta che sono già state fatte (anche se il tuo consiglio è valido).
mlissner,

1
La specifica dello schema JSON afferma in realtà che le date verificate da uno schema devono essere nel formato 8601.
gnasher729,

3
@ gnasher729 hai un link?
Russ Cam,

@vallismortis - Questa è una bozza di specifica per la definizione di uno schema per una determinata struttura json scambiata tra le parti, non il formato per le date nella specifica json. Revisionerò la mia risposta basandomi sui commenti, non sembra che l'abbia chiarito abbastanza bene
Russ Cam

27

Da RFC 7493 (il formato dei messaggi I-JSON) :

I-JSON sta per Internet JSON o Interoperable JSON, a seconda di chi chiedi.

I protocolli contengono spesso elementi di dati progettati per contenere timestamp o durate. Si RACCOMANDA che tutti questi elementi di dati siano espressi come valori stringa nel formato ISO 8601, come specificato nella RFC 3339 , con le restrizioni aggiuntive che devono essere utilizzate lettere maiuscole anziché minuscole, che il fuso orario sia incluso non predefinito e che i secondi finali opzionali essere incluso anche quando il loro valore è "00". È inoltre RACCOMANDATO che tutti gli elementi di dati contenenti periodi di tempo siano conformi alla produzione "durata" nell'Appendice A della RFC 3339, con le stesse restrizioni aggiuntive.


2
Questo è anche il formato prodotto da Date().toISOString()e Date().toJSON(), con la limitazione che Datenon tiene traccia di un valore di fuso orario, e quindi emette sempre i timestamp nel Zfuso orario UTC ( ). Il valore può essere analizzato usando new Date("...")e Date.parseDate.
Søren Løvborg,

15

Solo per riferimento ho visto questo formato utilizzato:

Date.UTC(2017,2,22)

Funziona con JSONP che è supportato dalla $.getJSON()funzione. Non sono sicuro che mi spingerei fino a raccomandare questo approccio ... semplicemente lanciandolo là fuori come possibilità perché la gente lo sta facendo in questo modo.

FWIW: Non usare mai i secondi dall'epoca in un protocollo di comunicazione, né i millisecondi dall'epoca, perché sono pieni di pericoli grazie all'implementazione randomizzata dei secondi intercalari (non si ha idea se mittente e destinatario implementano correttamente i secondi intercalari UTC).

Una specie di odio da compagnia, ma molte persone credono che UTC sia solo il nuovo nome di GMT - sbagliato! Se il tuo sistema non implementa i secondi bisestili, stai usando GMT (spesso chiamato UTC nonostante sia errato). Se si implementano completamente i secondi bisestili, si utilizza davvero UTC. I secondi bisestili futuri non possono essere conosciuti; vengono pubblicati dallo IERS secondo necessità e richiedono aggiornamenti costanti. Se stai eseguendo un sistema che tenta di implementare secondi saltati ma contiene una tabella di riferimento non aggiornata (più comune di quanto potresti pensare), allora non hai né GMT, né UTC, hai un sistema traballante che finge di essere UTC.

Questi contatori di date sono compatibili solo se espressi in un formato suddiviso (y, m, d, ecc.). Non sono MAI compatibili in un formato d'epoca. Tienilo a mente.


4
Non userei quel formato, ma il resto delle informazioni che hai fornito è molto utile, grazie!
Robert Mikes,

9

In caso di dubbi, vai semplicemente alla console Web JavaScript di un browser moderno premendo F12 (Ctrl + K in Firefox) e scrivi quanto segue:

new Date().toISOString()

Uscita:

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

Ta-da !!


3

Credo che il miglior formato per l'interoperabilità universale non sia la stringa ISO-8601, ma piuttosto il formato utilizzato da EJSON:

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

Come descritto qui: https://docs.meteor.com/api/ejson.html

Benefici

  1. Prestazioni di analisi: se memorizzi le date come stringhe ISO-8601, questo è ottimo se ti aspetti un valore di data in quel determinato campo, ma se hai un sistema che deve determinare i tipi di valore senza contesto, stai analizzando ogni stringa per un formato data.
  2. Non è necessario per la convalida della data: non è necessario preoccuparsi della convalida e della verifica della data. Anche se una stringa corrisponde al formato ISO-8601, potrebbe non essere una data reale; questo non può mai accadere con una data EJSON.
  3. Dichiarazione di tipo inequivocabile: per quanto riguarda i sistemi di dati generici, se si desidera archiviare una stringa ISO come stringa in un caso e una data di sistema reale in un altro, i sistemi generici che adottano il formato di stringa ISO-8601 non lo consentiranno, meccanicamente (senza trucchi di fuga o simili soluzioni orribili).

Conclusione

Comprendo che un formato leggibile dall'uomo (stringa ISO-8601) è utile e più conveniente per l'80% dei casi d'uso, e in effetti a nessuno dovrebbe mai essere detto di non memorizzare le proprie date come stringhe ISO-8601 se questo è ciò che le loro applicazioni capire, ma per un formato di trasporto universalmente accettato che dovrebbe garantire determinati valori per essere sicuramente date, come possiamo consentire ambiguità e necessità di così tanta convalida?


Vedere questo precedente risposta nel thread del motivo per cui millisecondi dal momento epoca ha avvertimenti come ad esempio il calcolo non corretto del salto secondi ecc: stackoverflow.com/a/42480073/190476
Sudhanshu Mishra

@SudhanshuMishra Le avvertenze che fai riferimento sono gotcha generali per preoccupazioni estremamente accademiche di timestamp unix, principalmente legati alla generazione di timestamp. Ciò è ancor meno preoccupante per la risoluzione di millisecondi. Come è stato richiamato in un altro commento, la maggior parte delle date dei computer sono rappresentate internamente come timestamp unix, anche se sono esposte e formattate diversamente. Tuttavia, non c'è nulla di sbagliato nella rappresentazione in millisecondi di una data + ora specifica, soprattutto se confrontato con altri approcci, che possono essere facilmente influenzati dagli stessi avvertimenti di nano-impatto sotto il cofano.
Ciabaros,

Giusto da aggiungere per quanto riguarda le preoccupazioni relative alle date "fuori intervallo" per i timestamp unix: questi sono problemi di archiviazione del sistema, da affrontare in un contesto molto più ampio rispetto al formato di trasporto. Ad esempio, questo formato non deve essere limitato a numeri interi che si adattano a 32 bit, né devono essere numeri strettamente positivi, ma nessuno risolverà il "problema dell'anno 2038" facendo cadere i timestamp a livello di sistema / architettura ; devono solo essere espansi (ad esempio a 64 bit o oltre) e ciò non influisce sul formato di trasporto proposto.
Ciabaros,

3

JSON stesso non ha un formato data, non importa come qualcuno memorizza le date. Tuttavia, poiché questa domanda è contrassegnata con javascript, presumo che tu voglia sapere come archiviare le date javascript in JSON. Puoi semplicemente passare una data al JSON.stringifymetodo, che utilizzerà Date.prototype.toJSONper impostazione predefinita, che a sua volta utilizza Date.prototype.toISOString( MDN su 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

Ho anche trovato utile utilizzare il reviverparametro di JSON.parse( MDN su JSON.parse ) per convertire automaticamente le stringhe ISO in date javascript ogni volta che leggo le stringhe 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...

2

Il modo preferito sta usando 2018-04-23T18:25:43.511Z...

L'immagine seguente mostra perché questo è il modo preferito:

Data JSON

Come vedi Date ha un metodo nativo toJSON, che returnin questo formato e può essere facilmente convertito in Datenuovo ...


2
Corretta! La sintassi JSON Data Interchange non specifica lo standard: ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf ma, in pratica, i formati compatibili ISO 8601 sono più desiderabili su tutte le piattaforme, incluso il runtime JavaScript.
Kamyar Nazeri,

1

In Sharepoint 2013, ottenendo dati in JSON non esiste un formato per convertire la data in formato solo data, perché in quella data dovrebbe essere in formato ISO

yourDate.substring(0,10)

Questo può esserti utile


0

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

La data è rappresentata in un formato standard e ordinabile che rappresenta un'ora UTC (indicata dalla Z). ISO 8601 supporta anche i fusi orari sostituendo la Z con + o - per l'offset del fuso orario:

"2014-02-01T09: 28: 56,321-10: 00"

Esistono altre varianti della codifica del fuso orario nella specifica ISO 8601, ma il formato –10: 00 è l'unico formato TZ supportato dagli attuali parser JSON. In generale, è meglio utilizzare il formato basato su UTC (Z) a meno che non si abbia una necessità specifica di capire il fuso orario in cui è stata prodotta la data (possibile solo nella generazione lato server).

NB: var date = new Date (); console.log (data); // Mer 01 Gen 2014 13:28:56 GMT- 1000 (Hawaiian Standard Time)

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

per dirti che è il modo preferito anche se JavaScript non ha un formato standard per esso

// 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

0

Se stai usando Kotlin, questo risolverà il tuo problema. (Formato MS Json)

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

-3

funziona per me con parse Server

{
    "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"
            }
}

-6

C'è solo una risposta corretta a questo e la maggior parte dei sistemi sbaglia. Numero di millisecondi dall'epoca, ovvero un numero intero a 64 bit. Il fuso orario è un problema dell'interfaccia utente e non ha attività commerciali nel livello app o nel livello db. Perché il tuo db si preoccupa del fuso orario, quando sai che lo memorizzerà come numero intero a 64 bit, quindi esegui i calcoli di trasformazione.

Rimuovi i bit estranei e tratta le date come numeri fino all'interfaccia utente. È possibile utilizzare semplici operatori aritmetici per eseguire query e logica.


I commenti sono stati spostati nella chat .
Jon Clements

5
Ora hai 2 problemi: quale epoca dovresti scegliere e quali millisecondi dovresti contare? Probabilmente la scelta più comune è il tempo Unix (1970-01-01T00: 00: 00 millisecondi UTC e SI ad eccezione di quelli che rientrano in un secondo bisestile), ma ovviamente ciò rende indefiniti i tempi futuri.
aij,

2
Quindi, come si rappresentano i microsecondi? RFC3339 funziona perfettamente con qualsiasi precisione, avrai un lettore che analizza il fuso orario e ti dà il giusto timestamp, e sono informazioni aggiuntive. Le app di calendario di solito si preoccupano dei fusi orari.
gnasher729,

11
Il fuso orario non è un problema di interfaccia utente, a meno che non ti dispiaccia perdere il tuo prossimo volo. I voli sono pubblicati in ora locale e seguono regole specifiche per le modifiche dell'ora legale. Perdere l'offset significa perdere importanti informazioni commerciali
Panagiotis Kanavos il

1
Alcuni ulteriori controargomenti includono la capacità di rappresentare i tempi prima del 1970 (ipotizzando quell'epoca particolare) e la tendenza dei JSON ad essere in qualche modo leggibile dall'uomo.
Timo,

-8

Il seguente codice ha funzionato per me. Questo codice stampa la data nel formato GG-MM-AAAA .

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

altrimenti, puoi anche usare:

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

-19

Penso che dipenda davvero dal caso d'uso. In molti casi potrebbe essere più utile utilizzare un modello a oggetti adeguato (anziché eseguire il rendering della data in una stringa), in questo modo:

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

Certamente questo è più dettagliato di RFC 3339 ma:

  • è anche leggibile dall'uomo
  • implementa un modello a oggetti adeguato (come in OOP, per quanto JSON lo consenta)
  • supporta i fusi orari (non solo l'offset UTC alla data e ora indicate)
  • può supportare unità più piccole come millisecondi, nanosecondi, ... o semplicemente secondi frazionari
  • non richiede un passaggio di analisi separato (per analizzare la stringa di data e ora), il parser JSON farà tutto per te
  • facile creazione con qualsiasi framework di data e ora o implementazione in qualsiasi lingua
  • può essere facilmente esteso per supportare altre scale di calendario (ebraico, cinese, islamico ...) ed epoche (AD, BC, ...)
  • è l'anno 10000 sicuro ;-) (RFC 3339 non lo è)
  • supporta le date di tutto il giorno e i tempi mobili (Javascript Date.toJSON()no)

Non penso che l'ordinamento corretto (come notato da funroll per RFC 3339) sia una funzionalità che è davvero necessaria durante la serializzazione di una data su JSON. Inoltre, questo vale solo per gli orari di data con lo stesso offset di fuso orario.


7
Dubito che qualcuno userà json nell'anno 10000, o anche che a quel punto l'anno 10000 sarà ancora l'anno 10000. Ma se entrambe queste cose sono ancora vere per allora, il formato può semplicemente essere espanso per contenere una cifra di 3 cifre componente del secolo. Quindi direi che le persone possono tranquillamente attenersi a RFC 3339, almeno fino all'anno 9900
memoria di un sogno

8
@downvoters: Secondo Perché è importante votare? dovresti sottovalutare se a post contains wrong information, is poorly researched, or fails to communicate information. Spiegare per quale di questi motivi è stata annullata la votazione di questa risposta.
Marten,

5
@Marten Due cose. 1. Non hai mai dovuto una spiegazione per i voti negativi, anche se capisco che può essere utile. 2. Non ho votato in negativo la tua risposta, ma immagino che alla tua risposta non piaccia perché pensano che sia il modo sbagliato di farlo. Ciò lo qualificherebbe come "informazione errata" poiché la domanda sta cercando il modo migliore per fare qualcosa
Kevin Wells,

7
Non ti ho sottovalutato, ma posso certamente capire come "inventare un altro formato mal specificato" (che è fondamentalmente quello che stai dicendo) sarebbe visto come sbagliato o scarsamente studiato.
aij,

2
@Phil, UTC non è in realtà un fuso orario (non esiste un luogo al mondo che utilizza "UTC" come fuso orario ufficiale), è uno standard orario . Anche gli offset di fuso orario sono piuttosto imprevedibili. Non c'è modo di dire se nel 2025 "12:00 Moscow time" è ancora "9:00 UTC" come è oggi, è stato cambiato un paio di volte negli ultimi 30 anni . Se si desidera esprimere una futura ora locale, sono necessari veri fusi orari.
Marten,
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.