Detectar una instancia de fecha de "fecha no válida" en JavaScript

1494

Me gustaría decir la diferencia entre objetos de fecha válidos e inválidos en JS, pero no pude entender cómo:

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'

¿Alguna idea para escribir una isValidDatefunción?

  • Ash se recomienda Date.parsepara analizar cadenas de fecha, lo que proporciona una forma autorizada de verificar si la cadena de fecha es válida.
  • Lo que preferiría, si es posible, es que mi API acepte una instancia de Date y pueda verificar / afirmar si es válida o no. La solución de Borgar hace eso, pero necesito probarlo en todos los navegadores. También me pregunto si hay una forma más elegante.
  • Ash me hizo considerar no tener mi API para aceptar Dateinstancias, esto sería más fácil de validar.
  • Borgar sugirió probar para una Dateinstancia, y luego probar el Datevalor de tiempo del 's. Si la fecha no es válida, el valor del tiempo es NaN. Verifiqué con ECMA-262 y este comportamiento está en el estándar, que es exactamente lo que estoy buscando.
orip
fuente
18
Puede eliminar la instrucción if cambiando el cuerpo de la función a:return ( Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()) );
styfle
3
@styfle: supongo que es una preferencia de estilo: me resulta más claro separar la verificación de tipo de la lógica de igualdad.
orip
26
El discurso de @orip es exactamente lo que se desaconseja en las preguntas. Consulte los metatemas relevantes para conocer la lógica detrás de esto. Colocar una respuesta a la propia pregunta en la pregunta misma va en contra de la política del sitio. OTOH, agradecer las respuestas y tener "EDITAR" en su respuesta es una pelusa típica. Si desea que su pregunta mejor calificada lo identifique como una persona que no sabe qué es SO y cómo usarlo, y no desea aprender eso, sea mi invitado.
14
@orip: No se "perdió"; todavía está abarrotando el historial de revisiones de la pregunta si desea volver a verla. Pero no pertenece a una pregunta. A 37k rep., Deberías saber esto.
ligereza corre en órbita el
66
Amablemente pare la guerra de edición. Las ediciones sobre esta pregunta se discuten en meta . Por favor, no edite / revierta esta publicación más. Si no está de acuerdo con ediciones / retrocesos anteriores o tiene algún comentario al respecto, publique en ese metahilo y no aquí.
Lundin

Respuestas:

1304

Así es como lo haría:

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
}

Actualización [2018-05-31] : si no le preocupan los objetos Date de otros contextos JS (ventanas externas, marcos o marcos flotantes), se puede preferir esta forma más simple:

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}
Borgar
fuente
21
La instancia de roturas a través de marcos. La escritura de pato también puede funcionar bien: validDate == d && d.getTime &&! IsNaN (d.getTime ()); - Dado que la pregunta es para una función de utilidad general, prefiero ser más estricto.
Borgar
11
@Borgar, acabo de encontrar mi respuesta: "Los problemas surgen cuando se trata de secuencias de comandos en entornos DOM de múltiples cuadros. En pocas palabras, los objetos de matriz creados dentro de un iframe no comparten [[Prototype]] 's con matrices creadas dentro de otro iframe "Sus constructores son objetos diferentes y, por lo tanto, fallan las instancias y las comprobaciones de constructor".
Ash el
64
ni siquiera necesita d.getTimesoloisNan(d)
TecHunter
8
Podría simplificarse así:d instanceof Date && !isNaN(d.getTime())
Zorgatone
55
Gracias por la respuesta, pero deseo enfatizar los comentarios de @Borgar y @blueprintChris: si analizo el dígito, 1por ejemplo, todavía tendría una fecha válida, Mon Jan 01 2001 00:00:00que de hecho es una fecha, sin embargo, para el propósito de mi aplicación, es completamente inútil . Por lo tanto, se necesita más validación de entrada en mi caso al menos. Esta respuesta valida un dateObjectno a Date!
dnhyde
264

En lugar de usar new Date(), debe usar:

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

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

Date.parse()devuelve una marca de tiempo, un número entero que representa el número de milisegundos desde el 01 / enero / 1970. Volverá NaNsi no puede analizar la cadena de fecha proporcionada.

