如何验证日期?


72

我正在尝试测试以确保某个日期有效(如果有人输入2/30/2011则应该是错误的)。

我该如何在任何日期进行此操作?


@Mitch-在靶心里:)
Andrey

2
@Mitch-OP想要知道它是否是有效日期,而不是有效日期对象。例如,new Date('2011/5/33')将创建一个日期对象,但该日期将不被视为有效。
RobG 2011年

1
您能再打开一遍吗?可能还有其他更好的答案。
RobG

@MitchWheat既然这是两个不同的问题,并且这个问题有一个好的答案,我想您有责任重新打开它。[这个问题的观看次数也很高。]
LCJ 2012年

这是一个非常复杂的问题。首先,格式设置:2011年2月25日是欧洲大部分地区的最佳约会。但是是2013年12月2日2月12日还是2月12日?第二:如果您希望它具有历史意义,那么有些古老的领导人会通过弄乱日历来使某些日期无效。
保罗,

Answers:


128

验证日期字符串的一种简单方法是将其转换为日期对象并进行测试,例如

// Expect input as d/m/y
function isValidDate(s) {
  var bits = s.split('/');
  var d = new Date(bits[2], bits[1] - 1, bits[0]);
  return d && (d.getMonth() + 1) == bits[1];
}

['0/10/2017','29/2/2016','01/02'].forEach(function(s) {
  console.log(s + ' : ' + isValidDate(s))
})

以这种方式测试日期时,仅需要测试月份,因为如果日期超出范围,则月份将更改。如果月份超出范围,则相同。任何一年都是有效的。

您还可以测试日期字符串的位:

function isValidDate2(s) {
  var bits = s.split('/');
  var y = bits[2],
    m = bits[1],
    d = bits[0];
  // Assume not leap year by default (note zero index for Jan)
  var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

  // If evenly divisible by 4 and not evenly divisible by 100,
  // or is evenly divisible by 400, then a leap year
  if ((!(y % 4) && y % 100) || !(y % 400)) {
    daysInMonth[1] = 29;
  }
  return !(/\D/.test(String(d))) && d > 0 && d <= daysInMonth[--m]
}

['0/10/2017','29/2/2016','01/02'].forEach(function(s) {
  console.log(s + ' : ' + isValidDate2(s))
})


6
注意:示例2中使用的dateformat是dd / mm / yyyy,而不是mm / dd / yyyy
Stefan Steiger 2012年

1
方法2是否将00/10/2000标记为有效日期?
丹尼尔·斯科科

@DanielScocco-绝对正确!固定,并转换为可运行的代码段。;-)
RobG

提出的第一个解决方案还不是很完整。例如,对于不是真正有效的日期,它对于“ 367/1/2000”返回true。看看我的答案,其中包括在解析日期和比较月份之前进行的正则表达式检查。
罗森菲尔德

10

RobG建议的第一个函数isValidDate是否对输入字符串'1/2 /'有效?我认为不会,因为YEAR未通过验证;(

我的建议是使用此功能的改进版本:

//input in ISO format: yyyy-MM-dd
function DatePicker_IsValidDate(input) {
        var bits = input.split('-');
        var d = new Date(bits[0], bits[1] - 1, bits[2]);
        return d.getFullYear() == bits[0] && (d.getMonth() + 1) == bits[1] && d.getDate() == Number(bits[2]);
}

您应该以其他方式认为,我发布的功能只需要检查月份即可。测试年份是没有意义的,因为任何年份都可能有效或无效,并且仅当月份也更改时,其值才会更改。
RobG

@RobG-我认为Piotr的意思是应该检查年份,以防“ Year”是null数字或非数字。
凯文·费根

@KevinFegan-如果是这样,那么结果将是无效的日期,并且月份检查(正确)将失败。;-)
RobG '16

1
Rob,尝试使用您的解决方案时,我发现01/02返回true。
adi518 '17

@ adi518-为两个示例添加了“ 01/02”作为测试,第一个返回false,第二个返回true。如果其他人想要更改或不更改,则由我自己决定。
RobG

4

此解决方案不解决明显的日期验证问题,例如确保日期部分为整数,或者日期部分符合明显的验证检查,例如日期大于0且小于32。该解决方案假定您已经拥有所有三个日期部分(年,月,日),并且每个都已经通过了明显的验证。鉴于这些假设,此方法应仅用于检查日期是否存在。

