1852 votes

Detection d'une instance de date "invalide" en JavaScript

Je voudrais faire la différence entre les objets de date valides et non valides en JS, mais je n'ai pas réussi à comprendre comment:

var d = new Date("foo");
console.log(d.toString()); // affiche 'Date invalide'
console.log(typeof d); // affiche 'object'
console.log(d instanceof Date); // affiche 'true'

Des idées pour écrire une fonction isValidDate ?

  • Ash recommande d'utiliser Date.parse pour analyser les chaînes de date, ce qui donne une façon autorisée de vérifier si la chaîne de date est valide.
  • Si possible, j'aimerais que mon API accepte une instance de Date et qu'il soit possible de vérifier/affirmer si elle est valide ou non. La solution de Borgar le fait, mais je dois la tester sur différents navigateurs. Je me demande aussi s'il n'y a pas une façon plus élégante de faire.
  • Ash m'a fait réfléchir à ne pas faire accepter des instances de Date par mon API du tout, ce serait le plus facile à valider.
  • Borgar suggère de tester si c'est une instance de Date, puis de tester la valeur temporelle de la Date. Si la date est invalide, la valeur temporelle est NaN. J'ai vérifié avec ECMA-262 et ce comportement est dans la norme, ce que je recherche exactement.

1 votes

J'ai supprimé ma réponse originale car vérifier si NaN est une solution bien meilleure que de comparer à une chaîne "Invalid Date". Je vais devoir utiliser la solution isNaN moi-même.

0 votes

@orip, "avez-vous essayé de faire accepter un Date instance à mon API et de pouvoir vérifier/affirmer si elle est valide ou non" Avez-vous essayé : isNan(d.getTime())==true sur l'instance de date?

0 votes

@Ash, oui - c'est ce que Borgar a suggéré. J'ai recherché la définition des méthodes de Date selon l'ECMA-262, et getTime n'est pas garanti de renvoyer NaN. Les autres méthodes "get*", telles que getMonth, le sont.

1654voto

Borgar Points 12493

Voici comment je le ferais :

if (Object.prototype.toString.call(d) === "[object Date]") {
  // c'est une date
  if (isNaN(d)) { // d.getTime() ou d.valueOf() fonctionneront également
    // l'objet date n'est pas valide
  } else {
    // l'objet date est valide
  }
} else {
  // pas un objet date
}

Mise à jour [2018-05-31] : Si vous ne vous souciez pas des objets Date provenant d'autres contextes JS (fenêtres externes, cadres ou iframes), cette forme plus simple peut être préférée :

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}

Mise à jour [2021-02-01] : Veuillez noter qu'il y a une différence fondamentale entre les "dates invalides" (2013-13-32) et les "objets date invalides" (new Date('foo')). Cette réponse ne traite pas de la validation de l'entrée de date, seulement si une instance de Date est valide.

1 votes

@Borgar, Je ne comprends pas pourquoi instanceof ne fonctionne pas à travers les frames. Quel genre de "frame" mentionnez-vous ? De plus, à quel point la chaîne "[object Date]" est-elle stable ?

13 votes

@Borgar, je viens de trouver ma réponse : "Les problèmes surviennent lorsqu'il s'agit de script dans des environnements DOM multi-cadres. En gros, les objets Array créés dans un iframe ne partagent pas [[Prototype]] avec les tableaux créés dans un autre iframe. Leurs constructeurs sont des objets différents et donc les vérifications instanceof et constructor échouent."

79 votes

Vous n'avez même pas besoin de d.getTime juste isNan(d)

305voto

Ash Points 31541

Au lieu d'utiliser new Date(), vous devriez utiliser :

var timestamp = Date.parse('foo');

if (isNaN(timestamp) == false) {
  var d = new Date(timestamp);
}

Date.parse() renvoie un timestamp, un entier représentant le nombre de millisecondes écoulées depuis le 01/Jan/1970. Il renverra NaN s'il ne peut pas analyser la chaîne de date fournie.

166 votes

