【问题标题】:Validation of Bad date in Javascript [duplicate]在Javascript中验证错误日期[重复]
【发布时间】:2019-08-05 17:19:54
【问题描述】:

我正在关注this 示例来验证日期字符串。

虽然下面这个例子的计算结果为真。

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

即使它是错误的日期,下面的示例也评估为 true。我的意思是错误的日期,日历中不存在该日期。

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

有没有更好的方法?

【问题讨论】:

  • 为什么你认为第二个例子是一个糟糕的日期?
  • @ethane 我想“坏”的意思是“不存在”。不过需要明确的是,JavaScript 认为这是 3 月 3 日。就像它将 4 月的“0 日”视为 3 月的最后一天一样。
  • @TylerRoper,糟糕透顶。 JS 足够聪明,实际上不会给你 2019 年 2 月 31 日。它会产生一个 3 月的日期。
  • @TylerRoper 我确实理解 JS 认为它是什么。但对于实际使用,这并没有帮助。
  • @TheFallenOne 调用moment(input) 没有格式字符串已被弃用。如果您要走 moment.js 路线,Ramy 在下面提供的答案应该仍然是完全有效的:)

标签: javascript date


【解决方案1】:

使用momentjs

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

来自图书馆的当前文档:isValid momentjs

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

您仍然可以通过拆分字符串并对每个部分进行评估来编写自己的解决方案。这种方法的问题在于,不仅 2 月 不是 31 天,还有其他月份也只有 30 天。因此,您需要一些时间才能开发出“没有错误”的解决方案。

【讨论】:

  • OP 没有用 moment.js 标记问题或提到它。不需要大型库,验证日期字符串的解析就像检查结果日期值与输入值一样简单。
【解决方案2】:

不建议使用new Date('02/31/2019')(隐式调用Date.parse)解析日期,因为实现之间存在不一致。

不推荐使用 Date.parse 直到 ES5,解析 字符串完全依赖于实现。还是有很多 不同主机解析日期字符串的方式不同,因此日期 应该手动解析字符串(如果有很多,一个库可以提供帮助 将适应不同的格式)。

来源:MDN

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

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

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

【讨论】:

    【解决方案3】:

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

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-10
      • 1970-01-01
      • 2021-02-23
      相关资源
      最近更新 更多