Rilevamento di un'istanza di data "non valida" in JavaScript


1494

Vorrei dire la differenza tra oggetti data validi e non validi in JS, ma non sono riuscito a capire come:

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'

Qualche idea per scrivere una isValidDatefunzione?

  • Ash ha raccomandato Date.parsedi analizzare le stringhe di date, il che fornisce un modo autorevole per verificare se la stringa di date è valida.
  • Ciò che preferirei, se possibile, è che la mia API accetti un'istanza Date e che sia in grado di verificare / affermare se è valida o meno. La soluzione di Borgar lo fa, ma devo provarlo su tutti i browser. Mi chiedo anche se esiste un modo più elegante.
  • Ash mi ha fatto considerare di non far accettare le Dateistanze alle mie API , questo sarebbe più facile da convalidare.
  • Borgar ha suggerito di provare per Dateun'istanza, e quindi di testare il Datevalore temporale. Se la data non è valida, il valore dell'ora è NaN. Ho verificato con ECMA-262 e questo comportamento è nello standard, che è esattamente quello che sto cercando.

18
È possibile rimuovere l'istruzione if modificando il corpo della funzione in:return ( Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()) );
styfle

3
@styfle - suppongo sia una preferenza di stile: trovo più chiaro separare il controllo del tipo dalla logica dell'uguaglianza.
Orip,

26
Il discorso di @orip è esattamente ciò che è fortemente scoraggiato dalle domande. Consultare i meta argomenti pertinenti per apprendere le motivazioni alla base. Inserire una risposta alla propria domanda nella domanda stessa è contrario alla politica del sito. OTOH, ringraziare per le risposte e avere "EDIT" nella tua risposta è un tipico fluff. Se vuoi che la tua domanda più votata ti identifichi come una persona che non sa cos'è la SO e come usarla, e non desidera impararla, sii mia ospite.

14
@orip: non è stato "perso"; sta ancora ingombrando la cronologia delle revisioni della domanda se vuoi vederla di nuovo. Ma non appartiene a una domanda. A 37k rappresentanti dovresti saperlo.
Razze di leggerezza in orbita,

6
Si prega di fermare la guerra di modifica. Le modifiche a questa domanda sono discusse su meta . Non modificare / ripristinare ulteriormente questo post. Se non sei d'accordo con precedenti modifiche / rollback o hai commenti in merito, ti preghiamo di pubblicare su quel meta thread e non qui.
Lundin,

Risposte:


1304

Ecco come lo farei:

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
}

Aggiornamento [2018-05-31] : se non si è interessati agli oggetti Date di altri contesti JS (finestre esterne, frame o iframe), è possibile preferire questo modulo più semplice:

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

21
instanceof si rompe attraverso i frame. Anche la digitazione dell'anatra può funzionare bene: validDate == d && d.getTime &&! IsNaN (d.getTime ()); - Poiché la domanda riguarda una funzione di utilità generale, preferisco essere più severa.
Borgar,

11
@Borgar, ho appena trovato la mia risposta: "I problemi sorgono quando si tratta di scripting in ambienti DOM multi-frame. In breve, gli oggetti Array creati all'interno di un iframe non condividono quelli di [[Prototype]] con gli array creati all'interno di un altro iframe I loro costruttori sono oggetti diversi e quindi falliscono sia i controlli di instanceof che quelli di costruttori ".
Ash,

64
non ti serve nemmeno d.getTimesoloisNan(d)
TecHunter

8
Potrebbe essere semplificato in questo modo:d instanceof Date && !isNaN(d.getTime())
Zorgatone,

5
Grazie per la risposta, ma desidero sottolineare i commenti di @Borgar e @blueprintChris: se analizzo la cifra, 1ad esempio, avrei comunque una data valida risultante Mon Jan 01 2001 00:00:00che è effettivamente una data, tuttavia ai fini della mia applicazione è completamente inutile . Pertanto, nel mio caso è necessario almeno un po 'più di convalida dell'input. Questa risposta conferma un dateObjectnon a Date!
dnhyde,

264

Invece di usare new Date()dovresti usare:

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

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

Date.parse()restituisce un timestamp, un numero intero che rappresenta il numero di millisecondi dall'01 / gen / 1970. Restituirà NaNse non è in grado di analizzare la stringa della data fornita.


