在JavaScript中检测“无效date”date实例

我想告诉JS有效和无效的date对象之间的区别,但不知道如何:

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来parsingdatestring,它提供了一个权威的方法来检查datestring是否有效。
  • 我更喜欢,如果可能的话,是让我的API接受一个Date实例,并能够检查/断言是否有效。 Borgar的解决scheme是这样做的,但是我需要在浏览器上testing它。 我也怀疑是否有更优雅的方式。
  • Ash让我觉得没有我的API接受Date实例,这将是最容易validation的。
  • Borgarbuild议testingDate实例,然后testingDate的时间值。 如果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 } 

而不是使用“新的date()”,你应该使用:

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

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

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

 d instanceof Date && isFinite(d) 

为了避免交叉框架问题,可以使用replace检查的instanceof

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

在Borgar的回答中调用getTime()是不必要的,因为isNaN()isFinite()都隐含地转换为数字。

我的解决scheme是简单地检查你是否得到一个有效的date对象:

履行

 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 

想要提到的是,jQuery UI DatePicker小部件有一个非常好的datevalidation器实用程序方法,检查格式和有效性(例如,不允许01/33/2013date)。

即使您不希望将页面上的dateselect器小部件用作UI元素,也可以随时将其.js库添加到页面中,然后调用validation器方法,将要validation的值传递给它。 为了让生活更简单,它将一个string作为input,而不是一个JavaScript Date对象。

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

它没有被列为一种方法,而是作为一种效用函数。 search“parsing”页面,你会发现:

$ .datepicker.parseDate(格式,值,设置) – 从指定格式的string值中提取date。

用法示例:

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

(有关指定date格式的更多信息,请参阅http://api.jqueryui.com/datepicker/#utility-parseDate

在上面的例子中,你看不到提示信息,因为'01 / 03/2012'是指定格式的日历有效date。 但是,例如,如果您将'stringval'等于'13 / 04/2013',那么您将收到警报消息,因为值“13/04/2013”​​不是日历有效的。

如果成功parsing了传入的string值,则“testdate”的值将是表示传入的string值的Javascript Date对象。 如果不是,它将是未定义的。

你可以简单地使用moment.js

这里是一个例子:

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

文档中的validation部分非常清晰。

而且,以下parsing标记导致无效的date:

  • overflow :date字段的溢出,例如13个月,该月的第32天(或非闰年的2月29日),一年的第367天等。溢出包含无效的索引单位匹配#invalidAt(见下文); -1意味着没有溢出。
  • invalidMonth :无效的月份名称,例如“Marmo”,“MMMM”等。 包含无效的月份string本身,否则为空。
  • empty :一个不包含任何可parsing的inputstring,如moment('this is nonsense');. 布尔。
  • 等等。

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

最短的答案来检查有效date

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

我真的很喜欢克里斯托夫的方法(但没有足够的声望来投票)。 对于我的使用,我知道我将始终有一个Date对象,所以我只是用有效的()方法延长date。

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

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

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

我使用下面的代码来validation年份,月份和date的值。

 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中的检查date

 // check whether date is valid var t = new Date('2011-07-07T11:20:00.000+00:00x'); valid = !isNaN(t.valueOf()); 

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

 angular.isDate(myDate); 

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

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

这只是为我工作

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

然而这并没有奏效

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

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

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

甚至在ES6中:

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

上述解决scheme都不是为我工作,但是工作是什么

 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日进入03/02/2012,它无效

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

尝试validationdate(例如2/31/2012)时,这些答案都不适用于我(在Safari 6.0中testing过),但是,尝试使用大于31的任何date时,它们都可以正常工作。

所以我不得不暴力一点。 假设date的格式是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 

我已经写了这个function。 传递一个string参数,并根据这个格式“dd / MM / yyyy”确定它是否是有效的date。

这里是一个testing

input:“hahaha”,输出:false。

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

input:“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; } } 

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

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

正如@ MiF的简短提示

  if(isNaN(new Date(...))) 

受到Borgar方法的启发,我确信代码不仅可以validationdate,而且可以确保date是真正的date,这意味着像2011年3月31日和2011年2月29日这样的date是不允许的。

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

date对象到string是更简单和可靠的方式来检测,如果两个字段是有效的date。 例如,如果您input这个“——-”dateinput字段。 上面的一些答案是行不通的。

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

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

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

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

选定的答案是非常好的,我也使用它。 但是,如果您正在寻找一种validation用户dateinput的方法,则应该意识到Date对象对于将看似无效的构造参数变为有效的参数非常持久。 以下unit testing代码说明了这一点:

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

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

  • 是一个Date实例( 在这里是基准 )
  • 有一个有效的date( 基准在这里 )

结果如下:

 function isValidDate(input) { if(!(input && input.getTimezoneOffset && input.setUTCFullYear)) return false; var time = input.getTime(); return time === time; }; 
 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 

我认为这是一个漫长的过程。 我们可以缩短它,如下所示:

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

一般来说,我会坚持什么植入在浏览器堆栈中。 这意味着从回复的date起,在Chrome,Firefox和Safari中调用toDateString()时,您将始终得到“无效date”。

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

虽然我没有在IE中testing。

 function isValidDate(date) { return !! (Object.prototype.toString.call(date) === "[object Date]" && +date); } 

isValidDate的这种风格使用处理闰年的正则expression式:

 function isValidDate(value) { return /((^(10|12|0?[13578])([/])(3[01]|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(11|0?[469])([/])(30|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(2[0-8]|1[0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(29)([/])([2468][048]00)$)|(^(0?2)([/])(29)([/])([3579][26]00)$)|(^(0?2)([/])(29)([/])([1][89][0][48])$)|(^(0?2)([/])(29)([/])([2-9][0-9][0][48])$)|(^(0?2)([/])(29)([/])([1][89][2468][048])$)|(^(0?2)([/])(29)([/])([2-9][0-9][2468][048])$)|(^(0?2)([/])(29)([/])([1][89][13579][26])$)|(^(0?2)([/])(29)([/])([2-9][0-9][13579][26])$))/.test(value) } 

基于最高评价答案的现成function:

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