Ceniza
fuente
119
-1 No sé por qué esto tiene tantos votos positivos, Date.parsedepende de la implementación y definitivamente no se debe confiar para analizar cadenas de fechas generales. No hay un formato único que se analice correctamente en los navegadores populares, y mucho menos todos los que están en uso (aunque eventualmente el formato ISO8601 especificado en ES5 debería estar bien).
RobG
1
Si usa el new Date('foo')que es básicamente equivalente con el Date.parse('foo')método. Ver: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Entonces, lo que dijo @RobG, también se aplica a él.
golddragon007
2
Esta prueba fallaría en Chrome. Por ejemplo, Date.parse ('AAA-0001') en Chrome me da un número.
Nick
falló ... detectar todos los valores numéricos
Hos Mercury
109

Puede verificar la validez de un Dateobjeto a dtravés de

d instanceof Date && isFinite(d)

Para evitar problemas de marcos cruzados, uno podría reemplazar el instanceofcheque con

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

Una llamada al getTime()igual que en la respuesta de Borgar es innecesario, ya que isNaN()y isFinite()tanto convertir implícitamente al número.

Christoph
fuente
Pruebe esto en Chrome: Object.prototype.toString.call (nueva fecha ("2013-07-09T19: 07: 9Z")). Devolverá "[fecha del objeto]". Según usted, por lo tanto, "2013-07-09T19: 07: 9Z", debe ser una fecha válida. Pero no lo es. Puede verificarlo, nuevamente en Chrome, haciendo var dateStr = new Date ("2013-07-09T19: 07: 9Z"); dateStr Devolverá una fecha no válida.
Tintin
2
@Tintin: para eso isFinite()está, toString.call()es solo un reemplazo para la instanceofparte del cheque
Christoph
¿La comparación con '[fecha del objeto]' funcionará con navegadores que no estén en inglés? Lo dudo.
Kristianp
2
@kristianp en realidad probablemente lo sea y probablemente sea incluso parte de la especificación ECMAScript. Pero sí, parece feo.
binki
Para mí, el primer enfoque aquí es la mejor opción, aunque no estoy seguro de si hay alguna ventaja en el mundo real de usar isFinitemás isNaN(ambos funcionan bien con Date(Infinity)). Por otra parte, si desea que la condición opuesta, se pone un poco más simple: if (!(date instanceof Date) || isNaN(date)).
Andrew
86

Mi solución es simplemente verificar si obtiene un objeto de fecha válido:

Implementación

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
Ash Clarke
fuente
28
isNaNes una forma más explícita de realizar pruebas de NaN
orip
1
Y sin embargo, siempre encuentras personas que escriben sus propias versiones :) documentcloud.github.com/underscore/docs/…
Ash Clarke
44
desde que respeto underscore.js esto provocó algunas investigaciones. isNaN("a") === true, mientras ("a" !== "a") === false. Vale la pena pensarlo. +1
orip
8
Probé el rendimiento de las 3 soluciones principales que he encontrado aquí. ¡Felicidades, eres el ganador! jsperf.com/detecting-an-invalid-date
zVictor
2
@ Ali Es un objeto de fecha válido. new Date("02-31-2000") // Thu Mar 02 2000 00:00:00 GMT+0000 (GMT Standard Time). Si está pasando una cadena al constructor de la fecha, debe pasar una cadena estandarizada para obtener un resultado confiable. Específicamente, "La cadena debe estar en un formato reconocido por el método Date.parse ()". developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ash Clarke
71

respuesta más corta para verificar la fecha válida

if(!isNaN(date.getTime()))
abhirathore2006
fuente
2
El único problema es si la fecha no es del tipo Fecha; obtienes un error JS.
Andrew
@Andrew necesita crear el Objeto de fecha y si ya tiene un objeto, usedate && !isNaN(date.getTime())
abhirathore2006
Eso todavía le da un error JS si dateno es del tipo Fecha. Por ejemplo: var date = 4; date && !isNaN(date.getTime());.
Andrew
@Andrew use date instanceof Date && !isNaN(date.getTime())
abhirathore2006
3
Correcto, como las otras respuestas de hace 8 años. : P stackoverflow.com/a/1353945/2321042
Andrew
45

Simplemente puede usar moment.js

Aquí hay un ejemplo:

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

La sección de validación en la documentación es bastante clara.