119
-1 Non so perché questo abbia così tanti voti positivi, Date.parsedipende dall'implementazione e sicuramente non ci si può fidare di analizzare le stringhe di date generali. Non esiste un singolo formato analizzato correttamente nei browser più diffusi, tanto meno tutti quelli in uso (anche se alla fine il formato ISO8601 specificato in ES5 dovrebbe essere ok).
RobG

1
Se usi new Date('foo')questo è sostanzialmente equivalente al Date.parse('foo')metodo. Vedi: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Quindi ciò che ha detto @RobG, si applica anche ad esso.
golddragon007,

2
Questo test fallirebbe in Chrome. Ad esempio, Date.parse ('AAA-0001') in Chrome mi dà un numero.
Nick,

fallito ... rileva tutti i valori numerici
Hos Mercury

109

È possibile verificare la validità di un Dateoggetto dtramite

d instanceof Date && isFinite(d)

Per evitare problemi tra frame, è possibile sostituire il instanceofcontrollo con

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

Una chiamata a getTime()come nella risposta di Borgar è superflua, in quanto isNaN()e isFinite()sia implicitamente convertire in numero.


Prova questo in chrome - Object.prototype.toString.call (nuova data ("2013-07-09T19: 07: 9Z")). Restituirà "[Data oggetto]". Secondo te, quindi, "2013-07-09T19: 07: 9Z", dovrebbe essere una data valida. Ma non è. Puoi verificarlo, sempre in Chrome, facendo var dateStr = new Date ("2013-07-09T19: 07: 9Z"); dateStr Restituirà una data non valida.
Tintin,

2
@Tintin: ecco a cosa isFinite()serve - toString.call()è solo una sostituzione per la instanceofparte dell'assegno
Christoph,

Il confronto con "[data oggetto]" funzionerà con browser non inglesi? Ne dubito.
kristianp,

2
@kristianp in realtà probabilmente lo farà ed è probabilmente anche parte delle specifiche ECMAScript. Ma sì, sembra brutto.
binki,

Per me il primo approccio qui è l'opzione migliore, anche se non sono sicuro che ci sia un vantaggio reale nell'utilizzare isFiniteover isNaN(entrambi funzionano bene con Date(Infinity)). Inoltre, se si desidera che la condizione opposta, diventa un po 'più semplice: if (!(date instanceof Date) || isNaN(date)).
Andrew

86

La mia soluzione è semplicemente verificare se si ottiene un oggetto data valido:

Implementazione

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

uso

var d = new Date("lol");

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

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

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

28
isNaNè un modo più esplicito per testare NaN
orip,

1
Eppure, trovi sempre persone che scrivono le loro versioni :) documentcloud.github.com/underscore/docs/…
Ash Clarke,

4
dal momento che rispetto underscore.js questo ha spinto alcune ricerche. isNaN("a") === true, mentre ("a" !== "a") === false. Vale la pena pensarci. +1
orip

8
Ho testato le prestazioni per le 3 soluzioni principali che ho trovato qui. Complimenti, sei il vincitore! jsperf.com/detecting-an-invalid-date
zVictor

2
@Ali Questo è un oggetto data valido. new Date("02-31-2000") // Thu Mar 02 2000 00:00:00 GMT+0000 (GMT Standard Time). Se si passa una stringa al costruttore della data, è necessario passare una stringa standardizzata per ottenere un risultato affidabile. In particolare, "La stringa deve essere in un formato riconosciuto dal metodo Date.parse ()". developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ash Clarke,

71

risposta più breve per verificare la data valida

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

2
L'unico problema è se la data non è del tipo Date; viene visualizzato un errore JS.
Andrew

@Andrew è necessario creare l'oggetto Date e se si dispone già di un oggetto, utilizzaredate && !isNaN(date.getTime())
abhirathore2006

Questo ti dà ancora un errore JS se datenon è di tipo Data. Ad esempio: var date = 4; date && !isNaN(date.getTime());.
Andrew

@Andrew use date instanceof Date && !isNaN(date.getTime())
abhirathore2006,

3
Giusto, come le altre risposte di 8 anni fa. : P stackoverflow.com/a/1353945/2321042
Andrew

45

