¿Cómo verificar si un objeto es una fecha?

601

Tengo un error molesto en una página web:

date.GetMonth () no es una función

Entonces, supongo que estoy haciendo algo mal. La variable dateno es un objeto de tipo Date. ¿Cómo puedo verificar un tipo de datos en Javascript? Intenté agregar un if (date), pero no funciona.

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

Entonces, si quiero escribir código defensivo y evitar que se formatee la fecha (que no es una), ¿cómo hago eso?

¡Gracias!

ACTUALIZACIÓN: No quiero verificar el formato de la fecha, pero quiero estar seguro de que el parámetro pasado al método getFormatedDate()es de tipo Date.

Martín
fuente
En caso de que también deba validarse si la fecha no es Invalid Date: stackoverflow.com/a/44198641/5846045
Boghyon Hoffmann

Respuestas:

1110

Como alternativa al tipeo de pato a través de

typeof date.getMonth === 'function'

puede usar el instanceofoperador, es decir, pero también devolverá verdadero para fechas no válidas, por ejemplo, new Date('random_string')también es instancia de Fecha

date instanceof Date

Esto fallará si los objetos se pasan a través de los límites del marco.

Una solución para esto es verificar la clase del objeto a través de

Object.prototype.toString.call(date) === '[object Date]'
Christoph
fuente
29
Fuera de interés, ¿sabe la razón de este error al pasar los límites del marco?
Simon Lieschke
85
@Simon: los globales de JS son locales al objeto global actual (también conocido como windowo self); los diferentes marcos tienen sus propios objetos globales, y sus propiedades (es decir, globales) se refieren a objetos distintos: Dateen frame1 es un objeto de función diferente que Dateen frame2; lo mismo es cierto para Date.prototype, que es la razón de la instanceoffalla: Date.prototypedesde frame1 no es parte de la cadena de Dateinstancias prototipo desde frame2
Christoph
99
Christoph, ¿cómo llamas "marco"? IFRAME, cada cuadro en FRAMESET o algo más (quiero decir, específico de JS, no el HTML)?
Paul
12
new Date('something') instanceof DateVuelve trueen Chrome. Eso no funcionará entonces.
krillgar
12
Detectar un objeto de tipo Fecha (a diferencia de un Objeto simple o una cadena) y validar un objeto que espera que sea una Fecha son dos tareas diferentes. Hay una serie de situaciones en las que la entrada a su función podría ser uno de varios tipos de datos diferentes. En mi caso, puedo confiar en que cualquier objeto Date que obtenga sea válido (no proviene directamente de un cliente) Si la validación es una preocupación, aquí hay una publicación con varias opciones. stackoverflow.com/questions/1353684/…
Michael Blackburn
125

Puedes usar el siguiente código:

(myvar instanceof Date) // returns true or false
SF_dev
fuente
66
¿Por qué esta no es la respuesta aceptada o más votada? Simplemente verificar si la fecha tiene una propiedad .getMonth podría desencadenar un falso positivo.
doremi
24
La instancia de puede desencadenar falsos negativos, vea el comentario de Christoph a su propia respuesta.
Marco Mariani
2
@doremi Aquí hay una demostración del instanceofdesencadenante falso negativo: jsbin.com/vufufoq/edit?html,js,console
Boghyon Hoffmann
69

Para verificar si el valor es un tipo válido del objeto JS-date estándar, puede hacer uso de este predicado:

function isValidDate(date) {
  return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date);
}
  1. datecomprueba si el parámetro no era un valor Falsy ( undefined, null, 0, "", etc ..)
  2. Object.prototype.toString.call(date)devuelve una representación de cadena nativa del tipo de objeto dado: en nuestro caso "[object Date]". Debido a que date.toString()anula su método principal , necesitamos .callo .applyel método Object.prototypedirectamente desde el cual ...
  3. !isNaN(date)finalmente comprueba si el valor no era un Invalid Date.
Boghyon Hoffmann
fuente
1
Wow isNaNse puede usar para verificar a Date. Ese es un nivel de locura PHP.
Nick
@Nick a date es un número sin embargo.
Josías
@Josiah Bueno, seguro, eliminando toda contexto hay una marca de tiempo allí: typeof Date.now() === "number"pero: typeof new Date() === "object". Sin embargo, de manera más realista, una fecha es una hora y una ubicación en el espacio.
Nick
39

La función es getMonth(), no GetMonth().

De todos modos, puede verificar si el objeto tiene una propiedad getMonth haciendo esto. No significa necesariamente que el objeto sea una Fecha, solo cualquier objeto que tenga una propiedad getMonth.

if (date.getMonth) {
    var month = date.getMonth();
}
Chetan Sastry
fuente
3
Compruebe si es invocable:if (date.getMonth && typeof date.getMonth === "function") {...}
Aloso
20

Como se indicó anteriormente, probablemente sea más fácil verificar si la función existe antes de usarla. Si realmente te importa que sea un Date, y no solo un objeto con una getMonth()función, prueba esto:

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

Esto creará un clon del valor si es a Date, o creará una fecha no válida. Luego puede verificar si el valor de la nueva fecha no es válido o no.

