Le «bon» format de date JSON

1138

J'ai vu tellement de normes différentes pour le format de date 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

Lequel est le bon? Ou mieux? Existe-t-il une sorte de norme à ce sujet?

Kamyar Nazeri
la source
75
Il n'y a pas de format de date dans JSON, il n'y a que des chaînes qu'un dé- / sérialiseur décide de mapper aux valeurs de date.
11
strings, numbers, true, false, null, objectsEtarrays
Russ Cam
12
Cependant, l' objet JSON JavaScript intégré et ISO8601 contient toutes les informations à comprendre par l'homme et l'ordinateur et ne repose pas sur le début de l'ère informatique (1970-1-1).
poussma

Réponses:

1850

JSON lui - même ne spécifie pas comment les dates doivent être représentées, mais JavaScript le fait.

Vous devez utiliser le format émis par Datedes » toJSONméthode:

2012-04-23T18:25:43.511Z

Voici pourquoi:

  1. C'est lisible par l'homme mais aussi succinct

  2. Il trie correctement

  3. Il comprend des secondes fractionnaires, ce qui peut aider à rétablir la chronologie

  4. Il est conforme à ISO 8601

  5. ISO 8601 est bien établie à l'échelle internationale depuis plus d'une décennie

  6. ISO 8601 est approuvée par W3C , RFC3339 et XKCD

Cela étant dit , chaque bibliothèque de dates jamais écrite peut comprendre "millisecondes depuis 1970". Donc, pour une portabilité facile, ThiefMaster a raison.

funroll
la source
32
C'est aussi les représentations privilégiées selon l' ECMA :JSON.stringify({'now': new Date()}) "{"now":"2013-10-21T13:28:06.419Z"}"
Steven
11
J'ajouterais une autre raison importante à la liste: elle est indépendante des paramètres régionaux. Si vous aviez une date comme le 02-03-2014, vous auriez besoin d'informations supplémentaires pour savoir si elle fait référence au 3 février ou au 2 mars. Cela dépend si le format américain ou un autre format est utilisé.
Juanal
107
upvote pour mentionner et lier xkcd: D @ajorquera J'utilise habituellement momentjs pour cela. J'ai également vu des problèmes avec IE à cet égard
fholzer
54
En ce qui concerne le deuxième point, il ne trie pas correctement après l'année 10000. Nous avons cependant près de 8000 ans pour trouver un nouveau format, donc ce n'est probablement pas un problème.
Erfa
7
En fait, @Erfa, car -avant les chiffres ASCII, il triera très bien jusqu'à 100 000 ans. ; P
Ben Leggiero
128

JSON ne sait rien des dates. Ce que fait .NET est un hack / extension non standard.

J'utiliserais un format qui peut être facilement converti en Dateobjet en JavaScript, c'est-à-dire qui peut être transmis new Date(...). Le format le plus simple et probablement le plus portable est l'horodatage contenant des millisecondes depuis 1970.

ThiefMaster
la source
3
stackoverflow.com/questions/10286385/… - voyons si quelqu'un sait pourquoi FF se comporte comme ça.
ThiefMaster
11
Si vous suivez cette voie, assurez-vous que vous n'avez pas besoin de traiter des dates antérieures à 1970!
Ben Dolman
8
Comme l'a dit @BenDolman, cette "solution" ne traite pas correctement les dates antérieures au 1er janvier 1970 (Epoch). De plus, il y a une raison pour laquelle ISO8601 existe en premier lieu. Ici sur Terre, nous avons des choses appelées «fuseaux horaires». Où est-ce en millisecondes? JSON peut ne pas avoir de norme pour les dates, mais les dates existent en dehors de JSON, et il existe une norme pour cela. La réponse de funroll est la bonne (voir aussi: xkcd.com/1179 ).
JoeLinux
5
Il convient peut-être également de mentionner que les (milli) secondes de 1970 ne sont pas prévisibles pour les dates futures, car nous avons des secondes intercalaires . Je n'utiliserais donc pas if pour la communication interprocessus et le stockage de données. Il est cependant agréable de l'utiliser en interne dans un programme car il peut être stocké dans un seul entier, ce qui vous donne des avantages en termes de performances.
Brodie Garnet
5
L'horodatage Unix est toujours UTC, vous effectuez une conversion à partir de votre fuseau horaire local avant de générer l'horodatage, et de nouveau dans le fuseau horaire local affiché, il n'y a aucune ambiguïté.
lkraider
46