Y también, los siguientes indicadores de análisis dan como resultado una fecha no válida:

  • overflow: Un desbordamiento de un campo de fecha, como un 13º mes, un 32º día del mes (o un 29 de febrero en años no bisiestos), un 367º día del año, etc., el desbordamiento contiene el índice de la unidad no válida para que coincida con #invalidAt (ver más abajo); -1 significa que no hay desbordamiento.
  • invalidMonth: Un nombre de mes no válido, como momento ('marzo', 'MMMM') ;. Contiene la cadena de mes inválida o nula.
  • empty: Una cadena de entrada que no contiene nada analizable, como momento ('esto no tiene sentido') ;. Booleano
  • Etc.

Fuente: http://momentjs.com/docs/

Yves M.
fuente
66
La mejor solución, extremadamente fácil de implementar, funciona con cualquier formato (mi caso es dd / MM / aaaa), también conoce los años bisiestos y no convierte las fechas no válidas (es decir, 29/02/2015) en válidas por sí mismo (es decir 30/03/2015). Para verificar una fecha en el formato dd / MM / aaaa que solo tuve que usarmoment("11/06/1986", "DD/MM/YYYY").isValid();
Rafael Merlin
3
Este uso de Moment ha quedado en desuso :(
James Sumners
2
Este uso no ha sido depreciado. El momento de llamada (entrada) sin una cadena de formato se deprecia (a menos que la entrada tenga formato ISO).
Chet
2
Este método puede ser extremadamente lento cuando se procesan muchas fechas. Es mejor usar una expresión regular en esos casos.
Grid Trekkor
2
El uso de moment.js puede ser simple, pero es una sobrecarga enorme. Esta biblioteca es ENORME. Voté en contra de su respuesta.
Mick
38

Me gustaría mencionar que el widget jQuery UI DatePicker tiene un método de utilidad de validación de fecha muy bueno que verifica el formato y la validez (por ejemplo, no se permiten fechas 01/33/2013).

Incluso si no desea utilizar el widget de selector de fecha en su página como un elemento de la interfaz de usuario, siempre puede agregar su biblioteca .js a su página y luego llamar al método de validación, pasando el valor que desea validar en él. Para hacer la vida aún más fácil, se necesita una cadena como entrada, no un objeto Fecha de JavaScript.

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

No aparece en la lista como método, pero está allí, como una función de utilidad. Busque en la página "parsedate" y encontrará:

$ .datepicker.parseDate (formato, valor, configuración): extrae una fecha de un valor de cadena con un formato especificado.

Ejemplo de uso:

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

(Más información sobre cómo especificar formatos de fecha se encuentra en http://api.jqueryui.com/datepicker/#utility-parseDate )

En el ejemplo anterior, no vería el mensaje de alerta ya que '01 / 03/2012 'es una fecha válida de calendario en el formato especificado. Sin embargo, si hizo 'stringval' igual a '13 / 04/2013 ', por ejemplo, recibirá el mensaje de alerta, ya que el valor '13 / 04/2013' no es válido para el calendario.

Si un valor de cadena pasado se analiza correctamente, el valor de 'testdate' sería un objeto de Fecha Javascript que representa el valor de cadena pasado. Si no, sería indefinido.

Matt Campbell
fuente
3
Vota por ser la primera respuesta trabajando con formatos de fecha no ingleses / locales.
hacha
26

Realmente me gustó el enfoque de Christoph (pero no tenía suficiente reputación para votarlo). Para mi uso, sé que siempre tendré un objeto Date, así que simplemente extendí la fecha con un método válido ().

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

Ahora puedo escribir esto y es mucho más descriptivo que simplemente verificar isFinite en el código ...

d = new Date(userDate);
if (d.valid()) { /* do stuff */ }
broox
fuente
10
Extendiendo el prototipo? Eso es un gran JavaScript no no!
Jasdeep Khalsa
La votación por el isFinitetrabajo me funcionó perfectamente. Pero sí, no tiene sentido extender el prototipo. !isFiniteen una Datevoluntad captar el hecho de que Datees Invalid Date. También vale la pena señalar que mi contexto está dentro de Node.
Staghouse
23
// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());
faridz
fuente
55
Es lo mismo que escribió @Borgar hace 2 años ... ¿Qué hay de nuevo?
azulado
11
Son dos líneas en lugar de declaraciones if anidadas feas.
Cypher
17

Puede verificar el formato válido de txDate.value con este scirpt. si estaba en formato incorrecto, la fecha no obedece y devuelve nulo a dt.

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

Y como sugirió @ MiF en breve

 if(isNaN(new Date(...)))
Yuseferi
fuente
isNaN (nueva fecha (...)) - el método simple y corto
MiF
1
@MiF sí, actualizo mi respuesta con su sugerencia;) gracias
Yuseferi
16

Utilizo el siguiente código para validar valores para año, mes y fecha.

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

Para más detalles, consulte Comprobar fecha en javascript

Jingguo Yao
fuente
strNo se está utilizando.
samis
12

Demasiadas respuestas complicadas aquí ya, pero una línea simple es suficiente (ES5):

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

o incluso en ES6:

Date.prototype.isValid = d => !isNaN(Date.parse(d));
Sebastien H.
fuente
1
De MDN: "El método Date.parse () analiza una representación de cadena de una fecha y devuelve el número de milisegundos desde el 1 de enero de 1970, 00:00:00 UTC o NaN ..." Así que ejecuta una fecha potencial a través de este La función devuelve un número entero o NaN. Entonces la función isNaN () le dará un booleano limpio que le indicará si el valor original era un objeto de fecha válido o no. Esto es suficiente para hacer una comprobación puntual, pero el ejemplo anterior adjunta este método al objeto Fecha para que la funcionalidad esté fácilmente disponible y legible en todo el programa.
Max Wilder
¡Si d es booleano, recibirá 0 o 1 que no es un Nan!
Davcup
@davcup acaba de probar usando Date.parse(true), obtengo correctamente un NaN.
Sebastien H.
12

Vi algunas respuestas que se acercaron mucho a este pequeño fragmento.

Forma JavaScript:

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

Forma TypeScript:

const isValidDate = dateObject => new Date(dateObject ).toString() !== 'Invalid Date';
isValidDate(new Date('WTH'));
Jason Foglia
fuente
1
No estoy seguro de si me falta algo, pero ¿no está haciendo nueva fecha () dos veces sin sentido?
Jon Catmull
2
Este último no tiene nada que ver con TypeScript. Es perfectamente válido JS.
hackel
9

Buena solución! Incluido en mi biblioteca de funciones auxiliares, ahora se ve así:

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());
}
Dmytro Shevchenko
fuente
9

