Een datum-instantie met een “ongeldige datum” detecteren in JavaScript

Ik wil graag het verschil zien tussen geldige en ongeldige datumobjecten in JS, maar ik weet niet hoe:

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'

Ideeën voor het schrijven van een functie isValidDate?

  • Ash raadde Date.parseaan voor het ontleden van datumreeksen, wat een gezaghebbende manier biedt om te controleren of de datumreeks geldig is.
  • Waar ik de voorkeur aan geef, indien mogelijk, is dat mijn API een Date-instantie accepteert en kan controleren/beweren of deze geldig is of niet. De oplossing van Borgar doet dat, maar ik moet het in verschillende browsers testen. Ik vraag me ook af of er een elegantere manier is.
  • Ash liet me overwegen om mijn API helemaal geen Date-instanties te laten accepteren, dit zou het gemakkelijkst te valideren zijn.
  • Borgar stelde voor om te testen voor een Date-instantie en vervolgens te testen voor de tijdwaarde van de Date. Als de datum ongeldig is, is de tijdwaarde NaN. Ik heb het gecontroleerd met ECMA- 262en dit gedrag zit in de standaard, en dat is precies wat ik zoek.

Antwoord 1, autoriteit 100%

Zo zou ik het doen:

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
}

Update [2018-05-31]: als u zich niet bezighoudt met Date-objecten uit andere JS-contexten (externe vensters, frames of iframes), heeft deze eenvoudigere vorm wellicht de voorkeur:

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

Antwoord 2, autoriteit 19%

In plaats van new Date()te gebruiken, moet je het volgende gebruiken:

var timestamp = Date.parse('foo');
if (isNaN(timestamp) == false) {
  var d = new Date(timestamp);
}

Date.parse()retourneert een tijdstempel, een geheel getal dat staat voor het aantal milliseconden sinds 01/Jan/1970. Het zal NaNteruggeven als het de opgegeven datumstring niet kan ontleden.


Antwoord 3, autoriteit 8%

U kunt de geldigheid van een Dateobject dcontroleren via

d instanceof Date && isFinite(d)

Om cross-frame problemen te voorkomen, zou men de instanceofcheck kunnen vervangen door

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

Een aanroep naar getTime()zoals in Borgars antwoordis niet nodig omdat isNaN()en isFinite()beide impliciet worden omgezet in een getal.


Antwoord 4, autoriteit 6%

Mijn oplossing is om simpelweg te controleren of je een geldig datumobject krijgt:

Implementatie

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();
};  

Gebruik

var d = new Date("lol");
console.log(d.isValid()); // false
d = new Date("2012/09/11");
console.log(d.isValid()); // true

Antwoord 5, autoriteit 5%

kortste antwoord om geldige datum te controleren

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

Antwoord 6, autoriteit 3%

Je kunt gewoon moment.js

gebruiken

Hier is een voorbeeld:

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

De validatiesectiein de documentatie is vrij duidelijk.

En ook de volgende parseervlaggen resulteren in een ongeldige datum:

  • overflow: een overloop van een datumveld, zoals een 13e maand, een 32e dag van de maand (of 29 februari op niet-schrikkeljaren), een 367e dag van het jaar , etc. overflow bevat de index van de ongeldige eenheid die overeenkomt met #invalidAt (zie hieronder); -1 betekent geen overloop.
  • invalidMonth: een ongeldige maandnaam, zoals moment(‘Marbruary’, ‘MMMM’);. Bevat de ongeldige maandtekenreeks zelf, of anders null.
  • empty: een invoertekenreeks die niets paraseerbaars bevat, zoals moment(‘dit is onzin’);. Booleaans.
  • Enz.

Bron: http://momentjs.com/docs/


Antwoord 7, autoriteit 2%

Wilt u vermelden dat de JQuery UI DATEPICKER-widget een zeer goede datum validatorhulpmethode heeft die controleert op formaat en geldigheid (bijvoorbeeld nr. 01/33/2013 data toegestaan).

Zelfs als u de DATEPICKER-widget op uw pagina als een UI-element niet wilt gebruiken, kunt u altijd de .js-bibliotheek toevoegen aan uw pagina en vervolgens de Validator-methode bellen, waarbij u de waarde wilt laten valideren . Om het leven nog eenvoudiger te maken, maakt het een tekenreeks als invoer, geen JavaScript-datumobject.

