Detectando uma instância de Data de "data inválida" em JavaScript

1494

Gostaria de dizer a diferença entre objetos de data válidos e inválidos em JS, mas não consegui descobrir como:

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'

Alguma idéia para escrever uma isValidDatefunção?

  • Ash é recomendado Date.parsepara analisar cadeias de datas, o que fornece uma maneira autorizada de verificar se a cadeia de datas é válida.
  • O que eu preferiria, se possível, é fazer com que minha API aceite uma instância Date e seja capaz de verificar / afirmar se é válida ou não. A solução da Borgar faz isso, mas preciso testá-la nos navegadores. Também me pergunto se existe uma maneira mais elegante.
  • Ash me fez pensar em não ter minha API aceitar Dateinstâncias, isso seria mais fácil de validar.
  • Borgar sugeriu testes para uma Dateinstância e, em seguida, testes para o Datevalor de tempo do. Se a data for inválida, o valor da hora é NaN. Eu verifiquei com ECMA-262 e esse comportamento está no padrão, que é exatamente o que estou procurando.
orip
fonte
18
Você pode remover a instrução if, alterando o corpo da função para:return ( Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()) );
styfle
3
@ styfle - acho que é uma preferência de estilo: acho mais claro separar a verificação de tipo da lógica de igualdade.
orip 27/06
26
O discurso do @orip é exatamente o que é fortemente desencorajado em perguntas. Consulte os meta-tópicos relevantes para aprender a lógica por trás disso. Colocar uma resposta à própria pergunta na própria pergunta é contra a política do site. OTOH, agradecer pelas respostas e ter "EDITAR" na sua resposta é um fluff típico. Se você deseja que sua pergunta com melhor classificação o identifique como uma pessoa que não sabe o que é SO e como usá-lo e não deseja aprender isso - seja meu convidado.
14
@ orip: Não foi "perdido"; ainda está bagunçando o histórico de revisões da pergunta, se você quiser vê-lo novamente. Mas não pertence a uma pergunta. No 37k rep você deve saber isso.
Lightness Races in Orbit
6
Por favor, pare a guerra de edição. As edições desta questão são discutidas na meta . Por favor, não edite / role novamente esta postagem. Se você não concorda com as edições anteriores / retrocessos ou tem algum comentário a respeito, poste nesse meta thread e não aqui.
Lundin

Respostas:

1304

Aqui está como eu faria isso:

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
}

Atualização [31-05-2018] : se você não estiver preocupado com objetos Date de outros contextos JS (janelas, quadros ou iframes externos), este formato mais simples pode ser preferido:

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}
Borgar
fonte
21
instanceof quebra entre quadros. A digitação com patos também pode funcionar bem: validDate == d && d.getTime &&! IsNaN (d.getTime ()); - Como a pergunta é para uma função de utilidade geral, prefiro ser mais rigoroso.
Borgar
11
@Borgar, acabei de encontrar minha resposta: "Os problemas surgem quando se trata de scripts em ambientes DOM de vários quadros. Em poucas palavras, objetos Array criados em um iframe não compartilham [[Prototype]] com arrays criados em outro iframe. Seus construtores são objetos diferentes e, portanto, as verificações de instância e de construtor falham. "
Ash
64
você não precisa mesmo de d.getTimeapenasisNan(d)
TecHunter
8
Poderia ser simplificado assim:d instanceof Date && !isNaN(d.getTime())
Zorgatone 07/04
5
Obrigado pela resposta, mas gostaria de enfatizar os comentários @Borgar e @blueprintChris: se eu analisar o dígito, 1por exemplo, ainda teria uma data válida, resultando na Mon Jan 01 2001 00:00:00qual é realmente uma data, no entanto, para a finalidade do meu aplicativo, é completamente inútil . Portanto, há pelo menos mais alguma validação de entrada necessária no meu caso. Esta resposta valida um dateObjectnão a Date!
dnhyde
264

Em vez de usar, new Date()você deve usar:

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

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

Date.parse()retorna um registro de data e hora, um número inteiro que representa o número de milissegundos desde 01 / jan / 1970. Ele retornará NaNse não puder analisar a sequência de datas fornecida.