Esto solo funcionó para mí

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

Sin embargo esto no funcionó

new Date('foo') === 'Invalid Date'; //is false
usuario1296274
fuente
55
Creo que esto depende del navegador.
barrypicker
@barrypicker ¿Qué quieres decir con que esto depende del navegador?
Ajil O.
Puedes hacer: `${new Date('foo')}` === 'Invalid Date'
Daniele Vrut
9

Para proyectos de Angular.js puede usar:

angular.isDate(myDate);
Nick Taras
fuente
3
Esto devuelve verdadero para cuando se prueba un objeto de fecha que se ha inicializado con una Fecha no válida.
dchhetri
6

Ninguna de estas respuestas funcionó para mí (probada en Safari 6.0) al intentar validar una fecha como el 2/31/2012, sin embargo, funcionan bien al intentar cualquier fecha mayor que 31.

Así que tuve que forzar un poco la fuerza bruta. Asumiendo que la fecha está en el formato mm/dd/yyyy. Estoy usando la respuesta @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
Dex
fuente
(nueva Fecha ('30/02/2014')). valid () devuelve verdadero
Andre Figueiredo
1
Ha pasado un tiempo desde que respondí esto, pero es posible que necesite ambas condiciones de devolución, incluido el&& value.split('/')[0] == (d.getMonth()+1);
Dex
Usar new Date('string date')es equivalente a Date.parse('string date'), vea: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… para que pueda obtener valores falsos verdaderos o falsos.
golddragon007
5

Ninguna de las soluciones anteriores funcionó para mí, lo que sí funcionó es

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

el código anterior verá cuando JS convierte el 31/02/2012 en 02/03/2012 que no es válido

Juan
fuente
3
Ok, pero esto prueba si una cadena es una fecha en formato M / D / Y, no "la diferencia entre objetos de fecha válidos e inválidos". No se trata realmente de esto.
Borgar
la razón por la que se verifica contra el formato es para verificar si la fecha ha cambiado después de que se analizó
John
¿El OP no está pidiendo un método para devolver un booleano, no una cadena formateada?
barrypicker
1
El código de muestra devuelve un valor booleano, el formateo juega un papel en la prueba de algunos de los casos no válidos.
John
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;
}
Michael Goldshmidt
fuente
4