bdukes
fuente
1
Esto funcionó para mí, gracias. Sin embargo, si pasa un solo dígito como 0 o 1, lo trata como una fecha válida ... ¿alguna idea?
Ricardo Sanchez
Así es, @RicardoSanchez. Probablemente quiera usar la respuesta aceptada ( Object.prototype.toString.call(value) === '[object Date]') si es posible obtendrá números. El método en esta respuesta realmente te dice si el valuees convertible a a Date.
bdukes
18

Para todos los tipos, preparé una función de prototipo de objeto. Puede ser de utilidad para usted

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

Ahora puede verificar cualquier tipo como este:

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

[ Editar marzo de 2013 ] basado en una visión progresiva, este es un mejor método:

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
/[a-z]/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
KooiInc
fuente
10

UnderscoreJS y Lodash tienen una función llamada .isDate()que parece ser exactamente lo que necesita. Vale la pena mirar sus respectivas implementaciones: Lodash isDate , UnderscoreJs

avalancha1
fuente
8

La mejor manera que encontré es:

!isNaN(Date.parse("some date test"))
//
!isNaN(Date.parse("22/05/2001"))  // true
!isNaN(Date.parse("blabla"))  // false
jspassov
fuente
Esto no funciona Su verdadera línea es falsa y la pregunta es sobre si un objeto es un objeto de fecha ...
Clint
1
La respuesta de @jspassov es más precisa si una cadena es una fecha o no. Que estaba buscando. ¡¡Gracias!!
Anant el
Esta es la mejor respuesta para simplemente verificar si una cadena es una fecha o no
James Gentes,
4

En lugar de todas las soluciones, puede usar lo siguiente:

dateVariable = new Date(date);
if (dateVariable == 'Invalid Date') console.log('Invalid Date!');

¡Encontré este truco mejor!

itsHarshad
fuente
3

Puede verificar si existe una función específica para el objeto Fecha:

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

También puedes usar forma corta

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

o algo como esto:

(toString.call(date)) == 'Date'
Pavlo
fuente
2

He estado usando una forma mucho más simple, pero no estoy seguro de si esto solo está disponible en ES6 o no.

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"

Sin embargo, esto no funcionará en nulo o indefinido ya que no tienen constructor.

mjwrazor
fuente
"Date"También se devuelve cualquier objeto personalizado con el nombre de constructor "Fecha", que es tan arriesgado como simplemente verificar si el parámetro tiene getMonthpropiedad.
Boghyon Hoffmann
2
@boghyon parece que quien crea un objeto con el nombre del constructor de una biblioteca estándar de JavaScript ya predefinida no está siguiendo las mejores prácticas en primer lugar. Eso sería como descargar lodash y luego crear su propio módulo lodash y esperar que las cosas funcionen.
mjwrazor
1

Esta función volverá truesi es Fecha o falseno:

function isDate(myDate) {
    return myDate.constructor.toString().indexOf("Date") > -1;
} 
Jahid
fuente
1
isDate(new (function AnythingButNotDate(){ })())regresatrue
Boghyon Hoffmann
1

Otra variante más:

Date.prototype.isPrototypeOf(myDateObject)
Vadim
fuente
Agradable y corto! Pero desafortunadamente, tiene el mismo problema queinstanceof .
Boghyon Hoffmann el
@BoghyonHoffmann en el caso de iFrame puede verse así: iWindow.Date.prototype.isPrototypeOf(iWindow.date); // true iWindow.date instanceof iWindow.Date; // true
Vadim
1

Un enfoque usando un try / catch

function getFormatedDate(date = new Date()) {
  try {
    date.toISOString();
  } catch (e) {
    date = new Date();
  }
  return date;
}

console.log(getFormatedDate());
console.log(getFormatedDate('AAAA'));
console.log(getFormatedDate(new Date('AAAA')));
console.log(getFormatedDate(new Date(2018, 2, 10)));

codeKonami
fuente
0

En realidad la fecha será de tipo Object. Pero puede verificar si el objeto tiene getMonthmétodo y si es invocable.

function getFormatedDate(date) {
    if (date && date.getMonth && date.getMonth.call) {
       var month = date.getMonth();
    }
}
vartec
fuente
2
La respuesta de Christoph es más precisa. ¡Tener una propiedad 'call' no significa necesariamente que sea una función!
Chetan Sastry
-1

También podemos validarlo con el siguiente código

var a = new Date();
a.constructor === Date
/*
true
*/

ingrese la descripción de la imagen aquí

Arun
fuente
El constructor de function Date() {/*...*/}es también Date. Es decir, simplemente comparar la función del constructor es demasiado propenso a errores, lo que a menudo resulta en falsos positivos.
Omita el
-1

Inspirada en esta respuesta , esta solución funciona en mi caso (necesitaba verificar si el valor recibido de la API es una fecha o no):

!isNaN(Date.parse(new Date(YourVariable)))

De esta manera, si se trata de una cadena aleatoria proveniente de un cliente o de cualquier otro objeto, puede averiguar si es un objeto tipo Fecha.

Mohammad Ganji
fuente
-2

¿No podrías simplemente usar

function getFormatedDate(date) {
    if (date.isValid()) {
       var month = date.GetMonth();
    }
}
Gruñón
fuente
1
No, solo el objeto de fecha tiene el isValidmétodo
nikk wong
2
@grumpy @nikkwong No y no. El objeto de fecha estándar no tiene isValid. Solo moment.js tiene esa API.
Boghyon Hoffmann