Cinza
fonte
119
-1 Não sei por que isso tem tantos votos positivos, Date.parsedepende da implementação e definitivamente não é confiável para analisar sequências de datas gerais. Não existe um formato único que seja analisado corretamente em navegadores populares, muito menos em todos os que estão em uso (embora, eventualmente, o formato ISO8601 especificado no ES5 esteja ok).
RobG
1
Se você usar o new Date('foo')que é basicamente equivalente ao Date.parse('foo')método. Veja: developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/… Então, o que o @RobG disse, também se aplica a ele.
golddragon007
2
Este teste falharia no Chrome. Por exemplo, Date.parse ('AAA-0001') no Chrome me fornece um número.
Nick
falhou ... detectar todos os valores numéricos
Hos Mercury
109

Você pode verificar a validade de um Dateobjeto dvia

d instanceof Date && isFinite(d)

Para evitar problemas de estrutura cruzada, pode-se substituir a instanceofverificação por

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

Uma chamada para getTime()como na resposta de Borgar é desnecessária isNaN()e isFinite()ambas implicitamente se convertem em número.

Christoph
fonte
Tente isso no chrome - Object.prototype.toString.call (new Date ("2013-07-09T19: 07: 9Z")). Ele retornará "[data do objeto]". De acordo com você, portanto, "2013-07-09T19: 07: 9Z" deve ser uma data válida. Mas não é. Você pode verificá-lo, novamente no chrome, executando var dateStr = new Date ("2013-07-09T19: 07: 9Z"); dateStr Ele retornará uma data inválida.
Tintin
2
@ Tintin: isFinite()é para isso - toString.call()é apenas um substituto para a instanceofparte do cheque #
Christoph
A comparação com '[Data do objeto]' funcionará com navegadores não ingleses? Eu duvido.
kristianp
2
@ kristianp na verdade provavelmente vai e provavelmente faz parte da especificação do ECMAScript. Mas, sim, parece feio.
binki
Para mim, a primeira abordagem aqui é a melhor opção, embora eu não tenha certeza se há alguma vantagem no mundo real de usar isFinitemais isNaN(ambas funcionam bem Date(Infinity)). Além disso, se você quiser a condição oposta, ele fica um pouco mais simples: if (!(date instanceof Date) || isNaN(date)).
Andrew
86

Minha solução é simplesmente verificar se você obtém um objeto de data válido:

Implementação

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
fonte
28
isNaNé uma forma mais explícita para testar NaN
orip
1
E, no entanto, você sempre encontra pessoas escrevendo suas próprias versões :) documentcloud.github.com/underscore/docs/…
Ash Clarke
4
como eu respeito o underscore.js, isso levou a algumas pesquisas. isNaN("a") === trueenquanto ("a" !== "a") === false. Vale a pena pensar. +1
orip
8
Testei o desempenho das três principais soluções que encontrei aqui. Parabéns, você é o vencedor! jsperf.com/detecting-an-invalid-date
zVictor
2
@ Ali Esse é um objeto de data válido. new Date("02-31-2000") // Thu Mar 02 2000 00:00:00 GMT+0000 (GMT Standard Time). Se você estiver passando uma sequência para o construtor de datas, deverá passar uma sequência padronizada para obter um resultado confiável. Especificamente, "A cadeia de caracteres deve estar em um formato reconhecido pelo método Date.parse ()". developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…
Ash Clarke
71

resposta mais curta para verificar a data válida

if(!isNaN(date.getTime()))
abhirathore2006
fonte
2
O único problema é se a data não for do tipo Data; você recebe um erro de JS.
Andrew
@ Andrew você precisa criar o objeto de data e se você já tem um objeto, em seguida, usardate && !isNaN(date.getTime())
abhirathore2006
Isso ainda gera um erro de JS se datenão for do tipo Data. Por exemplo: var date = 4; date && !isNaN(date.getTime());.
Andrew
@Andrew use date instanceof Date && !isNaN(date.getTime())
abhirathore2006
3
Certo, como as outras respostas de 8 anos atrás. : P stackoverflow.com/a/1353945/2321042
Andrew
45

Você pode simplesmente usar o moment.js