He escrito esta función. Páselo como un parámetro de cadena y determinará si es una fecha válida o no según este formato "dd / MM / aaaa".

aquí hay una prueba

entrada: "jajaja", salida: falso.

entrada: "29/2/2000", salida: verdadero.

entrada: "29/2/2001", salida: 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;
    }
}
Yaseen
fuente
4

Date.prototype.toISOStringtiradas RangeError(al menos en Chromium y Firefox) en fechas no válidas. Puede usarlo como un medio de validación y puede que no lo necesite isValidDatecomo tal (EAFP). De lo contrario es:

function isValidDate(d)
{
  try
  {
    d.toISOString();
    return true;
  }
  catch(ex)
  {
    return false;    
  }    
}
saaj
fuente
1
Parece que es la única función que arroja un error por definición ECMA-262. 15.9.5.43 Date.prototype.toISOString () Esta función devuelve un valor de cadena que representa la instancia en el tiempo representada por este objeto Date. El formato de la cadena es el formato de cadena de fecha y hora definido en 15.9.1.15. Todos los campos están presentes en la cadena. La zona horaria siempre es UTC, denotada por el sufijo Z. Si el valor de hora de este objeto no es un número finito, se genera una excepción RangeError.
Henry Liu
3

Inspirado por el enfoque de Borgar, me he asegurado de que el código no solo valide la fecha, sino que también se asegure de que la fecha sea una fecha real, lo que significa que fechas como 31/09/2011 y 29/02/2011 no están permitidas.

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!";
}
Raz
fuente
Pero ... los métodos anteriores (@ Borgar's y los demás) ya comprueban este tipo de validez ... No puedo entender el problema.
azulado el
Borgar's no ve su propio comentario a su respuesta.
EML
1
Esta solución solo funciona cuando su país utiliza la dd/MM/yyyynotación. Además, regresa truecuando es válido y, 'Invalid date!'si no lo es, mejor devuelve solo 1 tipo.
A1rPun
3

Combiné los mejores resultados de rendimiento que encontré alrededor de esa verificación si un objeto dado:

El resultado es el siguiente:

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

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

Date object to string es una forma más simple y confiable de detectar si ambos campos son fecha válida. por ejemplo, si ingresa este "-------" en el campo de entrada de fecha. Algunas de las respuestas anteriores no funcionarán.

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

La respuesta seleccionada es excelente, y la estoy usando también. Sin embargo, si está buscando una forma de validar la entrada de la fecha del usuario, debe tener en cuenta que el objeto Date es muy persistente para convertir los argumentos de construcción no válidos en válidos. El siguiente código de prueba de unidad ilustra el 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());
});
dolphus333
fuente
2
function isValidDate(strDate) {
    var myDateStr= new Date(strDate);
    if( ! isNaN ( myDateStr.getMonth() ) ) {
       return true;
    }
    return false;
}

Llámalo así

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

Una función lista basada en la respuesta mejor calificada:

  /**
   * 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;
}
Zon
fuente
2

Solución simple y elegante:

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

fuentes:

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

[2] Fecha incorrecta mostrada en la nueva Fecha () en JavaScript

Apodo
fuente
1
date.getDate() == dayes insuficiente para determinar si la fecha es válida. El formato de fecha original devolverá una fecha no válida en algunas implementaciones, independientemente de si la fecha es válida o no. También "1970-01-01 00:00" si se analiza correctamente devolverá falso (es decir, Boolean(+new Date("1970-01-01"))devuelve falso).
RobG
ADVERTENCIA: Esto no funcionará en Safari
Vigrant
Funcionará en Safari si usa el formato const date = new Date(year, month, day); Tenga en cuenta que el mes es 0 indexado de esta manera, por lo que es posible que deba restar uno para alinearlo correctamente.
Vigrant
1

Creo que algo de esto es un proceso largo. Podemos acortarlo como se muestra a continuación:

 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;
    }
usuario889209
fuente
3
La pregunta preguntaba cómo encontrar instancias de Fecha inválidas, no cadenas, y además: ¿quién dice que una fecha no puede ser delimitada por algo más que una barra diagonal?
Jon z
1

Para componentes basados ​​en int 1 de una fecha:

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

Pruebas:

    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)
Denis Ryzhkov
fuente