Il n'y a pas de bon format ; La spécification JSON ne spécifie pas de format pour l'échange de dates, c'est pourquoi il y a tellement de façons différentes de le faire.

Le meilleur format est sans doute une date représentée au format ISO 8601 ( voir Wikipedia ); il s'agit d'un format bien connu et largement utilisé qui peut être géré dans de nombreuses langues différentes, ce qui le rend très bien adapté à l'interopérabilité. Si vous contrôlez le json généré, par exemple, vous fournissez des données à d'autres systèmes au format json, choisir 8601 comme format d'échange de date est un bon choix.

Si vous n'avez pas de contrôle sur le json généré, par exemple, vous êtes le consommateur de json de plusieurs systèmes existants différents, la meilleure façon de gérer cela est d'avoir une fonction utilitaire d'analyse de date pour gérer les différents formats attendus.

Russ Cam
la source
2
@mlissner mais c'est une opinion sur laquelle est la meilleure. ISO-8601 est une norme, mais ce n'est pas la norme pour JSON (même si je serais enclin à l'utiliser); par exemple, Microsoft a décidé de ne pas l'utiliser ( msdn.microsoft.com/en-us/library/… ). La meilleure pratique consiste à s'en tenir à une convention (raisonnable), quelle qu'elle soit. Comme je l'ai indiqué dans la réponse, la meilleure façon de gérer cela est de définir une fonction utilitaire d'analyse de date qui peut gérer les formats attendus. Si vous intégrez avec des systèmes qui utilisent différents formats, la fonction doit gérer chaque cas.
Russ Cam
1
@RussCam, nous pouvons faire des allers-retours, mais si quelqu'un demande la meilleure façon de coder les dates en JSON, il demande comment formater les dates quand il crée JSON (et la réponse est généralement ISO-8601). Vous répondez à la question opposée: comment consommer les dates JSON une fois qu'elles sont déjà faites (bien que vos conseils soient judicieux).
mlissner
1
La spécification de schéma JSON indique en fait que les dates vérifiées par un schéma doivent être au format 8601.
gnasher729
3
@ gnasher729 avez-vous un lien?
Russ Cam
@vallismortis - C'est un projet de spécification pour définir un schéma pour une structure json donnée échangée entre les parties, pas le format des dates dans la spécification json. Je vais réviser ma réponse en fonction des commentaires, il ne semble pas que j'aie été assez clair
Russ Cam
27

De RFC 7493 (le format de message I-JSON) :

I-JSON signifie Internet JSON ou Interoperable JSON, selon qui vous demandez.

Les protocoles contiennent souvent des éléments de données conçus pour contenir des horodatages ou des durées. Il est RECOMMANDÉ que tous ces éléments de données soient exprimés sous forme de valeurs de chaîne au format ISO 8601, comme spécifié dans la RFC 3339 , avec les restrictions supplémentaires que les majuscules plutôt que les lettres minuscules soient utilisées, que le fuseau horaire soit inclus non par défaut et que les secondes de fin facultatives être inclus même lorsque leur valeur est "00". Il est également RECOMMANDÉ que tous les éléments de données contenant des durées de temps soient conformes à la "durée" de production dans l'annexe A de la RFC 3339, avec les mêmes restrictions supplémentaires.

Bryan Larsen
la source
2
C'est également le format produit par Date().toISOString()et Date().toJSON(), avec la limitation qui Datene suit pas une valeur de fuseau horaire, et émet donc toujours les horodatages dans le fuseau Zhoraire UTC ( ). La valeur peut être analysée à l'aide de new Date("...")et Date.parseDate.
Søren Løvborg
15

Juste pour référence, j'ai vu ce format utilisé:

Date.UTC(2017,2,22)

Il fonctionne avec JSONP qui est pris en charge par la $.getJSON()fonction. Je ne suis pas sûr que j'irais jusqu'à recommander cette approche ... en la jetant simplement comme une possibilité parce que les gens le font de cette façon.

FWIW: N'utilisez jamais de secondes depuis l'époque dans un protocole de communication, ni de millisecondes depuis l'époque, car celles-ci sont lourdes de danger grâce à l'implémentation aléatoire des secondes intercalaires (vous ne savez pas si l'expéditeur et le destinataire implémentent correctement les secondes intercalaires UTC).

Une sorte de haine pour les animaux de compagnie, mais beaucoup de gens croient que l'UTC n'est que le nouveau nom de GMT - faux! Si votre système n'implémente pas de secondes intercalaires, vous utilisez GMT (souvent appelé UTC bien qu'il soit incorrect). Si vous implémentez complètement les secondes intercalaires, vous utilisez vraiment UTC. Les secondes intercalaires futures ne peuvent être connues; ils sont publiés par l'IERS selon les besoins et nécessitent des mises à jour constantes. Si vous exécutez un système qui tente d'implémenter des secondes intercalaires mais contient une table de référence obsolète (plus courante que vous ne le pensez), vous n'avez ni GMT, ni UTC, vous avez un système bancal prétendant être UTC.

Ces compteurs de date ne sont compatibles que lorsqu'ils sont exprimés dans un format décomposé (y, m, d, etc.). Ils ne sont JAMAIS compatibles dans un format d'époque. Garde cela à l'esprit.

Tél
la source
4
Je n'utiliserais pas ce format, mais le reste des informations que vous avez fournies sont très utiles, merci!
Robert Mikes
9

En cas de doute, accédez simplement à la console Web javascript d'un navigateur moderne en appuyant sur F12 (Ctrl + K dans Firefox) et écrivez ce qui suit:

new Date().toISOString()

Sortira:

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

Ta-da !!

Shayan Ahmad
la source
3

Je crois que le meilleur format pour l'interopérabilité universelle n'est pas la chaîne ISO-8601, mais plutôt le format utilisé par EJSON:

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

Comme décrit ici: https://docs.meteor.com/api/ejson.html

Avantages

  1. Analyser les performances: si vous stockez des dates sous forme de chaînes ISO-8601, c'est très bien si vous attendez une valeur de date sous ce champ particulier, mais si vous avez un système qui doit déterminer les types de valeurs sans contexte, vous analysez chaque chaîne pour un format de date.
  2. Pas besoin de validation de la date: vous n'avez pas à vous soucier de la validation et de la vérification de la date. Même si une chaîne correspond au format ISO-8601, il peut ne pas s'agir d'une date réelle; cela ne peut jamais arriver avec une date EJSON.
  3. Déclaration de type sans ambiguïté: en ce qui concerne les systèmes de données génériques, si vous souhaitez stocker une chaîne ISO en tant que chaîne dans un cas, et une date système réelle dans un autre, les systèmes génériques adoptant le format de chaîne ISO-8601 ne le permettront pas, mécaniquement (sans astuces d'échappement ou solutions horribles similaires).

Conclusion

Je comprends qu'un format lisible par l'homme (chaîne ISO-8601) est utile et plus pratique pour 80% des cas d'utilisation, et en effet personne ne devrait jamais être dit de ne pas stocker leurs dates en tant que chaînes ISO-8601 si c'est ce que leurs applications comprendre, mais pour un format de transport universellement accepté qui devrait garantir certaines valeurs à coup sûr des dates, comment pouvons-nous tenir compte de l'ambiguïté et avoir besoin de tant de validation?

Ciabaros
la source
Voir cette réponse plus tôt dans le fil pour savoir pourquoi millisecondes depuis l'époque a des mises en garde telles que le calcul incorrect des secondes intercalaires,
Sudhanshu Mishra
@SudhanshuMishra Les mises en garde auxquelles vous faites référence sont des pièges généraux pour les préoccupations extrêmement académiques des horodatages Unix, principalement liés à la génération d'horodatage. C'est encore moins un problème avec la résolution en millisecondes. Comme cela a été souligné dans un autre commentaire, la plupart des dates d'ordinateur sont représentées en interne sous forme d'horodatages Unix, même si elles sont exposées et formatées autrement. Néanmoins, il n'y a rien de mal à la représentation en millisecondes d'une date + heure donnée, en particulier par rapport à d'autres approches, qui peuvent facilement être affectées par les mêmes avertissements de nano-impact sous le capot.
Ciabaros
Juste pour ajouter des inquiétudes concernant les dates "hors limites" pour les horodatages Unix: ce sont des problèmes de stockage système, qui doivent être traités dans un contexte beaucoup plus large que le format de transport. Par exemple, ce format n'a pas besoin d'être limité aux entiers qui tiennent sur 32 bits, ni à des nombres strictement positifs, mais personne ne va résoudre le "problème de l'année 2038" en supprimant les horodatages au niveau du système / de l'architecture ; ils doivent simplement être étendus (par exemple à 64 bits ou au-delà), et cela n'affecte pas ce format de transport proposé.
Ciabaros
3

JSON lui-même n'a pas de format de date, peu importe comment quelqu'un stocke les dates. Cependant, puisque cette question est balisée avec javascript, je suppose que vous voulez savoir comment stocker les dates javascript dans JSON. Vous pouvez simplement passer une date à la JSON.stringifyméthode, et elle utilisera Date.prototype.toJSONpar défaut, qui à son tour utilise Date.prototype.toISOString( MDN on 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

J'ai également trouvé utile d'utiliser le reviverparamètre de JSON.parse( MDN sur JSON.parse ) pour convertir automatiquement les chaînes ISO en dates javascript chaque fois que je lis les chaînes 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
la source
2

La manière préférée utilise 2018-04-23T18:25:43.511Z...

L'image ci-dessous montre pourquoi c'est la manière préférée:

Date JSON

Donc, comme vous le voyez, Date a une méthode native toJSON, qui returndans ce format et peut être facilement convertie à Datenouveau ...

Alireza
la source
2
Correct! La syntaxe d'échange de données JSON ne spécifie pas la norme: ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf mais dans la pratique, les formats compatibles ISO 8601 sont plus souhaitables sur toutes les plates-formes, y compris le moteur d'exécution JavaScript.
Kamyar Nazeri
1

Dans Sharepoint 2013, obtenir des données en JSON, il n'y a pas de format pour convertir la date en format date uniquement, car cette date doit être au format ISO

yourDate.substring(0,10)

Cela peut vous être utile

raghava arr
la source
0

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

La date est représentée dans un format standard et triable qui représente une heure UTC (indiquée par le Z). ISO 8601 prend également en charge les fuseaux horaires en remplaçant la valeur Z par + ou - pour le décalage de fuseau horaire:

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

Il existe d'autres variantes du codage du fuseau horaire dans la spécification ISO 8601, mais le format –10: 00 est le seul format TZ pris en charge par les analyseurs JSON actuels. En général, il est préférable d'utiliser le format UTC (Z), sauf si vous avez un besoin spécifique de déterminer le fuseau horaire dans lequel la date a été produite (possible uniquement dans la génération côté serveur).

NB: var date = new Date (); console.log (date); // mer.01 janv.2014 13:28:56 GMT- 1000 (heure standard hawaïenne)

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

pour vous dire que c'est la manière préférée même si JavaScript n'a pas de format standard

// 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
la source
0

Si vous utilisez Kotlin, cela résoudra votre problème. (Format MS Json)

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

c'est du travail pour moi avec 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"
            }
}
Kemal Karadag
la source
-6

Il n'y a qu'une seule bonne réponse à cela et la plupart des systèmes se trompent. Nombre de millisecondes depuis l'époque, alias un entier 64 bits. Le fuseau horaire est une préoccupation d'interface utilisateur et n'a aucune activité dans la couche application ou la couche db. Pourquoi votre base de données se soucie-t-elle du fuseau horaire de quelque chose, quand vous savez qu'il va le stocker en tant qu'entier 64 bits, puis faites les calculs de transformation.

Supprimez les bits superflus et traitez simplement les dates comme des nombres jusqu'à l'interface utilisateur. Vous pouvez utiliser des opérateurs arithmétiques simples pour effectuer des requêtes et de la logique.

Chad Wilson
la source
Les commentaires ont été déplacés vers le chat .
Jon Clements
5
Vous avez maintenant 2 problèmes: quelle époque choisir et quelles millisecondes compter? Le choix le plus courant est probablement le temps Unix (1970-01-01T00: 00: 00 UTC et SI millisecondes, sauf pour ceux qui se situent dans une seconde intercalaire), mais bien sûr, cela rend les temps futurs indéfinis.
aij
2
Alors, comment représentez-vous les microsecondes? RFC3339 fonctionne très bien avec n'importe quelle précision, vous aurez un lecteur qui analyse le fuseau horaire et vous donne le bon horodatage, et ce sont des informations supplémentaires. Les applications d'agenda se soucient généralement des fuseaux horaires.
gnasher729
11
Le fuseau horaire n'est pas une préoccupation d'interface utilisateur, sauf si cela ne vous dérange pas de manquer votre prochain vol. Les vols sont affichés à l'heure locale et suivent des règles spécifiques pour les changements d'heure d'été. Perdre la compensation signifie perdre des informations commerciales importantes
Panagiotis Kanavos
1
Certains contre-arguments supplémentaires incluent la capacité à représenter des périodes antérieures à 1970 (en supposant cette époque particulière) et la tendance des JSON à être quelque peu lisibles par l'homme.
Timo
-8

Le code suivant a fonctionné pour moi. Ce code imprimera la date au format JJ-MM-AAAA .

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

sinon, vous pouvez également utiliser:

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

Je pense que cela dépend vraiment du cas d'utilisation. Dans de nombreux cas, il pourrait être plus avantageux d'utiliser un modèle d'objet approprié (au lieu de rendre la date à une chaîne), comme ceci:

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

Certes, c'est plus verbeux que RFC 3339 mais:

  • c'est aussi lisible par l'homme
  • il implémente un modèle d'objet approprié (comme dans la POO, dans la mesure où JSON le permet)
  • il prend en charge les fuseaux horaires (pas seulement le décalage UTC à la date et à l'heure données)
  • il peut prendre en charge des unités plus petites comme les millisecondes, les nanosecondes, ... ou simplement des secondes fractionnaires
  • il ne nécessite pas d'étape d'analyse distincte (pour analyser la chaîne date-heure), l'analyseur JSON fera tout pour vous
  • création facile avec n'importe quel cadre date-heure ou implémentation dans n'importe quelle langue
  • peut facilement être étendu pour prendre en charge d'autres échelles de calendrier (hébreu, chinois, islamique ...) et des époques (AD, BC, ...)
  • c'est l'année 10000 en sécurité ;-) (RFC 3339 ne l'est pas)
  • prend en charge les dates et les heures flottantes toute la journée (Javascript Date.toJSON()n'est pas le cas)

Je ne pense pas que le tri correct (comme noté par funroll pour RFC 3339) soit une fonctionnalité vraiment nécessaire lors de la sérialisation d'une date en JSON. Cela n'est également vrai que pour les dates-heures ayant le même décalage de fuseau horaire.

Martre
la source
7
Je doute que quelqu'un utilise json en l'an 10000, ou même qu'à ce moment-là, l'année 10000 soit toujours l'année 10000. Mais si ces deux choses sont toujours vraies d'ici là, le format peut simplement être étendu pour contenir un chiffre à 3 chiffres composante du siècle. Je dirais donc que les gens peuvent s'en tenir en toute sécurité avec la RFC 3339, au moins jusqu'à l'année 9900
souvenir d'un rêve
8
@downvoters: Selon Pourquoi le vote est-il important? vous devriez voter contre si a post contains wrong information, is poorly researched, or fails to communicate information. Veuillez expliquer pour laquelle l'une des raisons pour lesquelles vous avez rejeté cette réponse.
Marten
5
@Marten Deux choses. 1. On ne vous doit jamais d'explication pour les votes négatifs, même si je comprends que cela peut être utile. 2. Je n'ai pas déçu votre réponse, mais je suppose que les gens n'aiment pas votre réponse parce qu'ils pensent que c'est la mauvaise façon de procéder. Cela le qualifierait de "mauvaise information" car la question cherche la meilleure façon de faire quelque chose
Kevin Wells
7
Je ne vous ai pas déçu, mais je peux certainement comprendre comment "inventer encore un autre format mal spécifié" (qui est essentiellement ce que vous dites) serait considéré comme erroné ou mal étudié.
aij
2
@Phil, l'UTC n'est pas vraiment un fuseau horaire (il n'y a aucun endroit sur terre qui utilise "UTC" comme fuseau horaire officiel), c'est un standard horaire . Les décalages de fuseau horaire sont également assez imprévisibles. Il n'y a aucun moyen de dire si en 2025 "12:00 heure de Moscou" est toujours "9:00 UTC" comme c'est le cas aujourd'hui, il a été modifié à quelques reprises au cours des 30 dernières années . Si vous souhaitez exprimer une heure locale future, vous avez besoin de véritables fuseaux horaires.
Marten