Premier cas:
new Date(Date.parse("Jul 8, 2005"));
Production:
Ven.08 juil.2005 00:00:00 GMT-0700 (PST)
Deuxième cas:
new Date(Date.parse("2005-07-08"));
Production:
Jeu 07 juil 2005 17:00:00 GMT-0700 (PST)
Pourquoi la deuxième analyse est-elle incorrecte?
javascript
date
user121196
la source
la source
NaN
dans Firefox, j'ai découvert que la plupart des autres navigateurs (et Node.js) analyseront une date sans jour, comme "avril 2014" comme 1er avril 2014, mais Firefox renvoie NaN. Vous devez passer une date appropriée.Réponses:
Jusqu'à la sortie de la 5e édition, la
Date.parse
méthode était complètement dépendante de l'implémentation (new Date(string)
équivaut à ceDate.parse(string)
que ce dernier renvoie un nombre plutôt qu'un aDate
). Dans la 5e édition, l'exigence a été ajoutée pour prendre en charge une norme ISO-8601 simplifiée (et légèrement incorrecte) (voir également Que sont les chaînes de date-heure valides en JavaScript? ). Mais à part cela, il n'y avait aucune exigence pour ce queDate.parse
/new Date(string)
devrait accepter à part le fait qu'ils devaient accepter n'importe quelleDate#toString
sortie (sans dire ce que c'était).Depuis ECMAScript 2017 (édition 8), les implémentations devaient analyser leur sortie pour
Date#toString
etDate#toUTCString
, mais le format de ces chaînes n'était pas spécifié.Depuis ECMAScript 2019 (édition 9), le format de
Date#toString
etDate#toUTCString
, a été spécifié comme (respectivement):par exemple mar. 10 juil. 2018 18:39:58 GMT + 0530 (IST)
par ex. Mar.10 juil.2018 13:09:58 GMT
fournissant 2 autres formats qui
Date.parse
devraient être analysés de manière fiable dans les nouvelles implémentations (notant que la prise en charge n'est pas omniprésente et que les implémentations non conformes resteront utilisées pendant un certain temps).Je recommanderais que les chaînes de date soient analysées manuellement et que le constructeur Date soit utilisé avec les arguments année, mois et jour pour éviter toute ambiguïté:
la source
Date.parse
il ne se comportait pas avec les formats de date britanniques pour une raison quelconque, je n'ai pas pu travaillerreturn new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]);
Fonctionne parfaitement, merci!Au cours de ma récente expérience dans l'écriture d'un interprète JS, j'ai beaucoup lutté avec le fonctionnement interne des dates ECMA / JS. Donc, je pense que je vais jeter mes 2 cents ici. Espérons que le partage de ces informations aidera les autres à répondre à toutes les questions sur les différences entre les navigateurs dans la façon dont ils traitent les dates.
Le côté entrée
Toutes les implémentations stockent leurs valeurs de date en interne sous forme de nombres 64 bits qui représentent le nombre de millisecondes (ms) depuis le 01/01/1970 UTC (GMT est la même chose que UTC). Cette date est l'époque ECMAScript qui est également utilisée par d'autres langages tels que Java et les systèmes POSIX comme UNIX. Les dates survenant après l'époque sont des nombres positifs et les dates antérieures sont négatives.
Le code suivant est interprété comme la même date dans tous les navigateurs actuels, mais avec le décalage de fuseau horaire local:
Dans mon fuseau horaire (EST, qui est -05: 00), le résultat est 18000000 car c'est le nombre de ms en 5 heures (c'est seulement 4 heures pendant les mois d'heure d'été). La valeur sera différente selon les fuseaux horaires. Ce comportement est spécifié dans ECMA-262 donc tous les navigateurs le font de la même manière.
Bien qu'il existe une certaine variation dans les formats de chaîne d'entrée que les principaux navigateurs analyseront comme des dates, ils les interprètent essentiellement de la même manière en ce qui concerne les fuseaux horaires et l'heure d'été, même si l'analyse est largement dépendante de l'implémentation.
Cependant, le format ISO 8601 est différent. C'est l'un des deux seuls formats décrits dans ECMAScript 2015 (ed 6) spécifiquement qui doivent être analysés de la même manière par toutes les implémentations (l'autre est le format spécifié pour Date.prototype.toString ).
Mais, même pour les chaînes au format ISO 8601, certaines implémentations se trompent. Voici une sortie de comparaison de Chrome et Firefox lorsque cette réponse a été initialement écrite pour 1/1/1970 (l'époque) sur ma machine en utilisant des chaînes de format ISO 8601 qui devraient être analysées exactement à la même valeur dans toutes les implémentations:
Cette différence a été corrigée à partir de 2020, mais d'autres bizarreries existent entre les navigateurs lors de l'analyse des chaînes de format ISO 8601.
Mais ça empire. Une particularité d'ECMA-262 est que le format de date uniquement ISO 8601 (AAAA-MM-JJ) doit être analysé en UTC, tandis que ISO 8601 exige qu'il soit analysé en tant que local. Voici la sortie de FF avec les formats de date ISO longs et courts sans spécificateur de fuseau horaire.
Ainsi, le premier est analysé comme local car il s'agit de la date et de l'heure ISO 8601 sans fuseau horaire, et le second est analysé en UTC car il s'agit uniquement de la date ISO 8601.
Ainsi, pour répondre directement à la question d'origine,
"YYYY-MM-DD"
ECMA-262 doit être interprété comme UTC, tandis que l'autre est interprété comme local. Voilà pourquoi:Cela ne produit pas de résultats équivalents:
Cela fait:
La ligne de fond est la suivante pour analyser les chaînes de date. La SEULE chaîne ISO 8601 que vous pouvez analyser en toute sécurité entre les navigateurs est la forme longue avec un décalage (± HH: mm ou "Z"). Si vous le faites, vous pouvez aller et venir en toute sécurité entre l'heure locale et l'heure UTC.
Cela fonctionne sur tous les navigateurs (après IE9):
La plupart des navigateurs actuels traitent les autres formats d'entrée de la même manière, y compris le '1/1/1970' (M / D / YYYY) fréquemment utilisé et le '' 1/1/1970 00:00:00 AM '' (M / D / YYYY hh : mm: ss ap) formats. Tous les formats suivants (sauf le dernier) sont traités comme des entrées d'heure locale dans tous les navigateurs. La sortie de ce code est la même dans tous les navigateurs de mon fuseau horaire. Le dernier est traité comme -05: 00 quel que soit le fuseau horaire de l'hôte car le décalage est défini dans l'horodatage:
Cependant, étant donné que l'analyse même des formats spécifiés dans ECMA-262 n'est pas cohérente, il est recommandé de ne jamais compter sur l'analyseur intégré et de toujours analyser manuellement les chaînes, par exemple en utilisant une bibliothèque et en fournissant le format à l'analyseur.
Par exemple, dans moment.js, vous pourriez écrire:
Côté sortie
Côté sortie, tous les navigateurs traduisent les fuseaux horaires de la même manière mais ils gèrent les formats de chaîne différemment. Voici les
toString
fonctions et ce qu'elles produisent. Notez letoUTCString
et latoISOString
sortie des fonctions 5h00 sur ma machine. En outre, le nom du fuseau horaire peut être une abréviation et peut être différent dans différentes implémentations.Conversion de l'heure UTC en heure locale avant l'impression
Imprime l'heure UTC stockée directement
Normalement, je n'utilise pas le format ISO pour l'entrée de chaîne. La seule fois où l'utilisation de ce format est bénéfique pour moi, c'est lorsque les dates doivent être triées sous forme de chaînes. Le format ISO est triable tel quel tandis que les autres ne le sont pas. Si vous devez avoir une compatibilité entre navigateurs, spécifiez le fuseau horaire ou utilisez un format de chaîne compatible.
Le code
new Date('12/4/2013').toString()
passe par la pseudo-transformation interne suivante:J'espère que cette réponse a été utile.
la source
Il y a une méthode à la folie. En règle générale, si un navigateur peut interpréter une date comme ISO-8601, il le fera. "2005-07-08" tombe dans ce camp, et donc il est analysé comme UTC. "8 juillet 2005" ne peut pas, et il est donc analysé dans l'heure locale.
Voir JavaScript et les dates, quel gâchis! pour plus.
la source
Une autre solution consiste à créer un tableau associatif au format de date, puis à reformater les données.
Cette méthode est utile pour les dates formatées de manière inhabituelle.
Un exemple:
la source
Utilisez moment.js pour analyser les dates:
Le 3ème argument détermine une analyse stricte (disponible à partir de 2.3.0). Sans cela, moment.js peut également donner des résultats incorrects.
la source
Selon http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html le format "aaaa / mm / jj" résout les problèmes habituels. Il dit: "Respectez" AAAA / MM / JJ "pour vos chaînes de date chaque fois que possible. Il est universellement pris en charge et sans ambiguïté. Avec ce format, toutes les heures sont locales." J'ai mis des tests: http://jsfiddle.net/jlanus/ND2Qg/432/ Ce format: + évite l'ambiguïté de l'ordre du jour et du mois en utilisant la commande ymd et une année à 4 chiffres + évite le problème UTC vs local non se conformer au format ISO en utilisant slashes + danvk, le gars des dygraphes , dit que ce format est bon dans tous les navigateurs.
la source
Bien que CMS ait raison de dire que la transmission de chaînes dans la méthode d'analyse n'est généralement pas sûre, la nouvelle spécification ECMA-262 5e édition (aka ES5) de la section 15.9.4.2 suggère qu'en
Date.parse()
réalité, elle devrait gérer les dates au format ISO. L'ancienne spécification ne faisait pas une telle réclamation. Bien sûr, les anciens navigateurs et certains navigateurs actuels ne fournissent toujours pas cette fonctionnalité ES5.Votre deuxième exemple n'est pas faux. Il s'agit de la date spécifiée en UTC, comme le laisse entendre
Date.prototype.toISOString()
, mais elle est représentée dans votre fuseau horaire local.la source
Cette bibliothèque d'analyse de date légère devrait résoudre tous les problèmes similaires. J'aime la bibliothèque car elle est assez facile à étendre. Il est également possible de l'i18n (pas très simple, mais pas si difficile).
Exemple d'analyse:
Et le formatage revient à la chaîne (vous remarquerez que les deux cas donnent exactement le même résultat):
la source
Voici un extrait court et flexible pour convertir une chaîne datetime d'une manière sûre pour tous les navigateurs, comme nicel l'a détaillé par @ drankin2112.
Votre navigateur doit fournir le même résultat d'horodatage
Date.parse
qu'avec:la source
Les deux sont corrects, mais ils sont interprétés comme des dates avec deux fuseaux horaires différents. Vous avez donc comparé des pommes et des oranges:
J'ai enlevé le
Date.parse()
appel car il est utilisé automatiquement sur un argument de chaîne. J'ai également comparé les dates en utilisant le format ISO8601 afin que vous puissiez comparer visuellement les dates entre vos dates locales et les dates UTC. Les heures sont espacées de 7 heures, ce qui est la différence de fuseau horaire et pourquoi vos tests ont montré deux dates différentes.L'autre façon de créer ces mêmes dates locales / UTC serait:
Mais je recommande toujours vivement Moment.js qui est aussi simple que puissant :
la source
La réponse acceptée de CMS est correcte, je viens d'ajouter quelques fonctionnalités:
la source