web-dev-qa-db-fra.com

Détection d'une "date non valide" Instance de date en JavaScript

J'aimerais faire la différence entre les objets de date valides et non valides dans JS, mais je ne vois pas comment:

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

Des idées pour écrire une fonction isValidDate?

  • Ash a recommandé Date.parse pour analyser les chaînes de date, ce qui permet de vérifier si la chaîne de date est valide.
  • Ce que je préférerais, si possible, est que mon API accepte une instance de Date et puisse vérifier/affirmer si elle est valide ou non. La solution de Borgar fait cela, mais je dois la tester avec les navigateurs. Je me demande également s'il existe un moyen plus élégant.
  • Ash m'a fait envisager de ne pas laisser mon API accepter Date instances du tout, ce serait plus facile à valider.
  • Borgar a suggéré de tester une instance de Date, puis de tester la valeur temporelle de Date. Si la date n'est pas valide, la valeur de l'heure est NaN. J'ai vérifié avec ECMA-262 et ce comportement est dans la norme, ce qui est exactement ce que je recherche.
1318
orip

Voici comment je le ferais:

if (Object.prototype.toString.call(d) === "[object Date]") {
  // it is a date
  if (isNaN(d.getTime())) {  // d.valueOf() could also work
    // date is not valid
  } else {
    // date is valid
  }
} else {
  // not a date
}

Mise à jour [2018-05-31]: Si vous n'êtes pas concerné par les objets Date provenant d'autres contextes JS (fenêtres externes, cadres ou iframes), ce formulaire plus simple peut être préférable:

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

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

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

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

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

236
Ash

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

d instanceof Date && isFinite(d)

Pour éviter les problèmes inter-cadres, vous pouvez remplacer la vérification instanceof avec

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

Un appel à getTime() comme dans réponse de Borgar n'est pas nécessaire, car isNaN() et isFinite() sont tous deux implicitement convertis en nombre.

100
Christoph

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

La mise en oeuvre

Date.prototype.isValid = function () {
    // An invalid date object returns NaN for getTime() and NaN is the only
    // object not strictly equal to itself.
    return this.getTime() === this.getTime();
};  

Usage

var d = new Date("lol");

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

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

console.log(d.isValid()); // true
79
Ash Clarke

réponse la plus courte pour vérifier la date de validité

if(!isNaN(date.getTime()))
62
abhirathore2006

Vous pouvez simplement utiliser moment.js

Voici un exemple:

var m = moment('2015-11-32', 'YYYY-MM-DD');
m.isValid(); // false

Le section de validation dans la documentation est assez clair.

De plus, les indicateurs d'analyse suivants entraînent une date non valide:

  • overflow: débordement d'un champ de date, tel qu'un 13e mois, un 32e jour du mois (ou un 29 février pour les années non bissextiles), un 367e jour de l'année, etc. overflow contient les index de l'unité invalide pour correspondre à #invalidAt (voir ci-dessous); -1 signifie pas de débordement.
  • invalidMonth: Nom du mois invalide, tel que moment ('Marbruary', 'MMMM') ;. Contient la chaîne de mois invalide elle-même, ou null.
  • empty: Une chaîne d'entrée qui ne contient rien d'analyse, telle que moment ('this is nonsense') ;. Booléen.
  • Etc.

Source: http://momentjs.com/docs/

42
Yves M.

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

Même si vous ne souhaitez 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 validator en lui transmettant la valeur que vous souhaitez valider. Pour rendre la vie encore plus facile, il faut une chaîne en tant qu'entrée, et non un objet Date JavaScript.

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

Ce n'est pas répertorié en tant que méthode, mais c'est là, en tant que fonction utilitaire. Recherchez la page "Parsedate" et vous trouverez:

