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


当前回答

IsValidDate: function(date) {
        var regex = /\d{1,2}\/\d{1,2}\/\d{4}/;
        if (!regex.test(date)) return false;
        var day = Number(date.split("/")[1]);
        date = new Date(date);
        if (date && date.getDate() != day) return false;
        return true;
}

其他回答

在这么多人在我面前尝试之后,我为什么要写第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。

这里只有少数人(@Zen、@Dex、@wanglab……)对javascript容忍在2月、4月、6月等月份溢出日数。。。

如果指定要处理的格式(即yyyy-MM-dd),则在解决方案中根本不必使用javascript对象Date。

函数leapYear(年){return((年%4==0)&&(年%100!=0))||(年%400==0);}函数validateStr(dateStr){if(/^[0-9][0-9][0-9][0-9][0-9]-[0-9][9-9]-[0-9][0-9][0-9]$/.test(dateStr)==false){return false;}var m=parseInt(dateStr.substr(5,2));var d=parseInt(dateStr.substr(8,2));var y=parseInt(dateStr.substr(0,4));//您可以为大于5000:-D的值添加年度检查如果(m>12||d>31){return false;}否则,如果(m==2&&d>28){如果(d==29){if(!leapYear(y)){return false;}}其他{return false;}}否则如果(d>30&&(m==4||m==6||m==9||m===11)){return false;}返回true;}console.log(“2020-02-29:”+validateDateStr(“2020:02-29”));//真的console.log(“2020-02-30:”+validateDateStr(“2020:02-30”));//假的console.log(“2022-02-29:”+validateDateStr(“20202-02-29”));//假的console.log(“2021-02-28:”+validateDateStr(“2011-02-28”));//真的console.log(“2020-03-31:”+validateDateStr(“2020:03-31”));//真的console.log(“2020-04-30:”+validateDateStr(“2020:04-30”));//真的console.log(“2020-04-31:”+validateDateStr(“2020:04-31”));//假的console.log(“2020-07-31:”+validateDateStr(“2020:07-31”));//真的console.log(“2020-07-32:”+validateDateStr(“2020:07-32”));//假的控制台日志(“2020-08-31:”+validateDateStr(“2020:08-31”));//真的console.log(“2020-12-03:”+validateDateStr(“2020-102-03”));//真的console.log(“2020-13-03:”+validateDateStr(“2020-103-03”));//假的console.log(“0020-12-03:”+validateDateStr(“0020-102-03”));//真的//无效正则表达式console.log(“20-12-03:”+validateDateStr(“20-12-103”));//假的console.log(“2020-012-03:”+validateDateStr(“2020:012-03”));//假的console.log(“2020-12-003:”+validateDateStr(“2020-102-003”));//假的

我真的很喜欢克里斯托夫的方法(但没有足够的声誉来投票支持)。对于我的用途,我知道我将始终有一个Date对象,所以我只是用valid()方法扩展了日期。

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

现在我可以写这个了,它比在代码中检查isFinite更具描述性。。。

d = new Date(userDate);
if (d.valid()) { /* do stuff */ }

所以我喜欢@Ask Clarke的回答,通过为无法通过var d=new Date(d)的日期添加try-catch块,几乎没有什么改进-

function checkIfDateNotValid(d) {
        try{
            var d = new Date(d);
            return !(d.getTime() === d.getTime()); //NAN is the only type which is not equal to itself.
        }catch (e){
            return true;
        }

    }

在阅读了迄今为止的所有答案后,我将提供最简单的答案。

这里的每个解决方案都提到调用date.getTime()。然而,这是不需要的,因为从date到Number的默认转换是使用getTime()值。是的,你的打字检查会有问题OP明确知道他们有一个Date对象,所以也不需要测试。

要测试无效日期:

isNaN(date)

要测试有效日期:

!isNaN(date)

或(感谢icc97提供此选项)

isFinite(date) 

或打字稿(感谢pat migliaccio)

isFinite(+date)