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.
Solutions/Answers:
Solution 1:
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]'
Solution 2:
You can use the following code:
(myvar instanceof Date) // returns true or false
Solution 3:
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);
}
date
checks whether the parameter was not a falsy value (undefined
,null
,0
,""
, etc..)Object.prototype.toString.call(date)
returns a native string representation of the given object type – In our case"[object Date]"
. Becausedate.toString()
overrides its parent method, we need to.call
or.apply
the method fromObject.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
orDate.prototype.isPrototypeOf
.
!isNaN(date)
finally checks whether the value was not anInvalid Date
.
Solution 4:
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();
}
Solution 5:
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.
Solution 6:
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