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

我想说明 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进行了检查,这种行为符合标准,这正是我要寻找的。

答案

这是我的处理方式:

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

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

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

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

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

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

d instanceof Date && isFinite(d)

为了避免出现跨框架问题,可以将instanceof check 替换为

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

不需要像Borgar 的答案中那样调用getTime() ,因为isNaN()isFinite()都隐式转换为数字。

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

实作

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

检查有效日期的最短答案

if(!isNaN(date.getTime()))

您可以简单地使用moment.js

这是一个例子:

var m = moment('2015-11-32', 'YYYY-MM-DD');
m.isValid(); // false

文档中的验证部分非常清楚。

而且,以下分析标志会导致无效的日期:

  • overflow :日期字段的溢出,例如第 13 个月,该月的第 32 天(或非 years 年的 2 月 29 日),一年的第 367 天等。溢出包含无效索引。匹配 #invalidAt 的单位(请参见下文); -1 表示没有溢出。
  • invalidMonth :无效的月份名称,例如 moment('Marbruary','MMMM');。包含无效的月份字符串本身,否则为 null。
  • empty :一个不包含任何可解析内容的输入字符串,例如 moment('this is nosense');。布尔值。
  • 等等。

资料来源: http//momentjs.com/docs/

要提及的是,jQuery UI DatePicker 小部件具有非常好的日期验证器实用程序方法,该方法可检查格式和有效性(例如,不允许使用 01/33/2013 日期)。

即使您不想将页面上的 datepicker 小部件用作 UI 元素,也可以始终将其. js 库添加到页面中,然后调用 validateator 方法,将要验证的值传递到其中。为了使生活更加轻松,它使用字符串作为输入,而不是 JavaScript Date 对象。

请参阅: http//api.jqueryui.com/datepicker/

它没有作为方法列出,但作为实用程序函数存在。在页面上搜索 “parsedate”,您将找到:

$ .datepicker.parseDate(format,value,settings)- 从具有指定格式的字符串值中提取日期。

用法示例:

var stringval = '01/03/2012';
var testdate;

try {
  testdate = $.datepicker.parseDate('mm/dd/yy', stringval);
             // Notice 'yy' indicates a 4-digit year value
} catch (e)
{
 alert(stringval + ' is not valid.  Format must be MM/DD/YYYY ' +
       'and the date value must be valid for the calendar.';
}

(有关重新指定日期格式的更多信息,请参见http://api.jqueryui.com/datepicker/#utility-parseDate

在上述示例中,由于 “01/03/2012” 是指定格式的日历有效日期,因此您不会看到警报消息。但是,例如,如果使 “stringval” 等于 “13/04/2013”,则会收到警报消息,因为值 “13/04/2013” 不是日历有效的。

如果成功解析了传入的字符串值,则 “testdate” 的值将是表示传入字符串值的 Javascript Date 对象。如果没有,它将是不确定的。

我真的很喜欢 Christoph 的方法(但没有足够的声誉来表扬它)。对于我的使用,我知道我将始终有一个 Date 对象,因此我只是使用有效的()方法扩展了日期。

Date.prototype.valid = function() {
  return isFinite(this);
}

现在我可以编写它了,它比仅在代码中检查 isFinite 更具描述性...

d = new Date(userDate);
if (d.valid()) { /* do stuff */ }
// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());

我使用以下代码验证年份,月份和日期的值。

function createDate(year, month, _date) {
  var d = new Date(year, month, _date);
  if (d.getFullYear() != year 
    || d.getMonth() != month
    || d.getDate() != _date) {
    throw "invalid date";
  }
  return d;
}

有关详细信息,请参阅javascript 中的检查日期。