Aqui está um exemplo:

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

A seção de validação na documentação é bastante clara.

E também, os seguintes sinalizadores de análise resultam em uma data inválida:

  • overflow: Um estouro de um campo de data, como um 13º mês, um 32º dia do mês (ou um 29 de fevereiro em anos não bissextos), um 367º dia do ano etc. O excesso contém o índice da unidade inválida para combinar #invalidAt (veja abaixo); -1 significa que não há excesso.
  • invalidMonth: Um nome de mês inválido, como momento ('março', 'MMMM') ;. Contém a própria sequência de meses inválida ou nula.
  • empty: Uma sequência de entrada que não contém nada analisável, como moment ('this is absurdo') ;. Boleano.
  • Etc.

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

Yves M.
fonte
6
A melhor solução, extremamente fácil de implementar, funciona com qualquer formatação (meu caso é dd / MM / aaaa), também conhece os anos bissextos e não converte datas inválidas (por exemplo, 29/02/2015) em datas válidas por si só (por exemplo, 30/03/2015). Para verificar a data no FORMAD dd / mm / aaaa eu só tinha de usomoment("11/06/1986", "DD/MM/YYYY").isValid();
Rafael Merlin
3
Este uso do Moment foi descontinuado :(
James Sumners
2
Este uso não foi depreciado. O momento da chamada (entrada) sem uma sequência de formato é depreciado (a menos que a entrada esteja no formato ISO).
Chet
2
Este método pode ser extremamente lento ao processar muitas datas. Melhor usar uma regex nesses casos.
Grid Trekkor
2
O uso do moment.js pode ser simples, mas é uma sobrecarga enorme. Esta biblioteca é enorme. Eu voto negativo sua resposta.
Mick
38

Gostaria de mencionar que o widget DateQuicker da interface do usuário do jQuery possui um método utilitário de validador de data muito bom que verifica o formato e a validade (por exemplo, não são permitidas datas em 01/33/2013).

Mesmo se você não quiser usar o widget datepicker em sua página como um elemento da interface do usuário, sempre poderá adicionar sua biblioteca .js à sua página e chamar o método validador, passando o valor que deseja validar para ela. Para tornar a vida ainda mais fácil, é necessária uma string como entrada, não um objeto Data JavaScript.

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

Não está listado como um método, mas está lá - como uma função de utilitário. Pesquise na página por "analisado" e você encontrará:

$ .datepicker.parseDate (formato, valor, configurações) - Extrai uma data de um valor de sequência com um formato especificado.

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

(Mais informações sobre a especificação de formatos de data podem ser encontradas em http://api.jqueryui.com/datepicker/#utility-parseDate )

No exemplo acima, você não veria a mensagem de alerta, já que '01 / 03/2012 'é uma data válida do calendário no formato especificado. No entanto, se você criou 'stringval' igual a '13/04/04', por exemplo, você receberia a mensagem de alerta, pois o valor '13/04/04' não é válido para o calendário.

Se um valor de string passado for analisado com êxito, o valor de 'testdate' seria um objeto Data Javascript que representa o valor da sequência passada. Caso contrário, seria indefinido.

Matt Campbell
fonte
3
Voto positivo por ser a primeira resposta ao trabalhar com formatos de data que não sejam em inglês / local.
machado.
26

Eu realmente gostei da abordagem de Christoph (mas não tinha reputação suficiente para votar). Para meu uso, eu sei que sempre terei um objeto Date, então apenas estendi a data com um método válido ().

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

Agora eu posso escrever isso e é muito mais descritivo do que apenas verificar isFinite no código ...

d = new Date(userDate);
if (d.valid()) { /* do stuff */ }
broox
fonte
10
Estendendo o protótipo? Esse é um grande JavaScript, não, não!
Jasdeep Khalsa 8/15
Voto por causa do isFinitetrabalho para mim perfeitamente. Mas sim, não faz sentido estender o protótipo. !isFiniteem um Datevai pegar o fato de que Dateé Invalid Date. Também digno de nota, meu contexto está dentro do Node.
Staghouse 9/11/19
23
// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());
faridz
fonte
5
É o mesmo que @Borgar escreveu há 2 anos ... O que há de novo?
azulado
11
São duas linhas em vez de instruções if aninhadas feias.
Cypher
17

você pode verificar o formato válido de txDate.value com este escopo. se estiver em um formato incorreto, a data não será executada e retornará nulo para dt.

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

E como o @ MiF sugeriu de maneira curta

 if(isNaN(new Date(...)))
Yuseferi
fonte
isNaN (new Date (...)) - o método simples e curto
MiF
1
@MiF sim, eu atualizar a minha resposta com a sua sugestão;) graças
Yuseferi
16

Eu uso o código a seguir para validar valores para ano, mês 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;
}

