首页 文章

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

提问于
浏览
1157

我想告诉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实例并且能够检查/断言它是否's valid or not. Borgar'解决方案是这样做的,但我需要跨浏览器测试它 . 我也想知道是否有更优雅的方式 .

  • Ash让我觉得我的API根本没有接受 Date 实例,这最容易验证 .

  • Borgar建议测试 Date 实例,然后测试 Date 的时间值 . 如果日期无效,则时间值为 NaN . 我用ECMA-262检查了这个行为是在标准中,这正是我正在寻找的 .

30 回答

  • 12

    这里有太多复杂的答案,但一条简单的线就足够了(ES5):

    Date.prototype.isValid = function (d) { return !isNaN(Date.parse(d)) } ;
    

    甚至在ES6中:

    Date.prototype.isValid = d => !isNaN(Date.parse(d));
    
  • 91

    选择的答案非常好,我也在使用它 . 但是,如果您正在寻找一种验证用户日期输入的方法,您应该知道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());
    });
    
  • 948
    // check whether date is valid
    var t = new Date('2011-07-07T11:20:00.000+00:00x');
    valid = !isNaN(t.valueOf());
    
  • 2

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

    var timestamp = Date.parse('foo');
    
    if (isNaN(timestamp) == false) {
      var d = new Date(timestamp);
    }
    

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

  • 12

    上述解决方案都没有为我工作,但是工作是什么

    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何时将02/31/2012变为03/02/2012,它无效

  • 2

    对于日期的基于int 1的组件:

    var is_valid_date = function(year, month, day) {
        var d = new Date(year, month - 1, day);
        return d.getFullYear() === year && (d.getMonth() + 1) === month && d.getDate() === day
    };
    

    测试:

    is_valid_date(2013, 02, 28)
    &&  is_valid_date(2016, 02, 29)
    && !is_valid_date(2013, 02, 29)
    && !is_valid_date(0000, 00, 00)
    && !is_valid_date(2013, 14, 01)
    
  • 37

    我认为其中一些是漫长的过程 . 我们可以缩短它,如下所示:

    function isValidDate(dateString) {
            debugger;
            var dateStringSplit;
            var formatDate;
    
            if (dateString.length >= 8 && dateString.length<=10) {
                try {
                    dateStringSplit = dateString.split('/');
                    var date = new Date();
                    date.setYear(parseInt(dateStringSplit[2]), 10);
                    date.setMonth(parseInt(dateStringSplit[0], 10) - 1);
                    date.setDate(parseInt(dateStringSplit[1], 10));
    
                    if (date.getYear() == parseInt(dateStringSplit[2],10) && date.getMonth()+1 == parseInt(dateStringSplit[0],10) && date.getDate() == parseInt(dateStringSplit[1],10)) {
                        return true;
                    }
                    else {
                        return false;
                    }
    
                } catch (e) {
                    return false;
                }
            }
            return false;
        }
    
  • 2

    Date对象到字符串是更简单可靠的方法来检测两个字段是否都是有效日期 . 例如如果在日期输入字段中输入“-------” . 上面的一些答案是行不通的 .

    jQuery.validator.addMethod("greaterThan", 
    
        function(value, element, params) {
            var startDate = new Date($(params).val());
            var endDate = new Date(value);
    
            if(startDate.toString() === 'Invalid Date' || endDate.toString() === 'Invalid Date') {
                return false;
            } else {
                return endDate > startDate;
            }
        },'Must be greater than {0}.');
    
  • 5

    检查有效日期的最短答案

    if(!isNaN(date.getTime()))
    
  • 5
    function isValidDate(strDate) {
        var myDateStr= new Date(strDate);
        if( ! isNaN ( myDateStr.getMonth() ) ) {
           return true;
        }
        return false;
    }
    

    像这样称呼它

    isValidDate(""2015/5/2""); // => true
    isValidDate(""2015/5/2a""); // => false
    
  • 1

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

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

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

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

    你可以用这个scirpt检查txDate.value的有效格式 . 如果格式不正确,则Date obejct未实例化并返回null为dt .

    var dt = new Date(txtDate.value)
     if (isNaN(dt))
    

    正如@ MiF的建议那么简短

    if(isNaN(new Date(...)))
    
  • 2

    我写过这个函数 . 传递一个字符串参数,它将根据这种格式“dd / MM / yyyy”确定它是否是有效日期 .

    这是一个测试

    输入:“hahaha”,输出: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;
        }
    }
    
  • 2

    这是我将如何做到这一点:

    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
    }
    

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

    function isValidDate(d) {
      return d instanceof Date && !isNaN(d);
    }
    
  • 222

    在尝试验证日期(例如2/31/2012)时,这些答案都不适用于我(在Safari 6.0中测试),但是,当尝试任何大于31的日期时,它们工作正常 .

    所以我不得不蛮力一点 . 假设日期的格式为 mm/dd/yyyy . 我正在使用@broox答案:

    Date.prototype.valid = function() {
        return isFinite(this);
    }    
    
    function validStringDate(value){
        var d = new Date(value);
        return d.valid() && value.split('/')[0] == (d.getMonth()+1);
    }
    
    validStringDate("2/29/2012"); // true (leap year)
    validStringDate("2/29/2013"); // false
    validStringDate("2/30/2012"); // false
    
  • 1

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

    实施

    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
    
  • 59

    你可以简单地使用moment.js

    这是一个例子:

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

    文档中的validation section非常清楚 .

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

    • overflow :日期字段溢出,例如第13个月,第32个月(或非闰年2月29日),一年中第367天等 . 溢出包含指数无效单位匹配#invalidAt(见下文); -1表示没有溢出 .

    • invalidMonth :月份名称无效,例如片刻('Marbruary','MMMM');.包含无效的月份字符串本身,否则为null .

    • empty :包含无法解析的输入字符串,例如moment('this is nonsense');.布尔 .


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

  • 36

    对于Angular.js项目,您可以使用:

    angular.isDate(myDate);
    
  • 9

    想提一下,jQuery UI DatePicker小部件有一个非常好的日期验证器实用程序方法,它检查格式和有效性(例如,不允许01/33/2013日期) .

    即使您不想将页面上的datepicker小部件用作UI元素,也可以始终将其.js库添加到您的页面,然后调用验证器方法,将要验证的值传递给它 . 为了让生活更轻松,它需要一个字符串作为输入,而不是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对象 . 如果没有,它将是未定义的 .

  • 4

    受到Borgar方法的启发,我确保代码不仅验证了日期,而且实际上确保日期是真实日期,这意味着不允许日期为31/09/2011和29/02/2011 .

    function(dateStr) {
        s = dateStr.split('/');
        d = new Date(+s[2], s[1]-1, +s[0]);
        if (Object.prototype.toString.call(d) === "[object Date]") {
            if (!isNaN(d.getTime()) && d.getDate() == s[0] && 
                d.getMonth() == (s[1] - 1)) {
                return true;
            }
        }
        return "Invalid date!";
    }
    
  • 9

    好的解决方案包含在我的辅助函数库中,现在看起来像这样:

    Object.isDate = function(obj) {
    /// <summary>
    /// Determines if the passed object is an instance of Date.
    /// </summary>
    /// <param name="obj">The object to test.</param>
    
        return Object.prototype.toString.call(obj) === '[object Date]';
    }
    
    Object.isValidDate = function(obj) {
    /// <summary>
    /// Determines if the passed object is a Date object, containing an actual date.
    /// </summary>
    /// <param name="obj">The object to test.</param>
    
        return Object.isDate(obj) && !isNaN(obj.getTime());
    }
    
  • 1

    基于最高评级答案的准备功能:

    /**
       * Check if date exists and is valid.
       *
       * @param {String} dateString Date in YYYY-mm-dd format.
       */
      function isValidDate(dateString) {
      var isValid = false;
      var date;
    
      date =
        new Date(
          dateString);
    
      if (
        Object.prototype.toString.call(
          date) === "[object Date]") {
    
        if (isNaN(date.getTime())) {
    
          // Date is unreal.
    
        } else {
          // Date is real if month and day match each other in date and string (otherwise may be shifted):
          isValid =
            date.getUTCMonth() + 1 === dateString.split("-")[1] * 1 &&
            date.getUTCDate() === dateString.split("-")[2] * 1;
        }
      } else {
        // It's not a date.
      }
    
      return isValid;
    }
    
  • 15

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

    d instanceof Date && isFinite(d)
    

    为了避免跨框架问题,可以用 instanceof 替换

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

    不需要在Borgar's answer中调用 getTime() ,因为 isNaN()isFinite() 都隐式转换为数字 .

  • 23
    function isValidDate(date) {
      return !! (Object.prototype.toString.call(date) === "[object Date]" && +date);
    }
    
  • 3
    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;
    }
    
  • 1

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

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

    有关详细信息,请参阅Check date in javascript

  • 3

    我结合了我发现的最佳性能结果,检查一个给定的对象:

    结果如下:

    function isValidDate(input) {
      if(!(input && input.getTimezoneOffset && input.setUTCFullYear))
        return false;
    
      var time = input.getTime();
      return time === time;
    };
    
  • 70

    这对我有用

    new Date('foo') == 'Invalid Date'; //is true
    

    但是这没用

    new Date('foo') === 'Invalid Date'; //is false
    
  • 18

    一般来说,我会坚持使用浏览器堆栈中的日期植入 . 这意味着在此回复日期之前,在Chrome,Firefox和Safari中调用toDateString()时,您将始终获得"Invalid Date" .

    if(!Date.prototype.isValidDate){
      Date.prototype.isValidDate = function(){
        return this.toDateString().toLowerCase().lastIndexOf('invalid') == -1;
      };
    }
    

    我没有在IE中测试这个 .

  • 5

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

    getTime() 方法无效时返回不是数字 NaN

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

相关问题