在Javascript中验证错误的日期

Validation of Bad date in Javascript

本问题已经有最佳答案,请猛点这里访问。

我正在按照这个例子来验证日期字符串。

虽然以下示例评估为true。

1
2
var date = new Date('12/21/2019');
console.log(date instanceof Date && !isNaN(date.valueOf()));

以下示例也评估为true,即使它是一个糟糕的日期。我的意思是错误的日期,日期中不存在该日期。

1
2
var date = new Date('02/31/2019');
console.log(date instanceof Date && !isNaN(date.valueOf()));

有没有更好的方法呢?


使用momentjs

1
2
moment("02/30/2019","MM/DD/YYYY", true).isValid(); // false
moment("03/30/2019","MM/DD/YYYY", true).isValid(); // true

来自图书馆的现有文档:isValid momentjs

1
moment("not a real date").isValid(); // false

您仍然可以通过拆分字符串并为每个部分进行评估来编写自己的解决方案。这种方法的问题在于,不仅2月不是31天,还有其他月份也只有30天。因此,在制定"无障碍"解决方案之前需要一些时间。


很大程度上取决于允许的输入格式,但这似乎是您的示例的可能解决方案(纯JS,没有额外的库):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const trueDate = '12/21/2019'
const falseDate = '02/31/2019'

const checkDate = (dateStr) => {
  const dateObj = new Date(dateStr)
  const actualDate = dateObj.getDate()
  const actualMonth = dateObj.getMonth() + 1 // months are from 0 to 11 in JS
  const actualFullYear = dateObj.getFullYear()

  const [strMonth, strDate, strFullYear] = dateStr.split('/').map(Number)

  return strMonth === actualMonth && strDate === actualDate && strFullYear === actualFullYear
}

console.log(checkDate(trueDate))  // true
console.log(checkDate(falseDate))  // false


由于实现之间的不一致,建议不要使用new Date('02/31/2019')(隐式调用Date.parse)来解析日期。

It is not recommended to use Date.parse as until ES5, parsing of
strings was entirely implementation dependent. There are still many
differences in how different hosts parse date strings, therefore date
strings should be manually parsed (a library can help if many
different formats are to be accommodated).

资料来源:MDN

相反,您可以使用正则表达式提取日期的某些部分,然后使用new Date(year, monthIndex, day)new Date(Date.UTC(year, monthIndex, day))构造日期对象,具体取决于您假设的时区。

然后,您可以将新创建??的日期对象格式化为字符串,并检查它是否与初始字符串相同。如果日期结束到下个月(例如2月30日到3月1日),则字符串将不匹配。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function parseMMDDYYY(str) {
    const match = str.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
    if (!match) {
        throw new Error(`Invalid date format ${str}`);
    }
    const [, m, d, y] = match;
    const date = new Date(Date.UTC(y, m - 1, d));
    if (!date.toISOString().startsWith(`${y}-${m}-${d}`)) {
        throw new Error(`Invalid date ${str}`);
    }
    return date;
}

try {
    console.log(parseMMDDYYY('02/31/2019'));
} catch (e) {
    console.log(e.toString());
}

try {
    console.log(parseMMDDYYY('12/21/2019'));
} catch (e) {
    console.log(e.toString());
}