Je ne sais pas pourquoi cela a autant de votes positifs, Date.parse est dépendant de l'implémentation et certainement pas fiable pour analyser des chaînes de date générales. Il n'y a pas un seul format qui est analysé correctement dans les navigateurs populaires, encore moins tous ceux couramment utilisés (bien qu'éventuellement le format ISO8601 spécifié dans ES5 devrait être correct).

2 votes

Si vous utilisez le new Date('foo'), c'est essentiellement équivalent à la méthode Date.parse('foo'). Voir : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Donc ce que @RobG a dit, cela s'applique aussi à cela.

3 votes

Ce test échouerait sur Chrome. Par exemple, Date.parse('AAA-0001') dans Chrome me donne un numéro.

118voto

Christoph Points 64389

Vous pouvez vérifier la validité d'un objet Date d via

d instanceof Date && isFinite(d)

Pour éviter les problèmes de trames croisées, on pourrait remplacer la vérification instanceof par

Object.prototype.toString.call(d) === '[object Date]'

Un appel à getTime() comme dans la réponse de Borgar est inutile car isNaN() et isFinite() convertissent implicitement en nombre.

0 votes

Essayez ceci dans Chrome - Object.prototype.toString.call (new Date("2013-07-09T19:07:9Z")). Il renverra "[objet Date]". Selon vous, "2013-07-09T19:07:9Z" devrait donc être une date valide. Mais ce n'est pas le cas. Vous pouvez le vérifier, encore une fois dans Chrome, en faisant var dateStr = new Date("2013-07-09T19:07:9Z"); dateStr Il renverra une date invalide.

2 votes

@Tintin : c'est à cela que sert isFinite() - toString.call() n'est qu'un remplacement de la partie instanceof de la vérification

0 votes

Est-ce que la comparaison avec '[object Date]' fonctionnera avec les navigateurs non-anglophones? Je doute.

97voto

Ash Clarke Points 1625

Ma solution consiste simplement à vérifier si vous obtenez un objet date valide :

Implémentation

Date.prototype.isValid = function () {
    // Un objet date invalide renvoie NaN pour getTime () et NaN est le seul
    // objet qui n'est pas strictement égal à lui-même.
    return this.getTime() === this.getTime();
};  

Utilisation

var d = new Date("lol");

console.log(d.isValid()); // false

d = new Date("2012/09/11");

console.log(d.isValid()); // true

34 votes

isNaN est une façon plus explicite de tester NaN

1 votes

Et pourtant, vous trouvez toujours des gens écrivant leurs propres versions :) documentcloud.github.com/underscore/docs/…

4 votes

Puisque je respecte underscore.js, cela m'a poussé à faire des recherches. isNaN("a") === true, tandis que ("a" !== "a") === false. Cela vaut la peine d'y réfléchir. +1

38voto

Matt Campbell Points 446

Je voudrais mentionner que le widget jQuery UI DatePicker possède une très bonne méthode utilitaire de validation de date qui vérifie le format et la validité (par exemple, aucune date du type 01/33/2013 autorisée).

Même si vous ne voulez pas utiliser le widget datepicker sur votre page en tant qu'élément d'interface utilisateur, vous pouvez toujours ajouter sa bibliothèque .js à votre page puis appeler la méthode de validation, en lui passant la valeur que vous souhaitez valider. Pour faciliter encore plus les choses, elle prend une chaîne en entrée, et non un objet Date JavaScript.

Voir : http://api.jqueryui.com/datepicker/

Elle n'est pas répertoriée en tant que méthode, mais elle est là - en tant que fonction utilitaire. Recherchez sur la page "parsedate" et vous trouverez :

$.datepicker.parseDate( format, value, settings ) - Extraire une date à partir d'une valeur de chaîne avec un format spécifié.

Exemple d'utilisation :

var stringval = '01/03/2012';
var testdate;

try {
  testdate = $.datepicker.parseDate('mm/dd/yy', stringval);
             // Remarquez que 'yy' indique une valeur d'année à 4 chiffres
} catch (e)
{
 alert(stringval + ' n'est pas valide. Le format doit être MM/JJ/AAAA ' +
       'et la valeur de date doit être valide pour le calendrier.';
}

(Plus d'informations sur la spécification des formats de date se trouvent sur http://api.jqueryui.com/datepicker/#utility-parseDate)

Dans l'exemple ci-dessus, vous ne verriez pas le message d'alerte puisque '01/03/2012' est une date valide pour le calendrier dans le format spécifié. Cependant, si vous faisiez de 'stringval' égal à '13/04/2013', par exemple, vous obtiendriez le message d'alerte, car la valeur '13/04/2013' n'est pas valide pour le calendrier.

Si une valeur de chaîne passée en réussit à être analysée, la valeur de 'testdate' serait un objet Date JavaScript représentant la valeur de chaîne passée. Sinon, elle serait indéfinie.

3 votes

Vote en hausse pour être la première réponse à travailler avec des formats de date non anglais / local.

0 votes

Le commentaire précédent est incorrect et trompeur. L'objet Date en javascript gère la date dans n'importe quel paramètre régional et de nombreux formats ISO (et même certains non ISO selon l'implémentation)

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