$ .datepicker.parseDate (format, valeur, paramètres) - Extrait une date 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);
             // Notice 'yy' indicates a 4-digit year value
} catch (e)
{
 alert(stringval + ' is not valid.  Format must be MM/DD/YYYY ' +
       'and the date value must be valid for the calendar.';
}

(Pour plus d'informations sur la spécification des formats de date, voir http://api.jqueryui.com/datepicker/#utility-parseDate )

Dans l'exemple ci-dessus, le message d'alerte ne s'affiche pas, car '01/03/2012 'est une date valide au calendrier dans le format spécifié. Toutefois, si vous définissez 'stringval' égal à '13/04/2013 ', par exemple, vous obtiendrez le message d'alerte, car la valeur '13/04/2013' n'est pas valide pour le calendrier.

Si une valeur de chaîne transmise est analysée avec succès, la valeur de 'testdate' sera un objet Date Javascript représentant la valeur de la chaîne transmise. Sinon, ce serait indéfini.

37
Matt Campbell

J'ai vraiment aimé l'approche de Christoph (mais je n'avais pas assez de réputation pour le faire accepter). Pour mon utilisation, je sais que j'aurai toujours un objet Date, alors je viens de prolonger la date avec une méthode valide ().

Date.prototype.valid = function() {
  return isFinite(this);
}

Maintenant, je peux simplement écrire ceci et c'est beaucoup plus descriptif que de simplement vérifier isFinite dans le code ...

d = new Date(userDate);
if (d.valid()) { /* do stuff */ }
22
broox
// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());
21
faridz

J'utilise le code suivant pour valider les valeurs pour l'année, le mois et la date.

function createDate(year, month, _date) {
  var d = new Date(year, month, _date);
  if (d.getFullYear() != year 
    || d.getMonth() != month
    || d.getDate() != _date) {
    throw "invalid date";
  }
  return d;
}

Pour plus de détails, reportez-vous à la section Vérifiez la date en javascript

15
Jingguo Yao

vous pouvez vérifier le format valide de txDate.value avec ce scirpt. Si le format est incorrect, l'objet Date n'est pas instancié et renvoie null à dt.

 var dt = new Date(txtDate.value)
 if (isNaN(dt))

Et comme suggéré par MiF à court terme

 if(isNaN(new Date(...)))
12
Yusef Mohamadi

Déjà trop de réponses compliquées ici, mais une simple ligne suffit (ES5):

Date.prototype.isValid = function (d) { return !isNaN(Date.parse(d)) } ;

ou même dans ES6:

Date.prototype.isValid = d => !isNaN(Date.parse(d));
12
Sebastien H.

Belle solution! Inclus dans ma bibliothèque de fonctions auxiliaires, cela ressemble maintenant à ceci:

Object.isDate = function(obj) {
/// <summary>
/// Determines if the passed object is an instance of Date.
/// </summary>
/// <param name="obj">The object to test.</param>

    return Object.prototype.toString.call(obj) === '[object Date]';
}

Object.isValidDate = function(obj) {
/// <summary>
/// Determines if the passed object is a Date object, containing an actual date.
/// </summary>
/// <param name="obj">The object to test.</param>

    return Object.isDate(obj) && !isNaN(obj.getTime());
}
9

Pour les projets Angular.js, vous pouvez utiliser:

angular.isDate(myDate);
9
Nick Taras

Cela a juste fonctionné pour moi

new Date('foo') == 'Invalid Date'; //is true

Cependant cela n'a pas fonctionné

new Date('foo') === 'Invalid Date'; //is false
8
user1296274

Aucune de ces réponses n'a fonctionné pour moi (testé dans Safari 6.0) lorsque j'essayais de valider une date telle que 2/31/2012. Cependant, elles fonctionnent correctement lorsque vous essayez une date supérieure à 31.

Je devais donc un peu de force brute. En supposant que la date est au format mm/dd/yyyy. J'utilise @broox réponse:

Date.prototype.valid = function() {
    return isFinite(this);
}    

function validStringDate(value){
    var d = new Date(value);
    return d.valid() && value.split('/')[0] == (d.getMonth()+1);
}

validStringDate("2/29/2012"); // true (leap year)
validStringDate("2/29/2013"); // false
validStringDate("2/30/2012"); // false
6
Dex

Aucune des solutions ci-dessus n'a fonctionné pour moi, mais ce qui a fonctionné est

function validDate (d) {
        var date = new Date(d);
        var day = ""+date.getDate();
        if( day.length == 1)day = "0"+day;
        var month = "" +( date.getMonth() + 1);
        if( month.length == 1)month = "0"+month;
        var year = "" + date.getFullYear();

        return ((month + "/" + day + "/" + year) == d);
    }

le code ci-dessus verra quand JS fera du 31/02/2012 au 03/02/2012 qu'il n'est pas valide

5
John

J'ai vu des réponses très proches de ce petit extrait.

Manière JavaScript:

function isValidDate(dateObject){ return new Date(dateObject).toString() !== 'Invalid Date'; }
isValidDate(new Date('WTH'));

Manière TypeScript:

const isValidDate = dateObject => new Date(dateObject ).toString() !== 'Invalid Date';
isValidDate(new Date('WTH'));
5
Jason Foglia
IsValidDate: function(date) {
        var regex = /\d{1,2}\/\d{1,2}\/\d{4}/;
        if (!regex.test(date)) return false;
        var day = Number(date.split("/")[1]);
        date = new Date(date);
        if (date && date.getDate() != day) return false;
        return true;
}
5
Michael Goldshmidt

J'ai écrit cette fonction. Si vous lui transmettez un paramètre de chaîne, il déterminera s’il s’agit d’une date valide ou non en fonction de ce format "jj/mm/aaaa".

voici un test

entrée: "hahaha", sortie: false.

entrée: "29/2/2000", sortie: vraie.

entrée: "29/2/2001", sortie: false.

function isValidDate(str) {
    var parts = str.split('/');
    if (parts.length < 3)
        return false;
    else {
        var day = parseInt(parts[0]);
        var month = parseInt(parts[1]);
        var year = parseInt(parts[2]);
        if (isNaN(day) || isNaN(month) || isNaN(year)) {
            return false;
        }
        if (day < 1 || year < 1)
            return false;
        if(month>12||month<1)
            return false;
        if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day > 31)
            return false;
        if ((month == 4 || month == 6 || month == 9 || month == 11 ) && day > 30)
            return false;
        if (month == 2) {
            if (((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0 && (year % 100) == 0)) {
                if (day > 29)
                    return false;
            } else {
                if (day > 28)
                    return false;
            }      
        }
        return true;
    }
}
4
Yaseen

Inspiré par l'approche de Borgar, j'ai veillé à ce que le code non seulement valide la date, mais s'assure en réalité que la date est une date réelle, ce qui signifie que les dates telles que 31/09/2011 et 29/02/2011 ne sont pas autorisées.

function(dateStr) {
    s = dateStr.split('/');
    d = new Date(+s[2], s[1]-1, +s[0]);
    if (Object.prototype.toString.call(d) === "[object Date]") {
        if (!isNaN(d.getTime()) && d.getDate() == s[0] && 
            d.getMonth() == (s[1] - 1)) {
            return true;
        }
    }
    return "Invalid date!";
}
3
Raz

J'ai combiné les meilleures performances que j'ai trouvées autour de cette vérification si un objet donné:

Le résultat est le suivant:

function isValidDate(input) {
  if(!(input && input.getTimezoneOffset && input.setUTCFullYear))
    return false;

  var time = input.getTime();
  return time === time;
};
3
zVictor

Une fonction prête basée sur la réponse la mieux notée:

  /**
   * Check if date exists and is valid.
   *
   * @param {String} dateString Date in YYYY-mm-dd format.
   */
  function isValidDate(dateString) {
  var isValid = false;
  var date;

  date =
    new Date(
      dateString);

  if (
    Object.prototype.toString.call(
      date) === "[object Date]") {

    if (isNaN(date.getTime())) {

      // Date is unreal.

    } else {
      // Date is real if month and day match each other in date and string (otherwise may be shifted):
      isValid =
        date.getUTCMonth() + 1 === dateString.split("-")[1] * 1 &&
        date.getUTCDate() === dateString.split("-")[2] * 1;
    }
  } else {
    // It's not a date.
  }

  return isValid;
}
2
Zon

La réponse choisie est excellente et je l'utilise aussi. Toutefois, si vous recherchez un moyen de valider la saisie de la date par l'utilisateur, sachez que l'objet Date est très persistant dans la volonté de transformer ce qui peut sembler être des arguments de construction non valides en arguments valables. Le code de test unitaire suivant illustre ce point:

QUnit.test( "valid date test", function( assert ) {
  //The following are counter-examples showing how the Date object will 
  //wrangle several 'bad' dates into a valid date anyway
  assert.equal(isValidDate(new Date(1980, 12, 15)), true);
  d = new Date();
  d.setFullYear(1980);
  d.setMonth(1);
  d.setDate(33);
  assert.equal(isValidDate(d), true);
  assert.equal(isValidDate(new Date(1980, 100, 150)), true);
  //If you go to this exterme, then the checker will fail
  assert.equal(isValidDate(new Date("This is junk")), false);
  //This is a valid date string
  assert.equal(isValidDate(new Date("November 17, 1989")), true);
  //but is this?
  assert.equal(isValidDate(new Date("November 35, 1989")), false);  
  //Ha!  It's not.  So, the secret to working with this version of 
  //isValidDate is to pass in dates as text strings... Hooboy
  //alert(d.toString());
});
2
dolphus333

Date.prototype.toISOString jette RangeError (au moins dans Chromium et Firefox) sur des dates non valides. Vous pouvez l'utiliser comme moyen de validation et vous n'avez peut-être pas besoin de isValidDate en tant que telle (EAFP). Sinon c'est:

function isValidDate(d)
{
  try
  {
    d.toISOString();
    return true;
  }
  catch(ex)
  {
    return false;    
  }    
}
2
saaj

Date date to string est un moyen plus simple et fiable de détecter si les deux champs sont des dates valides. par exemple. Si vous entrez ce "-------" dans le champ de saisie de la date. Certaines des réponses ci-dessus ne fonctionneront pas.

jQuery.validator.addMethod("greaterThan", 

    function(value, element, params) {
        var startDate = new Date($(params).val());
        var endDate = new Date(value);

        if(startDate.toString() === 'Invalid Date' || endDate.toString() === 'Invalid Date') {
            return false;
        } else {
            return endDate > startDate;
        }
    },'Must be greater than {0}.');
2
kam
function isValidDate(strDate) {
    var myDateStr= new Date(strDate);
    if( ! isNaN ( myDateStr.getMonth() ) ) {
       return true;
    }
    return false;
}

Appelez ça comme ça

isValidDate(""2015/5/2""); // => true
isValidDate(""2015/5/2a""); // => false
2
kiranvj

vous pouvez convertir votre date et heure en millisecondes getTime ()

this getTime() Méthode retourne pas un nombre NaN lorsqu'il n'est pas valide

if(!isNaN(new Date("2012/25/255").getTime()))
  return 'valid date time';
  return 'Not a valid date time';
2
Mina Gabriel
function isValidDate(date) {
  return !! (Object.prototype.toString.call(date) === "[object Date]" && +date);
}
1
Joel Kornbluh

Pour les composants int 1 d'une date:

var is_valid_date = function(year, month, day) {
    var d = new Date(year, month - 1, day);
    return d.getFullYear() === year && (d.getMonth() + 1) === month && d.getDate() === day
};

Tests:

    is_valid_date(2013, 02, 28)
&&  is_valid_date(2016, 02, 29)
&& !is_valid_date(2013, 02, 29)
&& !is_valid_date(0000, 00, 00)
&& !is_valid_date(2013, 14, 01)
1
Denis Ryzhkov

Je pense qu'une partie de ceci est un long processus. Nous pouvons le couper comme indiqué ci-dessous:

 function isValidDate(dateString) {
        debugger;
        var dateStringSplit;
        var formatDate;

        if (dateString.length >= 8 && dateString.length<=10) {
            try {
                dateStringSplit = dateString.split('/');
                var date = new Date();
                date.setYear(parseInt(dateStringSplit[2]), 10);
                date.setMonth(parseInt(dateStringSplit[0], 10) - 1);
                date.setDate(parseInt(dateStringSplit[1], 10));

                if (date.getYear() == parseInt(dateStringSplit[2],10) && date.getMonth()+1 == parseInt(dateStringSplit[0],10) && date.getDate() == parseInt(dateStringSplit[1],10)) {
                    return true;
                }
                else {
                    return false;
                }

            } catch (e) {
                return false;
            }
        }
        return false;
    }
1
user889209

Solution simple et élégante:

const date = new Date(`${year}-${month}-${day} 00:00`)
const isValidDate = (Boolean(+date) && date.getDate() == day)

sources:

[1] https://medium.com/@esganzerla/simple-date-validation-with-javascript-caea0f71883c

[2] Date incorrecte indiquée dans la nouvelle date () en JavaScript

1
Soubriquet

Généralement, je m'en tenir à la date d'implantation indiquée dans la pile du navigateur. Ce qui signifie que vous obtiendrez toujours une "date non valide" lors de l'appel de toDateString () sous Chrome, Firefox et Safari à la date de cette réponse.

if(!Date.prototype.isValidDate){
  Date.prototype.isValidDate = function(){
    return this.toDateString().toLowerCase().lastIndexOf('invalid') == -1;
  };
}

Je n'ai pas testé cela dans IE bien que.

1
pixelbacon

J'ai donc aimé @Ask Clarke répondre avec peu d'amélioration en ajoutant try bloc pour les dates qui ne peuvent pas passer par var d = new Date (d) -

function checkIfDateNotValid(d) {
        try{
            var d = new Date(d);
            return !(d.getTime() === d.getTime()); //NAN is the only type which is not equal to itself.
        }catch (e){
            return true;
        }

    }
1
Saurabh Gupta

date.parse(valueToBeTested) > 0 est tout ce dont vous avez besoin. Une date valide retournera la valeur Epoch et une valeur invalide renverra NaN qui échouera > 0 test du fait qu’il n’est même pas un nombre.

C’est si simple qu’une fonction d’aide ne sauvegarde pas le code, même s’il est peut-être un peu plus lisible. Si vous en vouliez un:

String.prototype.isDate = function() {
  return !Number.isNaN(Date.parse(this));
}

OR

Utiliser:

"StringToTest".isDate();
0
rainabba

Encore un autre moyen de vérifier si la date est un objet de date valide:

const isValidDate = (date) => 
  typeof date === 'object' && 
  typeof date.getTime === 'function' && 
  !isNaN(date.getTime())
0
iwatakeshi
Date.valid = function(str){
  var d = new Date(str);
  return (Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()));
}

https://Gist.github.com/dustinpoissant/b83750d8671f10c414b346b16e290ecf

0
Dustin Poissant

Cette version d'isValidDate utilise une expression régulière qui gère les années bissextiles:

function isValidDate(value)
{
    return /((^(10|12|0?[13578])([/])(3[01]|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(11|0?[469])([/])(30|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(2[0-8]|1[0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(29)([/])([2468][048]00)$)|(^(0?2)([/])(29)([/])([3579][26]00)$)|(^(0?2)([/])(29)([/])([1][89][0][48])$)|(^(0?2)([/])(29)([/])([2-9][0-9][0][48])$)|(^(0?2)([/])(29)([/])([1][89][2468][048])$)|(^(0?2)([/])(29)([/])([2-9][0-9][2468][048])$)|(^(0?2)([/])(29)([/])([1][89][13579][26])$)|(^(0?2)([/])(29)([/])([2-9][0-9][13579][26])$))/.test(value)
}
0
Greg Finzer
var isDate_ = function(input) {
        var status = false;
        if (!input || input.length <= 0) {
          status = false;
        } else {
          var result = new Date(input);
          if (result == 'Invalid Date') {
            status = false;
          } else {
            status = true;
          }
        }
        return status;
      }
0
Dhayalan

Cette fonction valide une date de chaîne dans des formats de chiffres délimités par un caractère, par exemple. jj/mm/aaaa, mm/jj/aaaa

/*
Param  : 
1)the date in string data type 
2)[optional - string - default is "/"] the date delimiter, most likely "/" or "-"
3)[optional - int - default is 0] the position of the day component when the date string is broken up via the String.split function (into arrays)
4)[optional - int - default is 1] the position of the month component when the date string is broken up via the String.split function (into arrays)
5)[optional - int - default is 2] the position of the year component when the date string is broken up via the String.split function (into arrays)

Return : a javascript date is returned if the params are OK else null
*/
function IsValidDate(strDate, strDelimiter, iDayPosInArray, iMonthPosInArray, iYearPosInArray) {
    var strDateArr; //a string array to hold constituents day, month, and year components
    var dtDate; //our internal converted date
    var iDay, iMonth, iYear;


    //sanity check 
    //no integer checks are performed on day, month, and year tokens as parsing them below will result in NaN if they're invalid
    if (null == strDate || typeof strDate != "string")
        return null;

    //defaults
    strDelimiter = strDelimiter || "/";
    iDayPosInArray = undefined == iDayPosInArray ? 0 : iDayPosInArray;
    iMonthPosInArray = undefined == iMonthPosInArray ? 1 : iMonthPosInArray;
    iYearPosInArray = undefined == iYearPosInArray ? 2 : iYearPosInArray;

    strDateArr = strDate.split(strDelimiter);

    iDay = parseInt(strDateArr[iDayPosInArray],10);
    iMonth = parseInt(strDateArr[iMonthPosInArray],10) - 1; // Note: months are 0-based
    iYear = parseInt(strDateArr[iYearPosInArray],10);

    dtDate = new Date(
        iYear,
        iMonth, // Note: months are 0-based
        iDay);

    return (!isNaN(dtDate) && dtDate.getFullYear() == iYear && dtDate.getMonth() == iMonth && dtDate.getDate() == iDay) ? dtDate : null; // Note: months are 0-based
}

Exemple d'appel:

var strDate="18-01-1971";

if (null == IsValidDate(strDate)) {

  alert("invalid date");
}
0
wanglabs