Para detalhes, consulte Verificar data em javascript

Jingguo Yao
fonte
strnão está sendo usado.
samis 02/02
12

Muitas respostas complicadas aqui já, mas uma linha simples é suficiente (ES5):

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

ou mesmo no ES6:

Date.prototype.isValid = d => !isNaN(Date.parse(d));
Sebastien H.
fonte
1
Do MDN: "O método Date.parse () analisa uma representação de seqüência de caracteres de uma data e retorna o número de milissegundos desde 1 de janeiro de 1970, 00:00:00 UTC ou NaN ..." Portanto, execute uma data potencial por esse A função retorna um número inteiro ou NaN. A função isNaN () fornecerá um booleano limpo, informando se o valor original era um objeto de data válido ou não. Isso é suficiente para fazer uma verificação pontual, mas o exemplo acima anexa esse método ao objeto Date para tornar a funcionalidade facilmente disponível e legível em todo o programa.
Max Wilder
se d for booleano, você receberá 0 ou 1 que não é um Nan !!
davcup 26/03/19
@Davcup apenas testado usando Date.parse(true), eu recebo corretamente um NaN.
Sebastien H.
12

Vi algumas respostas que chegaram bem perto desse pequeno trecho.

Maneira JavaScript:

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

Maneira TypeScript:

const isValidDate = dateObject => new Date(dateObject ).toString() !== 'Invalid Date';
isValidDate(new Date('WTH'));
Jason Foglia
fonte
1
Não tenho certeza se estou faltando alguma coisa, mas não está fazendo novo Date () duas vezes inútil?
Jon Catmull
2
Este último não tem nada a ver com TypeScript. É perfeitamente válido JS.
hackel
9

Ótima solução! Incluído na minha biblioteca de funções auxiliares, agora fica assim:

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
fonte
9

Isso só funcionou para mim

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

No entanto, isso não funcionou

new Date('foo') === 'Invalid Date'; //is false
user1296274
fonte
5
Eu acredito que isso depende do navegador.
Barrypicker #
@barrypicker O que você quer dizer com isso depende do navegador?
Ajil O.
Você pode fazer: `${new Date('foo')}` === 'Invalid Date'
Daniele Vrut 23/01
9

Para projetos Angular.js, você pode usar:

angular.isDate(myDate);
Nick Taras
fonte
3
Isso retorna true para ao testar um objeto de data que foi inicializado com uma Data Inválida.
dchhetri 3/08/19
6

Nenhuma dessas respostas funcionou para mim (testada no Safari 6.0) ao tentar validar uma data como 31/2/2012, no entanto, elas funcionam bem ao tentar qualquer data maior que 31.

Então eu tive que usar força bruta um pouco. Supondo que a data esteja no formato mm/dd/yyyy. Estou usando a resposta @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
fonte
(new Date ('2/30/2014')). valid () retorna true
Andre Figueiredo
1
Já faz um tempo desde que eu respondi isso, mas você pode precisar de ambas as condições de retorno, incluindo as #&& value.split('/')[0] == (d.getMonth()+1);
Dex
O uso new Date('string date')é equivalente a Date.parse('string date'), consulte: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…, para que você possa obter valores falsos verdadeiros ou falsos.
golddragon007
5

Nenhuma das soluções acima funcionou para mim, mas o que funcionou é

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

o código acima verá quando JS faz 31/02/2012 em 02/02/2012 que não é válido