例如,2009年2月29日不是真实日期,而是2008年2月29日。当您创建新的Date对象(例如2009年2月29日)时,请注意会发生什么情况(请记住,JavaScript中的月份从零开始):

console.log(new Date(2009, 1, 29));

上面的行输出:Sun Mar 01 2009 00:00:00 GMT-0800(PST)

请注意,日期是如何简单地滚动到下个月的第一天。假设您还有其他明显的验证,则可以使用以下功能使用以下信息来确定日期是否为真实信息(此功能允许使用非零月为基础的月份,以便输入更方便):

var isActualDate = function (month, day, year) {
    var tempDate = new Date(year, --month, day);
    return month === tempDate.getMonth();
};

这不是一个完整的解决方案,也没有考虑i18n,但可以使其更强大。


4
var isDate_ = function(input) {
        var status = false;
        if (!input || input.length <= 0) {
          status = false;
        } else {
          var result = new Date(input);
          if (result == 'Invalid Date') {
            status = false;
          } else {
            status = true;
          }
        }
        return status;
      }

该函数返回给定输入是否为有效日期的布尔值。例如:

if(isDate_(var_date)) {
  // statements if the date is valid
} else {
  // statements if not valid
}

请评论您的代码段-它如何帮助OP
Nogard 2014年

它不适用于所有日期格式。例如 dd-MMM-yyyy
Evaldas Dzimanavicius 2014年

'Invalid Date'是类型检查。如果与字符串比较,则结果为true。
Ashish Gaur 2015年

您有更改-> 7.line(result.toString()==='无效的日期')
AhbapAldirmaz

4

我建议使用moment.js。仅提供时刻的日期即可对其进行验证,而无需传递dateFormat。

var date = moment("2016-10-19");

然后date.isValid()给出期望的结果。

硒发布HERE


Moment是一个很棒的库,实际上我在当前的大多数Web项目中都使用了它,但是我最初试图在没有任何其他库的情况下完成此任务。不过,感谢您的贡献,我强烈建议Moment.js
塞斯·邓肯

1
仅当日期格式为“ RFC2822或ISO”格式时,此方法才有效。否则,它将传递给原始的Date构造函数。因此,它不能解决op的问题:moment('2/30/2011').isValid()return true
BJury

关于“无需传递dateFormat ”,您应该始终传递格式。如果不是默认的moment.js格式,它将退回到内置的解析器中,因此没有比更好的了new Date(string)
RobG '20年

1

我只是翻拍了RobG解决方案

var daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
var isLeap = new Date(theYear,1,29).getDate() == 29;

if (isLeap) {
  daysInMonth[1] = 29;
}
return theDay <= daysInMonth[--theMonth]

1

这是ES6(带有let声明)。

function checkExistingDate(year, month, day){ // year, month and day should be numbers
     // months are intended from 1 to 12
    let months31 = [1,3,5,7,8,10,12]; // months with 31 days
    let months30 = [4,6,9,11]; // months with 30 days
    let months28 = [2]; // the only month with 28 days (29 if year isLeap)

    let isLeap = ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);

    let valid = (months31.indexOf(month)!==-1 && day <= 31) || (months30.indexOf(month)!==-1 && day <= 30) || (months28.indexOf(month)!==-1 && day <= 28) || (months28.indexOf(month)!==-1 && day <= 29 && isLeap);

    return valid; // it returns true or false
}

在这种情况下,我打算从1到12个月。如果您更喜欢或使用基于0-11的模型,则可以使用以下命令更改数组:

let months31 = [0,2,4,6,7,9,11];
let months30 = [3,5,8,10];
let months28 = [1];

如果您的日期采用dd / mm / yyyy格式,则可以删除day,month和year函数参数,并执行以下操作来检索它们:

let arrayWithDayMonthYear = myDateInString.split('/');
let year = parseInt(arrayWithDayMonthYear[2]);
let month  = parseInt(arrayWithDayMonthYear[1]);
let day = parseInt(arrayWithDayMonthYear[0]);

0

如果有效日期,我的函数返回true,否则返回false:D

