372 votes

javascript Date.parse

Cas un:

 new Date(Date.parse("Jul 8, 2005"));
 

Sortie:

Ven Jul 08 2005 00:00:00 GMT-0700 (PST)

Deuxième cas:

 new Date(Date.parse("2005-07-08"));
 

Sortie:

Jeu. 07 juillet 2005 17:00:00 GMT-0700 (PST)


Pourquoi la deuxième analyse est-elle incorrecte?

466voto

CMS Points 315406

Jusqu'à la 5ème édition spec est sorti, l' Date.parse méthode a été complètement dépendant de l'implémentation (new Date(string) est équivalent à Date.parse(string) à l'exception de celle-ci retourne un nombre plutôt qu'un Date). Lors de la 5ème édition spec, l'exigence a été ajoutée à l'appui d'une simplifiée (et légèrement incorrect) ISO-8601, mais autre que cela, il n'y a aucune exigence pour ce qu' Date.parse / new Date(string) doit accepter d'autres qu'ils avaient à accepter tout ce qui Date#toString de sortie (sans dire ce que c'était).

Je vous recommande d'analyser votre date de chaîne manuellement, et d'utiliser le constructeur de Date avec l'année, le mois et le jour arguments pour éviter toute ambiguïté:

// parse a date in yyyy-mm-dd format
function parseDate(input) {
  var parts = input.split('-');
  // new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
  return new Date(parts[0], parts[1]-1, parts[2]); // Note: months are 0-based
}

209voto

drankin2112 Points 2357

Au cours de l'expérience récente de l'écriture d'un JS interprète j'ai beaucoup lutté avec le fonctionnement interne de l'ECMA/JS dates. Donc, je me dis que je vais le jeter dans mes 2 cents ici. Espérons que le partage de ce genre de choses va aider les autres avec des questions sur les différences entre les navigateurs dans la façon dont ils gèrent les dates.

Le Côté De L'Entrée

