Como verificar se um object é uma data?

Eu tenho um bug irritante em uma página da Web:

date.GetMonth () não é uma function

Então, suponho que estou fazendo algo errado. A date variável não é um object do tipo Date . Como posso verificar um tipo de dados em JavaScript? Eu tentei adicionar um if (date) , mas não funciona.

 function getFormatedDate(date) { if (date) { var month = date.GetMonth(); } } 

Então, se eu quiser escrever código defensivo e impedir que a data (que não é uma) seja formatada, como faço isso?

Obrigado!

UPDATE: Eu não quero verificar o formato da data, mas eu quero ter certeza de que o parâmetro passado para o método getFormatedDate() é do tipo Date .

Como alternativa à tipagem de pato via

 typeof date.getMonth === 'function' 

você pode usar o operador instanceof , isto é, mas ele também retornará true para datas inválidas, por exemplo, new Date('random_string') também é instance of Date

 date instanceof Date 

Isso falhará se os objects forem passados ​​pelos limites do quadro.

Uma solução alternativa para isso é verificar a class do object via

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

Você pode usar o seguinte código:

 (myvar instanceof Date) // returns true or false 

A function é getMonth() , não GetMonth() .

De qualquer forma, você pode verificar se o object tem uma propriedade getMonth fazendo isso. Isso não significa necessariamente que o object seja uma Data, qualquer object que tenha uma propriedade getMonth.

 if (date.getMonth) { var month = date.getMonth(); } 

Para todos os tipos, criei uma function de protótipo de object. Pode ser útil para você

 Object.prototype.typof = function(chkType){ var inp = String(this.constructor), customObj = (inp.split(/\({1}/))[0].replace(/^\n/,'').substr(9), regularObj = Object.prototype.toString.apply(this), thisType = regularObj.toLowerCase() .match(new RegExp(customObj.toLowerCase())) ? regularObj : '[object '+customObj+']'; return chkType ? thisType.toLowerCase().match(chkType.toLowerCase()) ? true : false : thisType; } 

Agora você pode verificar qualquer tipo como este:

 var myDate = new Date().toString(), myRealDate = new Date(); if (myRealDate.typof('Date')) { /* do things */ } alert( myDate.typof() ); //=> String 

[ Editar março de 2013 ] com base no insight de progresso, esse é um método melhor:

 Object.prototype.is = function() { var test = arguments.length ? [].slice.call(arguments) : null ,self = this.constructor; return test ? !!(test.filter(function(a){return a === self}).length) : (this.constructor.name || (String(self).match ( /^function\s*([^\s(]+)/im) || [0,'ANONYMOUS_CONSTRUCTOR']) [1] ); } // usage var Some = function(){ /* ... */} ,Other = function(){ /* ... */} ,some = new Some; 2..is(String,Function,RegExp); //=> false 2..is(String,Function,Number,RegExp); //=> true 'hello'.is(String); //=> true 'hello'.is(); //-> String /[az]/i.is(); //-> RegExp some.is(); //=> 'ANONYMOUS_CONSTRUCTOR' some.is(Other); //=> false some.is(Some); //=> true // note: you can't use this for NaN (NaN === Number) (+'ab2').is(Number); //=> true 

Como indicado acima, é provavelmente mais fácil apenas verificar se a function existe antes de usá-la. Se você realmente se importa que seja uma Date , e não apenas um object com uma function getMonth() , tente isto:

 function isValidDate(value) { var dateWrapper = new Date(value); return !isNaN(dateWrapper.getDate()); } 

Isso criará um clone do valor se for uma Date ou criará uma data inválida. Você pode então verificar se o valor da nova data é inválido ou não.

Para verificar se o valor é um tipo válido do object data-padrão JS, você pode fazer uso deste predicado:

 function isValidDate(date) { return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date); } 
  1. date verifica se o parâmetro não é um valor falso ( undefined , null , 0 , "" , etc.)
  2. Object.prototype.toString.call(date) retorna uma representação de string nativa do tipo de object fornecido – Em nosso caso, "[object Date]" . Porque date.toString() sobrescreve seu método pai , nós precisamos .call ou .apply o método de Object.prototype diretamente qual ..
    • Ignora o tipo de object definido pelo usuário com o mesmo nome de construtor (por exemplo: “Data”)
    • Trabalha em diferentes contextos JS (por exemplo, iframes) em contraste com instanceof ou Date.prototype.isPrototypeOf .
  3. !isNaN(date) finalmente verifica se o valor não foi uma Invalid Date .

UnderscoreJS e Lodash têm uma function chamada .isDate() que parece ser exatamente o que você precisa. Vale a pena olhar para as respectivas implementações: Lodash isDate , UnderscoreJs

Você pode verificar se existe uma function específica para o object Date:

 function getFormatedDate(date) { if (date.getMonth) { var month = date.getMonth(); } } 

A melhor maneira que encontrei é:

 !isNaN(Date.parse("some date test")) // !isNaN(Date.parse("22/05/2001")) // true !isNaN(Date.parse("blabla")) // false 

Esta function retornará true se for Data ou false caso contrário:

 function isDate(myDate) { return myDate.constructor.toString().indexOf("Date") > -1; } 

Além disso, você pode usar o formulário curto

 function getClass(obj) { return {}.toString.call(obj).slice(8, -1); } alert( getClass(new Date) ); //Date 

ou algo parecido com isto:

 (toString.call(date)) == 'Date' 

Eu tenho usado uma maneira muito mais simples, mas não tenho certeza se isso está disponível apenas no ES6 ou não.

 let a = {name: "a", age: 1, date: new Date("1/2/2017"), arr: [], obj: {} }; console.log(a.name.constructor.name); // "String" console.log(a.age.constructor.name); // "Number" console.log(a.date.constructor.name); // "Date" console.log(a.arr.constructor.name); // "Array" console.log(a.obj.constructor.name); // "Object" 

No entanto, isso não funcionará em null ou indefinido, pois eles não possuem um construtor.

Na verdade, a data será do tipo Object . Mas você pode verificar se o object tem o método getMonth e se ele pode ser chamado.

 function getFormatedDate(date) { if (date && date.getMonth && date.getMonth.call) { var month = date.getMonth(); } } 

Ainda outra variante:

 Date.prototype.isPrototypeOf(myDateObject) 

Você não poderia simplesmente usar

 function getFormatedDate(date) { if (date.isValid()) { var month = date.GetMonth(); } }