Zie: http://api.jQueryui.com/datepicker/

Het is niet vermeld als een methode, maar het is daar – als een nutsfunctie. Doorzoek de pagina voor “Parsedate” en u zult vinden:

$. DATEPICKER.PARSEDATE (FORMATION, VALUE, INSTELLINGEN) – Pak een datum uit van een stringwaarde met een opgegeven formaat.

Voorbeeldgebruik:

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.';
}

(meer info re opgeeft datumformaten is te vinden op http://api.jQueryui.com / DATEPICKER / # Utility-Parsedate )

In het bovenstaande voorbeeld ziet u het ALERT-bericht sinds ’01 / 03/2012 ‘een agenda-geldige datum in het opgegeven formaat. Als u bijvoorbeeld ‘stringval’ gelijk hebt gemaakt aan ’13 / 04/2013 ‘, krijgt u bijvoorbeeld het ALERT-bericht, aangezien de waarde ’13 / 04/2013’ geen agenda-geldig is.

Als een doorgegeven tekenreekswaarde succesvol is geparseerd, zou de waarde van ‘testdate’ een Javascript Date-object zijn dat de doorgegeven tekenreekswaarde vertegenwoordigt. Zo niet, dan is het ongedefinieerd.


Antwoord 8, autoriteit 2%

// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());

Antwoord 9, autoriteit 2%

Ik heb enkele antwoorden gezien die heel dicht bij dit kleine fragment kwamen.

JavaScript-manier:

function isValidDate(dateObject){
    return new Date(dateObject).toString() !== 'Invalid Date';
}
console.log(isValidDate('WTH')); // -> false
console.log(isValidDate(new Date('WTH'))); // -> false
console.log(isValidDate(new Date())); // -> true

Antwoord 10, autoriteit 2%

Ik vond de aanpak van Christoph erg goed (maar had niet genoeg reputatie om het te bevestigen).
Voor mijn gebruik weet ik dat ik altijd een Date-object zal hebben, dus ik heb de datum gewoon verlengd met een valid()-methode.

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

Nu kan ik dit gewoon schrijven en het is veel beschrijvender dan alleen isFinite in code controleren…

d = new Date(userDate);
if (d.valid()) { /* do stuff */ }

Antwoord 11

Ik gebruik de volgende code om waarden voor jaar, maand en datum te valideren.

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;
}

Raadpleeg voor details Controleer de datum in javascript


Antwoord 12

u kunt het geldige formaat van txDate.value controleren met deze scirpt. als het in een onjuist formaat was, is de datum obejct niet geïnventariseerd en retourneert null naar dt .

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

En zoals @MiF’s in het kort suggereerde

if(isNaN(new Date(...)))

Antwoord 13

Er zijn hier al te veel ingewikkelde antwoorden, maar een simpele regel is voldoende (ES5):

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

of zelfs in ES6 :

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

Antwoord 14

Dit werkte gewoon voor mij

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

Dit werkte echter niet

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

Antwoord 15

Voor Angular.js-projecten kunt u het volgende gebruiken:

angular.isDate(myDate);

Antwoord 16

Ik heb de volgende oplossing geschreven op basis van Borgar’s oplossing. Inbegrepen in mijn bibliotheek met hulpfuncties, ziet er nu zo uit:

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());
}

Antwoord 17

Geen van deze antwoorden werkte voor mij (getest in Safari 6.0) bij het valideren van een datum zoals 31-2-2012, maar ze werken prima bij het proberen van een datum groter dan 31.

Dus ik moest een beetje bruut geweld gebruiken. Ervan uitgaande dat de datum in het formaat mm/dd/yyyyis. Ik gebruik @broox antwoord:

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

Antwoord 18

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;
}

Antwoord 19

Ik heb deze functie geschreven. Geef het een stringparameter door en het zal bepalen of het een geldige datum is of niet op basis van dit formaat “dd/MM/jjjj”.

hier is een test

invoer: “hahaha”, uitvoer: onwaar.

invoer: “29/2/2000”, uitvoer: waar.

