我想知道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)) { // d.getTime() or d.valueOf() will also work
// date object is not valid
} else {
// date object is valid
}
} else {
// not a date object
}
更新〔2018-05-31〕:如果您不关心来自其他JS上下文(外部窗口、框架或iframe)的Date对象,则可以使用更简单的形式:
function isValidDate(d) {
return d instanceof Date && !isNaN(d);
}
更新[2021-02-01]:请注意,“无效日期”(2013-13-32)和“无效日期对象”(new date('fo'))之间存在根本区别。只有当date实例有效时,此答案才处理验证日期输入。
我认为这是一个漫长的过程。我们可以简化如下:
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;
}
我想提到的是,jQueryUIDatePicker小部件有一个非常好的日期验证器实用程序方法,可以检查格式和有效性(例如,不允许2013年1月33日的日期)。
即使您不想将页面上的datepicker小部件用作UI元素,也可以始终将其.js库添加到页面中,然后调用验证器方法,将要验证的值传递给它。
参见:http://api.jqueryui.com/datepicker/
它没有被列为一种方法,但它是作为一种实用函数存在的。在页面中搜索“parsedate”,您会发现:
$.datepicker.parseDate(格式、值、设置)-从具有指定格式的字符串值中提取日期。
示例用法:
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/13”不是日历有效值。
如果成功解析了传入的字符串值,“testdate”的值将是表示传入字符串值的Javascript 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}.');
对于日期的基于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)
选择的答案很好,我也在使用它。然而,如果您正在寻找一种验证用户日期输入的方法,您应该知道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());
});
此函数以字符分隔的数字格式验证字符串日期,例如dd/mm/yyyy、mm/dd/yyyy
/*
Param :
1)the date in string data type
2)[optional - string - default is "/"] the date delimiter, most likely "/" or "-"
3)[optional - int - default is 0] the position of the day component when the date string is broken up via the String.split function (into arrays)
4)[optional - int - default is 1] the position of the month component when the date string is broken up via the String.split function (into arrays)
5)[optional - int - default is 2] the position of the year component when the date string is broken up via the String.split function (into arrays)
Return : a javascript date is returned if the params are OK else null
*/
function IsValidDate(strDate, strDelimiter, iDayPosInArray, iMonthPosInArray, iYearPosInArray) {
var strDateArr; //a string array to hold constituents day, month, and year components
var dtDate; //our internal converted date
var iDay, iMonth, iYear;
//sanity check
//no integer checks are performed on day, month, and year tokens as parsing them below will result in NaN if they're invalid
if (null == strDate || typeof strDate != "string")
return null;
//defaults
strDelimiter = strDelimiter || "/";
iDayPosInArray = undefined == iDayPosInArray ? 0 : iDayPosInArray;
iMonthPosInArray = undefined == iMonthPosInArray ? 1 : iMonthPosInArray;
iYearPosInArray = undefined == iYearPosInArray ? 2 : iYearPosInArray;
strDateArr = strDate.split(strDelimiter);
iDay = parseInt(strDateArr[iDayPosInArray],10);
iMonth = parseInt(strDateArr[iMonthPosInArray],10) - 1; // Note: months are 0-based
iYear = parseInt(strDateArr[iYearPosInArray],10);
dtDate = new Date(
iYear,
iMonth, // Note: months are 0-based
iDay);
return (!isNaN(dtDate) && dtDate.getFullYear() == iYear && dtDate.getMonth() == iMonth && dtDate.getDate() == iDay) ? dtDate : null; // Note: months are 0-based
}
示例调用:
var strDate="18-01-1971";
if (null == IsValidDate(strDate)) {
alert("invalid date");
}
为什么我建议moment.js
这是非常受欢迎的图书馆
简单地解决所有日期和时间、格式和时区问题
易于检查字符串日期是否有效
var date = moment("2016-10-19");
date.isValid()
我们无法解决验证所有案例的简单方法
分歧
如果我插入有效数字,如89,90,95英寸new Date()在几个应答器上,我得到了坏结果,但它返回真
常量isValidDate=date=>{console.log('input'+date)var date=新日期(日期);console.log(日期)回来(Object.product.toString.call(date)==“[Object date]”&&+date)//返回!isNaN(date.getTime())}var test=“2012年4月5日”console.log(isValidDate(测试))var测试=“95”console.log(isValidDate(测试))var测试=“89”console.log(isValidDate(测试))var测试=“80”console.log(isValidDate(测试))var test=“badstring”console.log(isValidDate(测试))
在这么多人在我面前尝试之后,我为什么要写第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。
对于日期FNS,有一个名为isExists的函数。它检查日期是否存在(2月31日不应存在)。
示例:
// For the valid date:
const result = isExists(2018, 0, 31)
//=> true
// For the invalid date:
const result = isExists(2018, 1, 31)
//=> false
文档:https://date-fns.org/v2.28.0/docs/isExists