如何检查对象是否为日期?


600

我在网页上有一个烦人的错误:

date.GetMonth()不是函数

因此,我想我做错了什么。变量date不是type的对象Date如何检查Javascript中的数据类型?我尝试添加if (date),但无效。

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

因此,如果我想编写防御性代码并阻止格式化日期(不是一个日期),该怎么做?

谢谢!

更新:我不想检查日期的格式,但是我想确保传递给方法的参数getFormatedDate()是type Date


如果还应该验证日期是否不是一个有效的日期Invalid Datestackoverflow.com/a/44198641/5846045
Boghyon Hoffmann

Answers:


1108

作为通过鸭子输入的替代方法

typeof date.getMonth === 'function'

您可以使用instanceof运算符,即,但是对于无效日期也将返回true,例如new Date('random_string'),也是Date的实例

date instanceof Date

如果对象跨越帧边界传递,则将失败。

一种解决方法是通过检查对象的类

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

28
出于兴趣,您知道通过帧边界时失败的原因吗?
西蒙·里希克

85
@Simon:JS全局变量在当前全局对象(aka windowself)中是局部的;不同的框架具有自己的全局对象,并且它们的属性(即全局变量)引用不同的对象:Dateframe1中的功能对象不同于frame2中的功能对象Date;也是这样Date.prototype,这是instanceof失败的原因:Date.prototypefrom frame1不属于Dateframe2实例的原型链的一部分
Christoph 2010年

9
克里斯托夫,您怎么称呼“框架”?IFRAME,FRAMESET中的每个框架或其他内容(我的意思是JS特定而不是HTML内容)?
保罗

12
new Date('something') instanceof Datetrue在Chrome中返回。那将行不通。
krillgar

12
检测日期类型的对象(与普通对象或字符串相对)并验证您希望成为日期的对象是两个不同的任务。在许多情况下,函数的输入可能是许多不同数据类型之一。就我而言,我可以相信我得到的任何Date对象都是有效的(它不是直接来自客户端)。如果验证是一个问题,这里有很多选项。stackoverflow.com/questions/1353684/...
迈克尔·布莱克本

125

您可以使用以下代码:

(myvar instanceof Date) // returns true or false

6
为什么这不是公认的或更受欢迎的答案?只需检查日期是否具有.getMonth属性,即可触发误报。
doremi

24
instanceof可以触发错误否定,请参阅Christoph对自己答案的评论。
Marco Mariani

2
@doremi这是instanceof触发错误否定的演示:jsbin.com/vufufoq/edit?html
js,

67

为了检查该值是否是标准JS-date对象的有效类型,可以使用以下谓词:

function isValidDate(date) {
  return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date);
}
  1. date检查参数是否不是falsy值undefinednull0""等。)
  2. Object.prototype.toString.call(date)返回给定对象类型的本机字符串表示形式-在我们的例子中"[object Date]"。由于date.toString()它的父类的方法覆盖,我们需要.call.apply从方法Object.prototype直接从..。
  3. !isNaN(date)最后检查该值是否不是Invalid Date

1
isNaN可以用来检查Date。那就是PHP的等级限制。
尼克,

@尼克日期是一个数字。
约西亚

@Josiah好吧,当然,除去所有上下文,那里有一个时间戳:typeof Date.now() === "number",但是:typeof new Date() === "object"。但是,更现实的是,日期是时间和空间中的位置。
尼克

39

该功能getMonth()不是GetMonth()

无论如何,您可以通过执行此操作来检查对象是否具有getMonth属性。它不一定表示该对象是Date,而是任何具有getMonth属性的对象。

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

3
检查是否可调用:if (date.getMonth && typeof date.getMonth === "function") {...}
Aloso '16

20

如上所述,最简单的方法是在使用该功能之前先检查该功能是否存在。如果您真的关心它是一个Date,而不仅仅是具有getMonth()函数的对象,请尝试以下操作:

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

这将创建值的克隆(如果是)Date,或者创建无效的日期。然后,您可以检查新日期的值是否无效。


1
这对我有用,谢谢。但是,如果您传递一个数字(例如0或1),它将视为有效的日期...有什么想法吗?
里卡多·桑切斯2015年

是的,@ RicardoSanchez。Object.prototype.toString.call(value) === '[object Date]'如果可能会得到数字,您可能想使用接受的答案()。此答案中的方法确实告诉您能否将value转换为Date
bdukes

18

对于所有类型,我都编写了对象原型函数。它可能对您有用

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

现在,您可以检查以下任何类型:

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

[ 2013年3月编辑 ]基于不断发展的洞察力,这是一种更好的方法:

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


8

我发现的最好方法是:

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

这行不通。您的真实说法实际上是错误的,问题是关于检查某个对象是否为日期对象...
Clint

1
如果字符串是日期,则@jspassov答案更准确。我一直在寻找。谢谢!!
Anant,2016年

这是仅检查字符串是否为日期的最佳答案
James Gentes

3

您可以检查是否存在特定于Date对象的函数:

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

3

除了所有替代方法,您可以使用以下方法:

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

我发现这个技巧更好!


2

您也可以使用简写形式

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

或类似这样的东西:

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

2

我一直在使用一种简单得多的方法,但是不确定这是否仅在ES6中可用。

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"

但是,这对null或undefined无效,因为它们没有构造函数。


任何带有构造函数名称“ Date”的定制对象"Date"也会返回,这与检查参数是否具有getMonth属性一样危险。
Boghyon Hoffmann

2
@boghyon听起来像是用已定义的Javascript标准库的构造函数名称创建对象的人首先都不遵循最佳实践。这就像下载lodash然后创建自己的lodash模块并期望一切正常。
mjwrazor

1

true如果是日期,则返回此函数false

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

1
isDate(new (function AnythingButNotDate(){ })())返回true
Boghyon Hoffmann '18

1

另一个变体:

Date.prototype.isPrototypeOf(myDateObject)

好又短!但不幸的是,它具有与相同的问题instanceof
Boghyon Hoffmann '18

@BoghyonHoffmann在iFrame的情况下可能看起来像:iWindow.Date.prototype.isPrototypeOf(iWindow.date); // true iWindow.date instanceof iWindow.Date; // true
Vadim

1

一种使用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)));


0

实际上,日期将是类型Object。但是您可以检查对象是否具有getMonth方法以及是否可调用。

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

2
Christoph的答案更为准确。拥有“通话”属性并不一定意味着它是一个功能!
Chetan Sastry


-1

受此答案启发,此解决方案适用于我的情况(我需要检查从API接收的值是否为日期):

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

这样,如果它是来自客户端或其他任何对象的随机字符串,则可以找出它是否是类似Date的对象。


-2

你不能只用

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

1
不,只有日期对象具有isValid方法
nikk wong

2
@grumpy @nikkwong不,不。标准日期对象没有isValid。只有moment.js具有这样的API。
Boghyon Hoffmann
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.