John
fonte
3
Ok, mas isso testa se uma string é uma data no formato M / D / Y, não "a diferença entre objetos de data válidos e inválidos". Não é realmente sobre o que se trata.
Borgar
a razão pela qual a sua verificado contra o formato é verificar se a data mudou depois que foi analisado
John
O OP não está solicitando um método para retornar um Booleano, não uma string formatada?
Barrypicker #
1
O código de amostra retorna um valor booleano, a formatação desempenha um papel importante no teste de alguns casos invá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
fonte
4

Eu escrevi essa função. Passe um parâmetro string e ele determinará se é uma data válida ou não com base neste formato "dd / MM / aaaa".

aqui está um teste

entrada: "hahaha", saída: false.

entrada: "29/2/2000", saída: true.

entrada: "29/2/2001", saída: 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;
    }
}
Yaseen
fonte
4

Date.prototype.toISOStringlança RangeError(pelo menos no Chromium e Firefox) em datas inválidas. Você pode usá-lo como um meio de validação e pode não ser necessário isValidDate(EAFP). Caso contrário, é:

function isValidDate(d)
{
  try
  {
    d.toISOString();
    return true;
  }
  catch(ex)
  {
    return false;    
  }    
}
saaj
fonte
1
Parece que é a única função que gera um erro pela definição do ECMA-262. 15.9.5.43 Date.prototype.toISOString () Esta função retorna um valor String que representa a instância no tempo representado por este objeto Date. O formato da String é o formato da string Date Time definido em 15.9.1.15. Todos os campos estão presentes na String. O fuso horário é sempre UTC, indicado pelo sufixo Z. Se o valor da hora desse objeto não for um Número finito, uma exceção RangeError será lançada.
Henry Liu
3

Inspirado pela abordagem de Borgar, assegurei-me de que o código não apenas validasse a data, mas também de que a data fosse real, o que significa que datas como 31/09/2011 e 29/02/2011 não são 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
fonte
Mas ... os métodos acima (@ Borgar's e os outros) já verificam esse tipo de validade ... Não consigo entender o problema.
azulado
O de Borgar não - veja seu próprio comentário à sua resposta.
EML
1
Esta solução só funciona quando o seu país usa a dd/MM/yyyynotação. Além disso, ele retorna truequando é válido e, 'Invalid date!'se não for, é melhor retornar apenas um tipo.
A1rPun
3

Combinei os melhores resultados de desempenho encontrados em torno dessa verificação se um determinado objeto:

O resultado é o seguinte:

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

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

O objeto Date para String é uma maneira mais simples e confiável de detectar se os dois campos são data válida. Por exemplo, se você digitar "-------" no campo de entrada da data. Algumas das respostas acima não funcionarão.

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
fonte
2

A resposta selecionada é excelente, e eu estou usando também. No entanto, se você estiver procurando uma maneira de validar a entrada de data do usuário, lembre-se de que o objeto Date é muito persistente ao transformar argumentos de construção inválidos em argumentos válidos. O seguinte código de teste de unidade ilustra o ponto:

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

Chame assim

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

Uma função pronta com base na resposta mais votada:

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

Solução simples e elegante:

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

fontes:

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

[2] Data incorreta mostrada na nova Data () em JavaScript

Soubriquet
fonte
1
date.getDate() == dayé insuficiente para determinar se a data é válida. O formato da data original retornará uma data inválida em algumas implementações, independentemente de a data ser válida ou não. Também "1970-01-01 00:00", se analisado corretamente, retornará falso (ou seja, Boolean(+new Date("1970-01-01"))retorna falso).
RobG 5/08/19
AVISO: Isso não funcionará no Safari
Vigrant
Ele funcionará no Safari se você usar o formato const date = new Date(year, month, day); Observe que o mês é 0 indexado dessa maneira, portanto, pode ser necessário subtrair um para alinhá-lo corretamente.
Vigrant 24/02
1

Eu acho que parte disso é um processo longo. Podemos abreviá-lo, como mostrado abaixo:

 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;
    }
user889209
fonte
3
A pergunta perguntou como encontrar instâncias inválidas de data, não seqüências de caracteres e além disso: quem disse que uma data não pode ser delimitada por algo que não seja uma barra?
Jon z
1

Para componentes baseados em int 1 de uma 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
};

Testes:

    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
fonte