function isDate  (day, month, year){
	if(day == 0 ){
		return false;
	}
	switch(month){
		case 1: case 3: case 5: case 7: case 8: case 10: case 12:
			if(day > 31)
				return false;
			return true;
		case 2:
			if (year % 4 == 0)
				if(day > 29){
					return false;
				}
				else{
					return true;
				}
			if(day > 28){
				return false;
			}
			return true;
		case 4: case 6: case 9: case 11:
			if(day > 30){
				return false;
			}
			return true;
		default:
			return false;
	}
}

console.log(isDate(30, 5, 2017));
console.log(isDate(29, 2, 2016));
console.log(isDate(29, 2, 2015));


0

不幸的是,JavaScript似乎没有简单的方法来验证日期字符串。这是我想到的在现代浏览器中解析日期格式为“ m / d / yyyy”的最简单方法(这就是为什么它没有指定要解析的基数的原因,因为从ES5开始应该为10)。

const dateValidationRegex = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
function isValidDate(strDate) {
  if (!dateValidationRegex.test(strDate)) return false;
  const [m, d, y] = strDate.split('/').map(n => parseInt(n));
  return m === new Date(y, m - 1, d).getMonth() + 1;
}

['10/30/2000abc', '10/30/2000', '1/1/1900', '02/30/2000', '1/1/1/4'].forEach(d => {
  console.log(d, isValidDate(d));
});


0

嗨,请在下面找到答案。这是通过验证新创建的日期来完成的

var year=2019;
var month=2;
var date=31;
var d = new Date(year, month - 1, date);
if (d.getFullYear() != year
        || d.getMonth() != (month - 1)
        || d.getDate() != date) {
    alert("invalid date");
    return false;
}

-1
function isValidDate(year, month, day) {
        var d = new Date(year, month - 1, day, 0, 0, 0, 0);
        return (!isNaN(d) && (d.getDate() == day && d.getMonth() + 1 == month && d.getYear() == year));
    }

4
请解释您的答案。
辍学

-1

尽管这是很久以前提出的,但仍然是最需要的验证。我发现了一个有趣的博客,功能很少。

/* Please use these function to check the reuslt only. do not check for otherewise. other than utiljs_isInvalidDate

Ex:-

utiljs_isFutureDate() retuns only true for future dates. false does not mean it is not future date. it may be an invalid date.

practice :

call utiljs_isInvalidDate first and then use the returned date for utiljs_isFutureDate()

var d = {};

if(!utiljs_isInvalidDate('32/02/2012', d))

if(utiljs_isFutureDate(d))

//date is a future date

else

// date is not a future date



 */

function utiljs_isInvalidDate(dateStr, returnDate) {

    /*dateStr | format should be dd/mm/yyyy, Ex:- 31/10/2017

     *returnDate will be in {date:js date object}.

     *Ex:- if you only need to check whether the date is invalid,

     * utiljs_isInvalidDate('03/03/2017')

     *Ex:- if need the date, if the date is valid,

     * var dt = {};

     * if(!utiljs_isInvalidDate('03/03/2017', dt)){

     *  //you can use dt.date

     * }

     */

    if (!dateStr)
        return true;
    if (!dateStr.substring || !dateStr.length || dateStr.length != 10)
        return true;
    var day = parseInt(dateStr.substring(0, 2), 10);
    var month = parseInt(dateStr.substring(3, 5), 10);
    var year = parseInt(dateStr.substring(6), 10);
    var fullString = dateStr.substring(0, 2) + dateStr.substring(3, 5) + dateStr.substring(6);
    if (null == fullString.match(/^\d+$/)) //to check for whether there are only numbers
        return true;
    var dt = new Date(month + "/" + day + "/" + year);
    if (dt == 'Invalid Date' || isNaN(dt)) { //if the date string is not valid, new Date will create this string instead
        return true;
    }
    if (dt.getFullYear() != year || dt.getMonth() + 1 != month || dt.getDate() != day) //to avoid 31/02/2018 like dates
        return true;
    if (returnDate)
        returnDate.date = dt;
    return false;
}

function utiljs_isFutureDate(dateStrOrObject, returnDate) {
    return utiljs_isFuturePast(dateStrOrObject, returnDate, true);
}

function utiljs_isPastDate(dateStrOrObject, returnDate) {
    return utiljs_isFuturePast(dateStrOrObject, returnDate, false);
}