Toutes les implémentations de stocker leurs valeurs de date en interne comme en 64 bits des nombres qui représentent le nombre de millisecondes écoulées depuis le 1/1/1970 UTC (GMT est la même chose que l'UTC). Dates survenant après l' 1/1/1970 00:00:00 sont des nombres positifs et les dates antérieures sont négatifs.

Par conséquent, le code suivant produit exactement le même résultat sur tous les navigateurs.

Date.parse('1/1/1970');

Dans mon fuseau horaire (heure de l'est), le résultat est 18000000 parce que de nombreux états membres sont en 5 heures, c'est seulement 4 heures au cours de l'heure d'été mois). La valeur sera différente dans différents fuseaux horaires. Tous les principaux navigateurs faire la même façon.

Là est le hic. Bien qu'il existe une certaine variation dans la chaîne d'entrée les formats les principaux navigateurs va analyser comme des dates, ils sont essentiellement les interpréter de la même aussi loin que les fuseaux horaires et l'heure d'été sont concernés. Le seul à tenir est le format ISO 8601. C'est le seul format décrit dans l'ECMA-262 v. 5 spec spécifiquement. Pour tous les autres formats de chaîne, l'interprétation est dépendant de l'implémentation. Ironiquement, c'est le format où les navigateurs peuvent différer. Voici une comparaison de sortie de Chrome vs Firefox pour 1/1/1970 sur ma machine en utilisant la norme ISO 8601 format de chaîne de caractères.

Date.parse('1970-01-01T00:00:00Z');       // Chrome: 0         FF: 0
Date.parse('1970-01-01T00:00:00-0500');   // Chrome: 18000000  FF: 18000000
Date.parse('1970-01-01T00:00:00');        // Chrome: 0         FF: 18000000
  • Le "Z" spécificateur indique que l'entrée est déjà l'heure UTC et ne nécessite pas de décalage avant le stockage.
  • Le "-0500" spécificateur indique que l'entrée est à GMT-05:00 donc, à la fois les navigateurs n'interprètent comme étant dans mon fuseau horaire local. Cela signifie que l' la valeur est convertie à l'UTC, avant d'être stockés. Dans mon cas, cela signifie l'ajout de 18000000ms à la date de valeur interne, ce qui exige un -18000000ms (-05:00) maj pour me remettre dans l'heure locale.
  • Quand il n'y a pas de spécificateur cependant, FF traite de l'entrée en heure locale, tandis que Chrome il les traite comme de l'heure UTC. Pour moi, cela crée à 5 heures de différence dans la valeur stockée, ce qui est problématique. Dans mon application j'ai fini par le parti de la FF ici parce que j'aime la sortie de l' toString pour correspondre à mon entrée valeur, à moins que je spécifier un autre fuseau horaire, je ne fais jamais. L' absence d'un spécificateur devrait présumer l'heure locale de l'entrée.

Mais c'est ce qui est pire, FF traite de la forme courte du format ISO 8601 ("YYYY-MM-DD") différemment de ce qu'il traite de la forme longue ("YYYY-MM-DDTHH:mm:ss:sssZ") pour aucune raison logique que ce soit. Voici la sortie de FF avec le long et à court ISO formats de date avec un pas de temps horaire spécificateur.

Date.parse('1970-01-01T00:00:00');       // 18000000
Date.parse('1970-01-01');                // 0

Donc, pour répondre à l'original asker la question directement, "YYYY-MM-DD" est la forme courte de la norme ISO 8601 "YYYY-MM-DDTHH:mm:ss:sssZ". Donc, il est interprété comme de l'heure UTC, tandis que l'autre est interprétée comme un local. C'est pourquoi,

Ce n'est pas jive:

console.log(new Date(Date.parse("Jul 8, 2005")).toString());
console.log(new Date(Date.parse("2005-07-08")).toString());

Ce n':

console.log(new Date(Date.parse("Jul 8, 2005")).toString());
console.log(new Date(Date.parse("2005-07-08T00:00:00")).toString());

La ligne du bas est-ce pour l'analyse des chaînes date. La SEULE norme ISO 8601 chaîne de caractères que vous pouvez analyser tous les navigateurs est la forme longue. Et, TOUJOURS utiliser le "Z" spécificateur. Si vous faites cela, vous pouvez faire l'aller-retour entre le local et l'heure UTC.

Cela fonctionne sur tous les navigateurs (après IE9):

console.log(new Date(Date.parse("2005-07-08T00:00:00Z")).toString());

Heureusement, la plupart des navigateurs actuels ne traiter les autres formats d'entrée également, y compris les plus fréquemment utilisés "1/1/1970" et "1/1/1970 00:00:00' formats. Tous les formats suivants (et les autres) sont traités comme des locaux le temps d'entrée dans tous les navigateurs et converti à l'UTC, avant le stockage. Ainsi, les rendant compatible avec tous les navigateurs. La sortie de ce code est le même dans tous les navigateurs dans mon fuseau horaire.

console.log(Date.parse("1/1/1970"));
console.log(Date.parse("1/1/1970 12:00:00 AM"));
console.log(Date.parse("Thu Jan 01 1970"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00 GMT-0500"));

Le Côté De Sortie

Du côté de la production, tous les navigateurs traduire les fuseaux horaires de la même façon mais ils gèrent les formats de chaîne différemment. Voici l' toString fonctions et qu'ils sortie. Avis de l' toUTCString et toISOString fonctions de sortie 5:00 du matin, sur ma machine.

Convertit de l'heure UTC en heure Locale avant l'impression

 - toString
 - toDateString
 - toTimeString
 - toLocaleString
 - toLocaleDateString
 - toLocaleTimeString

Imprime la stockées heure UTC directement

 - toUTCString
 - toISOString 

Dans Chrome
toString            Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString        Thu Jan 01 1970
toTimeString        00:00:00 GMT-05:00 (Eastern Standard Time)
toLocaleString      1/1/1970 12:00:00 AM
toLocaleDateString  1/1/1970
toLocaleTimeString  00:00:00 AM

toUTCString         Thu, 01 Jan 1970 05:00:00 GMT
toISOString         1970-01-01T05:00:00.000Z

Dans Firefox
toString            Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString        Thu Jan 01 1970
toTimeString        00:00:00 GMT-0500 (Eastern Standard Time)
toLocaleString      Thursday, January 01, 1970 12:00:00 AM
toLocaleDateString  Thursday, January 01, 1970
toLocaleTimeString  12:00:00 AM

toUTCString         Thu, 01 Jan 1970 05:00:00 GMT
toISOString         1970-01-01T05:00:00.000Z

J'ai l'habitude de ne pas utiliser le format ISO pour la chaîne d'entrée. La seule fois que l'utilisation de ce format est bénéfique pour moi, c'est quand les dates doivent être triés comme des chaînes de caractères. Le format ISO est sortable comme-est, tandis que les autres ne le sont pas. Si vous disposez de la compatibilité inter-navigateur, soit spécifier le fuseau horaire ou utiliser un format de chaîne de caractères.

Le code new Date('12/4/2013').toString() passe par la suite de pseudo-transformation:

  "12/4/2013" -> toUCT -> [storage] -> toLocal -> print "12/4/2013"

J'espère que cette réponse vous a été utile.

72voto

danvk Points 2129

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é à l'heure locale.

Voir JavaScript et les dates, quel gâchis! pour plus.

7voto

guido rizzi Points 31

Une autre solution consiste à créer un tableau associatif avec un format de date, puis à reformater les données.

Cette méthode est utile pour la date formatée de manière non-aléatoire.

Un exemple:

     mydate='01.02.12 10:20:43':
    myformat='dd/mm/yy HH:MM:ss';


    dtsplit=mydate.split(/[\/ .:]/);
    dfsplit=myformat.split(/[\/ .:]/);

    // creates assoc array for date
    df = new Array();
    for(dc=0;dc<6;dc++) {
            df[dfsplit[dc]]=dtsplit[dc];
            }

    // uses assc array for standard mysql format
    dstring[r] = '20'+df['yy']+'-'+df['mm']+'-'+df['dd'];
    dstring[r] += ' '+df['HH']+':'+df['MM']+':'+df['ss'];
 

4voto

peller Points 3989

Alors que la CMS est correct que le passage des chaînes dans la méthode d'analyse est généralement dangereux, le nouveau ECMA-262 5e Édition (aka ES5) spécification dans la section 15.9.4.2 suggère qu' Date.parse() fait doit gérer ISO format des dates. L'ancien cahier des charges établi absence d'une telle revendication. Bien sûr, les anciens navigateurs et certains navigateurs ne proposent pas cette ES5 fonctionnalité.

Votre deuxième exemple n'est pas faux. C'est la date spécifiée dans l'UTC, comme l'implique Date.prototype.toISOString(), mais est représenté dans votre fuseau horaire local.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X