在 JavaScript 中检测“无效日期”日期实例

IT技术 javascript date
2021-01-23 05:03:04

我想区分 JS 中的有效日期对象和无效日期对象,但无法弄清楚如何:

var d = new Date("foo");
console.log(d.toString()); // shows 'Invalid Date'
console.log(typeof d); // shows 'object'
console.log(d instanceof Date); // shows 'true'

编写isValidDate函数的任何想法

  • Ash 推荐Date.parse用于解析日期字符串,它提供了一种权威的方式来检查日期字符串是否有效。
  • 如果可能的话,我更希望我的 API 接受一个 Date 实例并能够检查/断言它是否有效。Borgar 的解决方案可以做到这一点,但我需要跨浏览器对其进行测试。我也想知道是否有更优雅的方式。
  • Ash 让我考虑根本不让我的 API 接受Date实例,这将最容易验证。
  • Borgar 建议先测试一个Date实例,然后再测试它Date的时间值。如果日期无效,则时间值为NaN我检查了ECMA-262并且这种行为符合标准,这正是我正在寻找的。
6个回答

这是我将如何做到的:

if (Object.prototype.toString.call(d) === "[object Date]") {
  // it is a date
  if (isNaN(d.getTime())) {  // d.valueOf() could also work
    // date is not valid
  } else {
    // date is valid
  }
} else {
  // not a date
}

更新 [2018-05-31]:如果您不关心来自其他 JS 上下文(外部窗口、框架或 iframe)的 Date 对象,则可能更喜欢这种更简单的形式:

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}
感谢您的回答,但我想强调@Borgar 和@blueprintChris 的评论:1例如,如果我解析数字,我仍然会得到一个有效日期,Mon Jan 01 2001 00:00:00该日期确实是一个日期,但是对于我的应用程序而言,它完全没用. 因此,至少在我的情况下需要更多的输入验证。这个答案验证了一个dateObject不是Date
2021-03-10 05:03:04
instanceof 跨帧中断。Duck-typing 也可以正常工作:validDate == d && d.getTime && !isNaN(d.getTime()); - 由于问题是针对一般效用函数,我更喜欢更严格。
2021-03-15 05:03:04
可以简化成这样: d instanceof Date && !isNaN(d.getTime())
2021-03-29 05:03:04
你甚至不需要d.getTimeisNan(d)
2021-03-31 05:03:04
@Borgar,刚刚找到我的答案:“在多帧 DOM 环境中编写脚本时会出现问题。简而言之,在一个 iframe 中创建的数组对象不与在另一个 iframe 中创建的数组共享 [[Prototype]] . 它们的构造函数是不同的对象,因此 instanceof 和构造函数检查都失败了。”
2021-04-06 05:03:04

而不是使用new Date()你应该使用:

var timestamp = Date.parse('foo');

if (isNaN(timestamp) == false) {
  var d = new Date(timestamp);
}

Date.parse()返回一个时间戳,一个整数,表示自 1970 年 1 月 1 日以来的毫秒数。NaN如果它无法解析提供的日期字符串,它将返回

失败 ... 检测所有数值
2021-03-12 05:03:04
-1 不知道为什么这有这么多票,Date.parse取决于实现,绝对不值得信任来解析一般日期字符串。在流行的浏览器中,没有一种格式可以正确解析,更不用说所有使用的格式了(尽管最终ES5 中指定的 ISO8601 格式应该没问题)。
2021-03-19 05:03:04
如果您使用 ,new Date('foo')那基本上与该Date.parse('foo')方法等效请参阅:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...所以@RobG 所说的,也适用于它。
2021-03-24 05:03:04
需要美国 MM/DD/YYYY 格式才能工作。Date.parse('24/12/2021')返回NaN
2021-04-06 05:03:04
这个测试在 Chrome 中会失败。例如,Chrome 中的 Date.parse('AAA-0001') 给了我一个数字。
2021-04-09 05:03:04

您可以检查的有效性Date对象d通过

d instanceof Date && isFinite(d)

为避免跨框架问题,可以将instanceof支票替换为

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

要在通话getTime()Borgar的回答是不必要的,因为isNaN()isFinite()两个隐式转换为数字。

对我来说,这里的第一种方法是最好的选择,尽管我不确定使用isFiniteover是否有任何现实世界的优势isNaN(两者都可以很好地使用Date(Infinity))。此外,如果你想要相反的条件,它会变得更简单:if (!(date instanceof Date) || isNaN(date)).
2021-03-14 05:03:04
在 chrome 中试试这个 - Object.prototype.toString.call(new Date("2013-07-09T19:07:9Z"))。它将返回“[对象日期]”。因此,根据您的说法,“2013-07-09T19:07:9Z”应该是一个有效日期。但事实并非如此。您可以再次在 chrome 中通过执行 var dateStr = new Date("2013-07-09T19:07:9Z"); 来验证它;dateStr 它将返回无效日期。
2021-03-17 05:03:04
@Tintin:这isFinite()就是 -toString.call()只是instanceof支票部分的替代品
2021-03-19 05:03:04
@kristianp 实际上它可能会,甚至可能是 ECMAScript 规范的一部分。但是,是的,它看起来很丑。
2021-03-29 05:03:04
与 '[object Date]' 比较是否适用于非英语浏览器?我对此表示怀疑。
2021-04-08 05:03:04

我的解决方案是简单地检查您是否获得了有效的日期对象:

执行

Date.prototype.isValid = function () {
    // An invalid date object returns NaN for getTime() and NaN is the only
    // object not strictly equal to itself.
    return this.getTime() === this.getTime();
};  

用法

var d = new Date("lol");

console.log(d.isValid()); // false

d = new Date("2012/09/11");

console.log(d.isValid()); // true
@Ali 这是一个有效的日期对象。 new Date("02-31-2000") // Thu Mar 02 2000 00:00:00 GMT+0000 (GMT Standard Time). 如果将字符串传递给日期构造函数,则必须传入标准化字符串以获得可靠结果。具体来说,“字符串应该采用 Date.parse() 方法识别的格式”。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-03-19 05:03:04
isNaN 是一种更明确的测试 NaN 的方法
2021-03-25 05:03:04
因为我尊重 underscore.js 这促使了一些研究。isNaN("a") === true, 而("a" !== "a") === false. 值得思考。+1
2021-03-30 05:03:04
然而,你总能发现人们编写自己的版本 :) documentcloud.github.com/underscore/docs/...
2021-04-05 05:03:04
我测试了我在这里找到的 3 个主要解决方案的性能。恭喜你,你是赢家!jsperf.com/detecting-an-invalid-date
2021-04-06 05:03:04

检查有效日期的最短答案

if(!isNaN(date.getTime()))
是的,就像 8 年前的其他答案一样。:P stackoverflow.com/a/1353945/2321042
2021-03-11 05:03:04
只要他们使用var date = new Date(str),那么这个答案将是最短和最合适的。
2021-03-16 05:03:04
没有按预期工作,我可以输入日期为 60/80/9000 并返回Thu Oct 30 9006 00:00:00 GMT+0000 (Greenwich Mean Time)为日期?
2021-03-21 05:03:04
唯一的问题是如果 date 不是 Date 类型;你得到一个 JS 错误。
2021-03-26 05:03:04
@Andrew 你需要创建日期对象,如果你已经有一个对象然后使用 date && !isNaN(date.getTime())
2021-03-26 05:03:04