Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check whether an object is a date?

I have an annoying bug in on a webpage:

date.GetMonth() is not a function

So, I suppose that I am doing something wrong. The variable date is not an object of type Date. How can I check for a datatype in Javascript? I tried to add a if (date), but it doesn't work.

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

So, if I want to write defensive code and prevent the date (which is not one) to be formatted, how do I do that?

Thanks!

UPDATE: I don't want to check the format of the date, but I want to be sure that the parameter passed to the method getFormatedDate() is of type Date.

like image 798
Martin Avatar asked Mar 13 '09 17:03

Martin


19 Answers

As an alternative to duck typing via

typeof date.getMonth === 'function'

you can use the instanceof operator, i.e. But it will return true for invalid dates too, e.g. new Date('random_string') is also instance of Date

date instanceof Date

This will fail if objects are passed across frame boundaries.

A work-around for this is to check the object's class via

Object.prototype.toString.call(date) === '[object Date]'
like image 173
Christoph Avatar answered Oct 05 '22 17:10

Christoph


You can use the following code:

(myvar instanceof Date) // returns true or false
like image 26
SF_dev Avatar answered Oct 05 '22 18:10

SF_dev


In order to check if the value is a valid type of the standard JS-date object, you can make use of this predicate:

function isValidDate(date) {
  return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date);
}
  1. date checks whether the parameter was not a falsy value (undefined, null, 0, "", etc..)
  2. Object.prototype.toString.call(date) returns a native string representation of the given object type - In our case "[object Date]". Because date.toString() overrides its parent method, we need to .call or .apply the method from Object.prototype directly which ..
    • Bypasses user-defined object type with the same constructor name (e.g.: "Date")
    • Works across different JS contexts (e.g. iframes) in contrast to instanceof or Date.prototype.isPrototypeOf.
  3. !isNaN(date) finally checks whether the value was not an Invalid Date.
like image 21
Boghyon Hoffmann Avatar answered Oct 05 '22 17:10

Boghyon Hoffmann


The function is getMonth(), not GetMonth().

Anyway, you can check if the object has a getMonth property by doing this. It doesn't necessarily mean the object is a Date, just any object which has a getMonth property.

if (date.getMonth) {
    var month = date.getMonth();
}
like image 28
Chetan S Avatar answered Oct 05 '22 19:10

Chetan S


As indicated above, it's probably easiest to just check if the function exists before using it. If you really care that it's a Date, and not just an object with a getMonth() function, try this:

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

This will create either a clone of the value if it's a Date, or create an invalid date. You can then check if the new date's value is invalid or not.

like image 24
bdukes Avatar answered Oct 05 '22 19:10

bdukes


This is a pretty simple approach if you're not concerned about iframes / other contexts.

// isNaN(Invalid Date) == true
if (date instanceof Date && !isNaN(date)) {
    console.log("is date!");
}
  • Checks if object is actually a Date and not something that looks like one. Any object could have a getMonth function.
  • Ensures the Date is not an Invalid Date
  • Doesn't pass a value into new Date() where a number or even a string could be turned into a Date.

If you need to support iframes and different contexts you can use the accepted answer but add an extra check to identify invalid dates.

// isNaN(Invalid Date) == true
if (Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date)) {
    console.log("is date!");
}

like image 40
Ryan King Avatar answered Oct 05 '22 17:10

Ryan King


For all types I cooked up an Object prototype function. It may be of use to you

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

Now you can check any type like this:

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

[Edit march 2013] based on progressing insight this is a better method:

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
like image 42
KooiInc Avatar answered Oct 05 '22 18:10

KooiInc


The best way I found is:

!isNaN(Date.parse("some date test"))
//
!isNaN(Date.parse("22/05/2001"))  // true
!isNaN(Date.parse("blabla"))  // false
like image 26
jspassov Avatar answered Oct 05 '22 19:10

jspassov


UnderscoreJS and Lodash have a function called .isDate() which appears to be exactly what you need. It's worth looking at their respective implementations: Lodash isDate, UnderscoreJs

like image 26
avalanche1 Avatar answered Oct 05 '22 18:10

avalanche1


Instead of all the workarounds you can use the following:

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

I found this hack better!

like image 24
itsHarshad Avatar answered Oct 05 '22 17:10

itsHarshad


I have been using a much simpler way but am not sure if this is only available in ES6 or not.

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"

However, this will not work on null or undefined since they have no constructor.

like image 21
mjwrazor Avatar answered Oct 05 '22 17:10

mjwrazor


arrow function

const isValidDate = (value: any) => value instanceof Date && !isNaN(value);

Function:

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}
like image 33
G Clovs Avatar answered Oct 05 '22 17:10

G Clovs


You could check if a function specific to the Date object exists:

function getFormatedDate(date) {
    if (date.getMonth) {
        var month = date.getMonth();
    }
}
like image 38
Powerlord Avatar answered Oct 05 '22 17:10

Powerlord


Also you can use short form

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

or something like this:

(toString.call(date)) == 'Date'
like image 40
pavlo Avatar answered Oct 05 '22 17:10

pavlo


This function will return true if it's Date or false otherwise:

function isDate(myDate) {
    return myDate.constructor.toString().indexOf("Date") > -1;
} 
like image 29
Jahid Avatar answered Oct 05 '22 17:10

Jahid


Yet another variant:

Date.prototype.isPrototypeOf(myDateObject)
like image 22
Vadim Avatar answered Oct 05 '22 17:10

Vadim


with the following approach, you can even check date no to be "Invalid Date"

if(!!date.getDate()){
    console.log('date is valid')
}
like image 24
Hossein Mousavi Avatar answered Oct 05 '22 18:10

Hossein Mousavi


An approach using a try/catch

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

console.log(getFormattedDate());
console.log(getFormattedDate('AAAA'));
console.log(getFormattedDate(new Date('AAAA')));
console.log(getFormattedDate(new Date(2018, 2, 10)));
like image 35
codeKonami Avatar answered Oct 05 '22 17:10

codeKonami


Simply use moment

import moment from 'moment';

moment(myvar).isValid(); //  return true or false
like image 38
Mego Elhawary Avatar answered Oct 05 '22 17:10

Mego Elhawary