Puoi semplicemente usare moment.js

Ecco un esempio:

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

La sezione di validazione nella documentazione è abbastanza chiara.

Inoltre, i seguenti flag di analisi generano una data non valida:

  • overflow: Un overflow di un campo data, ad esempio un 13 ° mese, un 32 ° giorno del mese (o un 29 febbraio negli anni non bisestili), un 367 ° giorno dell'anno, ecc. Overflow contiene l'indice dell'unità non valida per abbinare #invalidAt (vedi sotto); -1 significa nessun overflow.
  • invalidMonth: Un nome di mese non valido, ad esempio momento ('Mar febbraio', 'MMMM') ;. Contiene la stringa del mese non valida stessa, oppure null.
  • empty: Una stringa di input che non contiene nulla di analizzabile, ad esempio moment ('this isssens') ;. Booleano.
  • Eccetera.

Fonte: http://momentjs.com/docs/


6
La migliore soluzione, estremamente facile da implementare, funziona con qualsiasi formattazione (il mio caso è gg / MM / aaaa), conosce anche gli anni bisestili e non converte le date non valide (cioè il 29/02/2015) in valide da solo (cioè 30/03/2015). Per controllare una data nel formato gg / MM / aaaa che ho appena dovuto usaremoment("11/06/1986", "DD/MM/YYYY").isValid();
Rafael Merlin,

