我想知道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检查了一下,这种行为符合标准,这正是我所要的。


当前回答

您可以将日期和时间转换为毫秒getTime()

此getTime()方法在无效时返回Not a Number NaN

if(!isNaN(new Date("2012/25/255").getTime()))
  return 'valid date time';
  return 'Not a valid date time';

其他回答

在这么多人在我面前尝试之后,我为什么要写第48个答案?大多数答案部分正确,不会在任何情况下都有效,而其他答案则是不必要的冗长和复杂。下面是一个非常简洁的解决方案。这将检查它是否为日期类型,然后检查有效的日期对象:

return x instanceof Date && !!x.getDate();

现在来解析日期文本:大多数解决方案都使用date.parse()或“new date()”——这两种方法都会在某些情况下失败,而且可能很危险。JavaScript解析多种格式,并且依赖于本地化。例如,像“1”和“blah-123”这样的字符串将解析为有效日期。

还有一些帖子要么使用大量代码,要么使用一英里长的RegEx,要么使用第三方框架。

这是验证日期字符串的非常简单的方法。

函数isDate(txt){var matches=txt.match(/^\d?\d\/(\d?\d)\/\d{4}$/)//注:RegEx中的“日”用括号括起来回来匹配&&!!Date.parse(txt)&&newDate(txt).getDate()==匹配[1];}测试功能<br/><br/><input id=“dt”value=“12/21/2020”><input type=“button”value=“validate”id=“btnAction”onclick=“document.getElementById('slt').innerText=isDate(document.getElement ById('dt').value)”><br/><br/>结果:<span id=“rslt”></span>

isDate的第一行使用简单的RegEx解析输入文本,以验证日期格式mm/dd/yyyy或m/d/yyyy。对于其他格式,您需要相应地更改RegEx,例如,对于dd-mm-yyyy,RegEx变为/^(\d?\d)-\d?\d-\d{4}$/

如果解析失败,“matches”为空,否则将存储月份的日期。第二行进行了更多测试,以确保它是有效日期,并消除了类似2021 9月31日(JavaScript允许)的情况。最后请注意,double-back(!!)将“falsy”转换为布尔值false。

我已经编写了这个函数。给它传递一个字符串参数,它将根据格式“dd/MM/yyyy”确定它是否为有效日期。

这是一个测试

输入:“哈哈哈”,输出:false。

输入:“29/2/2000”,输出:true。

输入:“29/2/2001”,输出:false。

function isValidDate(str) {
    var parts = str.split('/');
    if (parts.length < 3)
        return false;
    else {
        var day = parseInt(parts[0]);
        var month = parseInt(parts[1]);
        var year = parseInt(parts[2]);
        if (isNaN(day) || isNaN(month) || isNaN(year)) {
            return false;
        }
        if (day < 1 || year < 1)
            return false;
        if(month>12||month<1)
            return false;
        if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day > 31)
            return false;
        if ((month == 4 || month == 6 || month == 9 || month == 11 ) && day > 30)
            return false;
        if (month == 2) {
            if (((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0 && (year % 100) == 0)) {
                if (day > 29)
                    return false;
            } else {
                if (day > 28)
                    return false;
            }      
        }
        return true;
    }
}

上述解决方案对我来说都不起作用,但起作用的是

function validDate (d) {
    var date = new Date(d);
    var day = "" + date.getDate();
    if ( day.length == 1 ) day = "0" + day;
    var month = "" + (date.getMonth() + 1);
    if ( month.length == 1 ) month = "0" + month;
    var year = "" + date.getFullYear();
    return (( month + "/" + day + "/" + year ) == d );
}

上面的代码将在JS将2012年2月31日更改为2012年3月2日时看到它是无效的

Date.valid = function(str){
  var d = new Date(str);
  return (Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()));
}

https://gist.github.com/dustinpoissant/b83750d8671f10c414b346b16e290ecf

选择的答案很好,我也在使用它。然而,如果您正在寻找一种验证用户日期输入的方法,您应该知道date对象非常持久地将看似无效的构造参数转换为有效的构造参数。以下单元测试代码说明了这一点:

QUnit.test( "valid date test", function( assert ) {
  //The following are counter-examples showing how the Date object will 
  //wrangle several 'bad' dates into a valid date anyway
  assert.equal(isValidDate(new Date(1980, 12, 15)), true);
  d = new Date();
  d.setFullYear(1980);
  d.setMonth(1);
  d.setDate(33);
  assert.equal(isValidDate(d), true);
  assert.equal(isValidDate(new Date(1980, 100, 150)), true);
  //If you go to this exterme, then the checker will fail
  assert.equal(isValidDate(new Date("This is junk")), false);
  //This is a valid date string
  assert.equal(isValidDate(new Date("November 17, 1989")), true);
  //but is this?
  assert.equal(isValidDate(new Date("November 35, 1989")), false);  
  //Ha!  It's not.  So, the secret to working with this version of 
  //isValidDate is to pass in dates as text strings... Hooboy
  //alert(d.toString());
});