invoer: “29/2/2001”, uitvoer: onwaar.

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;
    }
}

Antwoord 20

Date.prototype.toISOStringgooit RangeError(tenminste in Chromium en Firefox) op ongeldige datums. U kunt het gebruiken als een validatiemiddel en u hoeft isValidDateals zodanig niet (EAFP) te hebben. Anders is het:

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

Antwoord 21

Geen van de bovenstaande oplossingen werkte voor mij, wat wel werkte is

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 );
}

de bovenstaande code zal zien dat wanneer JS 31/02/2012 in 03/02/2012 maakt, deze niet geldig is


Antwoord 22

Geïnspireerd door Borgar’s aanpakheb ik ervoor gezorgd dat de code niet alleen de datum valideert, maar er ook voor zorgt dat de datum echt is datum, wat betekent dat datums zoals 31/09/2011 en 29/02/2011 niet zijn toegestaan.

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!";
}

Antwoord 23

Ik raad bibliotheken zelden aan als je zonder kan. Maar gezien de overvloed aan antwoorden tot nu toe, lijkt het de moeite waard om erop te wijzen dat de populaire bibliotheek “date-fns” een functie isValidheeft. De volgende documentatie is afkomstig van hun website:

isValid argument Vóór v2.0.0 v2.0.0 en later
nieuwe datum() waar waar
nieuwe datum(‘2016-01-01’) waar waar
nieuwe datum(”) false false
nieuwe datum (1488370835081) waar waar
nieuwe datum(NaN) false false
‘2016-01-01’ TypeError false
TypeError false
1488370835081 TypeError waar
NaN TypeError false

Antwoord 24

Ik heb de beste prestatieresultaten die ik vond bij die controle gecombineerd als een bepaald object:

Het resultaat is het volgende:

function isValidDate(input) {
  if(!(input && input.getTimezoneOffset && input.setUTCFullYear))
    return false;
  var time = input.getTime();
  return time === time;
};

Antwoord 25

Niemand heeft het nog genoemd, dus symbolen zouden ook een goede oplossing zijn:

Symbol.for(new Date("Peter")) === Symbol.for("Invalid Date") // true
Symbol.for(new Date()) === Symbol.for("Invalid Date") // false

console.log('Symbol.for(new Date("Peter")) === Symbol.for("Invalid Date")', Symbol.for(new Date("Peter")) === Symbol.for("Invalid Date")) // true
console.log('Symbol.for(new Date()) === Symbol.for("Invalid Date")', Symbol.for(new Date()) === Symbol.for("Invalid Date")) // false

Antwoord 26

Na het lezen van elk antwoord tot nu toe, ga ik de meest eenvoudige antwoorden geven.

Elke oplossing hier vermeldt het aanroepen van date.getTime(). Dit is echter niet nodig, omdat de standaardconversie van Datum naar Getal is om de waarde getTime() te gebruiken. Ja, uw typecontrole zal klagen. 🙂 En de OP weet duidelijk dat ze een Dateobject hebben, dus daar hoef je ook niet op te testen.

Te testen op een ongeldigedatum:

isNaN(date)

Te testen op een geldigedatum:

!isNaN(date)

Antwoord 27

Datumobject naar string is een eenvoudigere en betrouwbaardere manier om te detecteren of beide velden een geldige datum zijn.
bijv. Als u deze “——-” invoert in het datuminvoerveld. Sommige van de bovenstaande antwoorden werken niet.

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}.');

Antwoord 28

Voor op int 1-gebaseerde componenten van een datum:

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
};

Testen:

   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)

Antwoord 29

u kunt uw datum en tijd converteren naar milliseconden getTime()

deze getTime()Methode retourneert Geen getal NaNwanneer niet geldig

if(!isNaN(new Date("2012/25/255").getTime()))
  return 'valid date time';
  return 'Not a valid date time';

Antwoord 30

Het geselecteerde antwoord is uitstekend en ik gebruik het ook. Als u echter op zoek bent naar een manier om de invoer van gebruikersdatums te valideren, moet u zich ervan bewust zijn dat het Date-object erg volhardend is in het maken van ongeldige constructieargumenten in geldige argumenten. De volgende eenheidstestcode illustreert het punt:

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());
});

Other episodes