3
Questo uso di Moment è stato deprecato :(
James Sumners,

2
Questo uso non è stato ammortizzato. Il momento della chiamata (input) senza una stringa di formato è ammortizzato (a meno che l'input non sia formattato ISO).
Chet

2
Questo metodo può essere estremamente lento quando si elaborano molte date. Meglio usare una regex in quei casi.
Grid Trekkor,

2
L'uso di moment.js può essere semplice, ma è un enorme sovraccarico. Questa libreria è ENORME. Ho votato in negativo la tua risposta.
Mick,

38

Vorrei menzionare che il widget DatePicker dell'interfaccia utente jQuery ha un ottimo metodo di utilità per la convalida della data che controlla il formato e la validità (ad esempio, non sono consentite date del 01/01/2013).

Anche se non vuoi usare il widget datepicker sulla tua pagina come elemento UI, puoi sempre aggiungere la sua libreria .js alla tua pagina e quindi chiamare il metodo validator, passando il valore che vuoi validare in essa. Per rendere la vita ancora più semplice, ci vuole una stringa come input, non un oggetto Date JavaScript.

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

Non è elencato come metodo, ma è lì, come funzione di utilità. Cerca "parsedate" nella pagina e troverai:

$ .datepicker.parseDate (formato, valore, impostazioni) - Estrai una data da un valore di stringa con un formato specificato.

Esempio di utilizzo:

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

(Ulteriori informazioni sulla specifica dei formati di data sono disponibili all'indirizzo http://api.jqueryui.com/datepicker/#utility-parseDate )

Nell'esempio sopra, non visualizzerai il messaggio di avviso poiché "01/03/2012" è una data valida per il calendario nel formato specificato. Tuttavia, se si imposta 'stringval' uguale a '13 / 04/2013 ', ad esempio, si otterrà il messaggio di avviso, poiché il valore '13 / 04/2013' non è valido per il calendario.

Se un valore di stringa passato viene analizzato correttamente, il valore di 'testdate' sarebbe un oggetto Date Javascript che rappresenta il valore di stringa passato. Altrimenti, sarebbe indefinito.


3
Voto per essere la prima risposta lavorando con formati di data non inglese / locale.
ax.

26

Mi è piaciuto molto l'approccio di Christoph (ma non avevo abbastanza reputazione per votarlo). Per il mio uso, so che avrò sempre un oggetto Date, quindi ho appena esteso la data con un metodo valid ().

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

Ora posso solo scrivere questo ed è molto più descrittivo del semplice controllo di isFinite nel codice ...

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

10
Estensione del prototipo? Questo è un grande JavaScript no no!
Jasdeep Khalsa,

La votazione a causa del fatto ha isFinitefunzionato perfettamente per me. Ma sì, inutile estendere il prototipo. !isFinitesu un Datecatturerà il fatto che Dateè Invalid Date. Vale anche la pena notare che il mio contesto è all'interno di Node.
Staghouse,

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

5
È lo stesso scritto da @Borgar 2 anni fa ... Novità ??
bluastro

11
Sono due righe invece di brutte istruzioni if ​​annidate.
Cypher,

17

puoi controllare il formato valido di txDate.value con questo scirpt. se era in formato errato, l'oggetto Data non è stato istanziato e restituisce null a dt.

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

E come ha suggerito @ MiF in breve

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

isNaN (nuova data (...)) - il metodo semplice e breve
MiF

1
@MiF sì, aggiorno la mia risposta con il tuo suggerimento;) grazie
Yuseferi

16

Uso il seguente codice per convalidare i valori per anno, mese e data.

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

Per i dettagli, consultare Controlla data in javascript


strnon viene utilizzato.
Samis,

12

Sono già presenti troppe risposte complicate, ma è sufficiente una semplice riga (ES5):

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

o anche in ES6:

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

1
Da MDN: "Il metodo Date.parse () analizza una rappresentazione in forma di stringa di una data e restituisce il numero di millisecondi dal 1 ° gennaio 1970, 00:00:00 UTC o NaN ..." Quindi eseguendo una data potenziale attraverso questo La funzione restituisce un numero intero o NaN. Quindi la funzione isNaN () fornirà un valore booleano pulito che ti dirà se il valore originale era o meno un oggetto data valido. Questo è sufficiente per effettuare un controllo a campione, ma l'esempio sopra attacca quindi questo metodo all'oggetto Date per rendere la funzionalità facilmente disponibile e leggibile in tutto il programma.
Max Wilder

se d è booleano riceverai 0 o 1 che non è un Nan !!
davcup,

@davcup appena testato con Date.parse(true), ho correttamente ricevuto una NaN.
Sebastien H.

12

Ho visto alcune risposte che si sono avvicinate molto a questo piccolo frammento.

Modo JavaScript:

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

Modo TypeScript:

const isValidDate = dateObject => new Date(dateObject ).toString() !== 'Invalid Date';
isValidDate(new Date('WTH'));

1
Non sei sicuro che mi manchi qualcosa, ma non sto facendo una nuova data () due volte inutile?
Jon Catmull,

2
Quest'ultimo non ha nulla a che fare con TypeScript. È perfettamente valido JS.
hackel

9

Bella soluzione! Incluso nella mia libreria di funzioni ausiliarie, ora appare così:

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

Questo ha funzionato per me

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

Tuttavia questo non ha funzionato

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

5
Credo che questo dipenda dal browser.
barrypicker,

@barrypicker Cosa vuoi dire che dipende dal browser?
Ajil O.

Puoi fare: `${new Date('foo')}` === 'Invalid Date'
Daniele Vrut il

9

Per i progetti Angular.js è possibile utilizzare:

angular.isDate(myDate);

3
Ciò restituisce true per il test di un oggetto data che è stato inizializzato con una data non valida.
Dchhetri,

6

Nessuna di queste risposte ha funzionato per me (testato in Safari 6.0) quando si tenta di convalidare una data come 31/02/2012, tuttavia, funzionano bene quando si tenta una data superiore a 31.

Quindi ho dovuto forzare un po 'la forza. Supponendo che la data sia nel formato mm/dd/yyyy. Sto usando la risposta di @broox:

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

(nuova data ('30/02/2014')). valid () restituisce true
Andre Figueiredo

1
È passato un po 'di tempo da quando ho risposto a questa domanda, ma potresti aver bisogno di entrambe le condizioni di reso, incluso il&& value.split('/')[0] == (d.getMonth()+1);
Dex

L'uso new Date('string date')è equivalente a Date.parse('string date'), vedi: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… in modo da poter ottenere valori falsi veri o falsi.
golddragon007,

5

Nessuna delle soluzioni di cui sopra ha funzionato per me ciò che ha funzionato comunque è

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

il codice sopra vedrà quando JS rende il 31/02/2012 il 03/02/2012 che non è valido


3
Ok, ma questo verifica se una stringa è una data in un formato M / D / Y, non "la differenza tra oggetti data validi e non validi". Non è proprio di questo che si tratta.
Borgar,

il motivo per cui è stato verificato rispetto al formato è verificare se la data è cambiata dopo che è stata analizzata
Giovanni

L'OP non sta chiedendo un metodo per restituire un valore booleano, non una stringa formattata?
barrypicker,

1
Il codice di esempio restituisce un valore booleano, la formulazione svolge un ruolo nel testing di alcuni dei casi non validi.
Giovanni

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

4

Ho scritto questa funzione. Passa un parametro stringa e determinerà se è una data valida o meno in base a questo formato "gg / MM / aaaa".

ecco un test

input: "hahaha", output: falso.

input: "29/2/2000", output: vero.

input: "29/2/2001", output: falso.

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

Date.prototype.toISOStringgenera RangeError(almeno in Chromium e Firefox) in date non valide. Puoi usarlo come mezzo di convalida e potrebbe non essere necessario in isValidDatequanto tale (EAFP). Altrimenti è:

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

1
Sembra che sia l'unica funzione che genera un errore dalla definizione ECMA-262. 15.9.5.43 Date.prototype.toISOString () Questa funzione restituisce un valore String che rappresenta l'istanza nel tempo rappresentata da questo oggetto Date. Il formato della stringa è il formato stringa della data e ora definito in 15.9.1.15. Tutti i campi sono presenti nella stringa. Il fuso orario è sempre UTC, indicato dal suffisso Z. Se il valore temporale di questo oggetto non è un numero finito, viene generata un'eccezione RangeError.
Henry Liu,

3

Ispirato all'approccio di Borgar, mi sono assicurato che il codice non solo convalida la data, ma in realtà si assicura che la data sia una data reale, il che significa che date come il 31/09/2011 e il 29/02/2011 non sono consentite.

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

Ma ... i metodi sopra (@ Borgar e gli altri) verificano già questo tipo di validità ... Non riesco a capire il problema.
bluastro

Borgar's no - vede il proprio commento alla sua risposta.
EML

1
Questa soluzione funziona solo quando il tuo paese utilizza la dd/MM/yyyynotazione. Inoltre, restituisce truequando è valido e, in 'Invalid date!'caso contrario, restituisce solo 1 tipo.
A1rPun,

3

Ho combinato i migliori risultati prestazionali che ho trovato in giro per verificare se un determinato oggetto:

Il risultato è il seguente:

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

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

2

L'oggetto Date su stringa è un modo più semplice e affidabile per rilevare se entrambi i campi sono validi. ad es. se si immette questo "-------" nel campo di immissione della data. Alcune delle risposte sopra non funzioneranno.

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

La risposta selezionata è eccellente e la sto usando anche io. Tuttavia, se stai cercando un modo per convalidare l'input della data dell'utente, dovresti essere consapevole che l'oggetto Date è molto persistente nel trasformare quelli che potrebbero sembrare argomenti di costruzione non validi in quelli validi. Il seguente codice di unit test illustra il punto:

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
function isValidDate(strDate) {
    var myDateStr= new Date(strDate);
    if( ! isNaN ( myDateStr.getMonth() ) ) {
       return true;
    }
    return false;
}

Chiamalo così

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

2

Una funzione pronta basata sulla risposta più votata:

  /**
   * 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

Soluzione semplice ed elegante:

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

fonti:

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

[2] Data errata visualizzata nella nuova data () in JavaScript


1
date.getDate() == daynon è sufficiente per determinare se la data è valida. Il formato della data originale restituirà una data non valida in alcune implementazioni indipendentemente dal fatto che la data sia valida o meno. Anche "1970-01-01 00:00" se analizzato correttamente restituirà false (ovvero Boolean(+new Date("1970-01-01"))restituisce false).
RobG

ATTENZIONE: Questo non funzionerà in Safari
Vigrant il

Funzionerà in Safari se usi il formato const date = new Date(year, month, day); Nota che il mese è 0 indicizzato in questo modo, quindi potresti doverne sottrarre uno per allinearlo correttamente.
Vigrant,

1

Penso che parte di questo sia un lungo processo. Possiamo abbreviarlo come mostrato di seguito:

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

3
La domanda chiedeva come trovare istanze Date non valide, non stringhe e inoltre: chi dice che una data non può essere delimitata da qualcosa di diverso da una barra?
Jon z il

1

Per i componenti basati su int 1 di una data:

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

test:

    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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.