function utiljs_isValidDateObjectOrDateString(dateStrOrObject, returnDate) { //this is an internal function
    var dt = {};
    if (!dateStrOrObject)
        return false;
    if (typeof dateStrOrObject.getMonth === 'function')
        dt.date = new Date(dateStrOrObject); //to avoid modifying original date
    else if (utiljs_isInvalidDate(dateStrOrObject, dt))
        return false;
    if (returnDate)
        returnDate.date = dt.date;
    return true;

}

function utiljs_isFuturePast(dateStrOrObject, returnDate, isFuture) { //this is an internal function, please use isFutureDate or isPastDate function
    if (!dateStrOrObject)
        return false;
    var dt = {};
    if (!utiljs_isValidDateObjectOrDateString(dateStrOrObject, dt))
        return false;
    today = new Date();
    today.setHours(0, 0, 0, 0);
    if (dt.date)
        dt.date.setHours(0, 0, 0, 0);
    if (returnDate)
        returnDate.date = dt.date;
    //creating new date using only current d/m/y. as td.date is created with string. otherwise same day selection will not be validated.
    if (isFuture && dt.date && dt.date.getTime && dt.date.getTime() > today.getTime()) {
        return true;
    }
    if (!isFuture && dt.date && dt.date.getTime && dt.date.getTime() < today.getTime()) {
        return true;
    }
    return false;
}

function utiljs_isLeapYear(dateStrOrObject, returnDate) {
    var dt = {};
    if (!dateStrOrObject)
        return false;
    if (utiljs_isValidDateObjectOrDateString(dateStrOrObject, dt)) {
        if (returnDate)
            returnDate.date = dt.date;
        return dt.date.getFullYear() % 4 == 0;
    }
    return false;
}

function utiljs_firstDateLaterThanSecond(firstDate, secondDate, returnFirstDate, returnSecondDate) {
    if (!firstDate || !secondDate)
        return false;
    var dt1 = {},
    dt2 = {};
    if (!utiljs_isValidDateObjectOrDateString(firstDate, dt1) || !utiljs_isValidDateObjectOrDateString(secondDate, dt2))
        return false;
    if (returnFirstDate)
        returnFirstDate.date = dt1.date;
    if (returnSecondDate)
        returnSecondDate.date = dt2.date;
    dt1.date.setHours(0, 0, 0, 0);
    dt2.date.setHours(0, 0, 0, 0);
    if (dt1.date.getTime && dt2.date.getTime && dt1.date.getTime() > dt2.date.getTime())
        return true;
    return false;
}

function utiljs_isEqual(firstDate, secondDate, returnFirstDate, returnSecondDate) {
    if (!firstDate || !secondDate)
        return false;
    var dt1 = {},
    dt2 = {};
    if (!utiljs_isValidDateObjectOrDateString(firstDate, dt1) || !utiljs_isValidDateObjectOrDateString(secondDate, dt2))
        return false;
    if (returnFirstDate)
        returnFirstDate.date = dt1.date;
    if (returnSecondDate)
        returnSecondDate.date = dt2.date;
    dt1.date.setHours(0, 0, 0, 0);
    dt2.date.setHours(0, 0, 0, 0);
    if (dt1.date.getTime && dt2.date.getTime && dt1.date.getTime() == dt2.date.getTime())
        return true;
    return false;
}

function utiljs_firstDateEarlierThanSecond(firstDate, secondDate, returnFirstDate, returnSecondDate) {
    if (!firstDate || !secondDate)
        return false;
    var dt1 = {},
    dt2 = {};
    if (!utiljs_isValidDateObjectOrDateString(firstDate, dt1) || !utiljs_isValidDateObjectOrDateString(secondDate, dt2))
        return false;
    if (returnFirstDate)
        returnFirstDate.date = dt1.date;
    if (returnSecondDate)
        returnSecondDate.date = dt2.date;
    dt1.date.setHours(0, 0, 0, 0);
    dt2.date.setHours(0, 0, 0, 0);
    if (dt1.date.getTime && dt2.date.getTime && dt1.date.getTime() < dt2.date.getTime())
        return true;
    return false;
}

将整个代码复制到文件中并包含。

希望这可以帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.