Detectando uma data inválida Data em JavaScript




object title javascript (20)

Gostaria de dizer a diferença entre objetos de data válidos e inválidos no 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 função isValidDate ?

  • Ash recomendou Date.parse para analisar as strings de data, o que fornece uma maneira autoritativa de verificar se a string de data é válida.
  • O que eu preferiria, se possível, é que minha API aceitasse uma instância Date e pudesse verificar / confirmar se é válida ou não. A solução de Borgar faz isso, mas eu preciso testá-lo nos navegadores. Eu também me pergunto se há uma maneira mais elegante.
  • Ash me fez considerar não ter minhas instâncias de Date aceitação da API, isso seria mais fácil de validar.
  • Borgar sugeriu testar uma ocorrência de Date e depois testar o valor de tempo da Date . Se a data for inválida, o valor da hora será NaN . Eu verifiquei com o ECMA-262 e esse comportamento está no padrão, que é exatamente o que estou procurando.

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 é bem 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., contém o índice do inválido unidade para combinar #invalidAt (veja abaixo); -1 significa que não há estouro.
  • invalidMonth : um nome de mês inválido, como moment ('Marbruary', 'MMMM') ;. Contém a string de mês inválida em si ou, caso contrário, null.
  • empty : Uma string de entrada que contém nada analisável, como moment ('this is nonsense') ;. Boleano.
  • Etc.

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


A resposta selecionada é excelente e estou usando também. No entanto, se você estiver procurando uma maneira de validar a entrada de dados do usuário, deve estar ciente de que o objeto Date é muito persistente em transformar os argumentos que podem parecer inválidos em construídos em 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());
});

Boa solução! Incluído na minha biblioteca de funções auxiliares, agora se parece com isso:

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

Combinei os melhores resultados de desempenho que encontrei 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;
};

Eu acho que parte disso é um processo longo. Podemos cortar curto 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;
    }

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

aqui está um teste

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

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

entrada: "29/2/2001", saída: falsa.

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

Eu uso o seguinte código 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 a data de verificação em javascript


Geralmente eu ficaria com qualquer implantação de data na pilha do navegador. O que significa que você sempre obterá "Data Inválida" ao chamar toDateString () no Chrome, Firefox e Safari até a data desta resposta.

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

Eu não testei isso no IE embora.


Inspirado pela abordagem de Borgar, assegurei-me de que o código não apenas valida a data, mas realmente garante que a data seja uma data 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!";
}

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

Muitas respostas complicadas já estão aqui, 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));

Nenhuma das soluções acima funcionou para mim o que funcionou no entanto é

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 vai ver quando JS faz de 31/02/2012 em 03/02/2012 que não é válido


Objeto de data para string é uma maneira mais simples e confiável de detectar se ambos os campos são válidos. Por exemplo, se você inserir este "-------" no campo de entrada de data. Algumas das respostas acima não funcionam.

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

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)

Uma função pronta com base na resposta melhor classificada:

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

Você pode verificar a validade de um objeto Date d via

d instanceof Date && isFinite(d)

Para evitar problemas de cross-frame, pode-se substituir o instanceof verificação por

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

Uma chamada para getTime() como na resposta de Borgar é desnecessária, já que isNaN() e isFinite() implicitamente convertem para number.


menor resposta para verificar data válida

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

você pode converter sua data e hora em milissegundos getTime()

este método getTime() return Não é um número NaN quando não é válido

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

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

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




date