【问题标题】:Javascript Date allows invalid data (e.g. Feb 30th) [duplicate]Javascript 日期允许无效数据(例如 2 月 30 日)[重复]
【发布时间】:2016-03-23 13:39:27
【问题描述】:

如何验证日期?我的意思不是格式,而是逻辑。 例如:2 月 30 日不是有效日期。

var date = new Date("2015-02-29T13:02:49.073Z"); // 2015 Feb 29th does not exist
console.log(date.toISOString());

返回 2015-03-01T13:02:49.073Z(3 月 1 日)。

但是我想知道这个日期(输入)是无效的。

编辑: 在 Chrome 中测试。 Firefox 返回“无效日期”。但不是解析。 只有在使用日期时(例如 toISOString())才会抛出异常。

try
{
  var date = new Date("2015-02-29T13:02:49.073Z");
  console.log(date.toISOString());
}
catch(e)
{
    console.log("error: " + e.message);
}

火狐:

无效日期

铬:

(什么都没有,只是切换到下一个日期。)

总结:它依赖于浏览器。所以,不推荐使用。

jsfiddle example

【问题讨论】:

  • 停止:我现在看到这取决于浏览器。 Firefox 返回无效日期,chrome 忽略并计算到下一天。好的,但这太可怕了。我必须编写一个自己的函数来验证日期字符串。 (?)
  • ES5 之前不建议使用 Date.parse,字符串的解析完全依赖于实现。不同主机解析日期字符串的方式仍有许多差异,因此应手动解析日期字符串(如果要适应多种不同格式,库可以提供帮助)。 (ref.)
  • 这里有问题吗? Date 构造函数如何处理各种参数背后的逻辑在ECMA-262 中有完整记录。如何验证日期(即值)已在 many questions here 中介绍。
  • @RobG 这不完全一样。问题是关于日期对象允许无效数据。很高兴知道这取决于浏览器。它与ECMA“无关”。这是一种浏览器行为。这个信息很有用。但是感谢您的链接和您的建议。

标签: javascript date


【解决方案1】:

我能想到的最简单的事情就是将解析后的日期转换为 ISO 字符串并与原始输入进行比较:

var input = "2015-02-29T13:02:49.073Z"
var date = new Date(input);
var isValid = (input === date.toISOString());

【讨论】:

  • 是的,谢谢。我只是有同样的想法。它仅适用于相同的字符串格式。但这正是我所需要的。我已经有一个用于验证 ISO 字符串的正则表达式。
【解决方案2】:

我使用这个函数来检查日期是否有效:

function isValidDate(year, month, day) {
    month = month - 1;
    var d = new Date(year, month, day);
    if (d.getFullYear() == year && d.getMonth() == month && d.getDate() == day) {
      return true;
    }
    return false;
}

【讨论】:

  • 是的,我也认为你必须这样做。仅仅用 Date() 解析是不够的。 :)
  • 请注意,您可能需要对此代码进行规范化并添加时区/夏令时,如我的回答中所述
  • @mplungjan — 可以忽略日期的夏令时(前提是浏览器没有错误)。只需要测试月份(因为超出月份范围的日期和超出 1 到 12 的月份将导致 getMonth 返回不同的月份编号)。
  • 创建的日期可能在午夜左右,因此取决于时区的第二天
【解决方案3】:

我为你写了一个小函数:

function check_date(str){
    try{
        return str == new Date(str).toISOString()
    }catch(e){
        return false;
    }
}

试试这个

console.log(check_date('2015-02-01T13:02:49.073Z'));
console.log(check_date('2015-02-35T13:02:49.073Z'));
console.log(check_date('2015-02-29T13:02:49.073Z'));

https://jsfiddle.net/8o040ctr/

【讨论】:

  • @trincot 我认为他的回答方式适用于任何浏览器
  • 你是对的,我错过了答案的重点:-)
【解决方案4】:

我发现这种行为很有趣。我以前只是将输入转换为日期(就像您所做的那样),然后更新文本框中的文本以显示由 JavaScript 解释的日期,以便用户看到结果(有效)日期。

幸运的是,我们现在可以做得更好。 Moment.js 是一个很棒的库,用于处理 JavaScript 中的日期/时间值。这确实让我的生活变得轻松多了!

http://momentjs.com/

【讨论】:

    【解决方案5】:

    如果您传递一个以 'YYYY-MM' 格式开头的字符串,就像您在问题中遇到的那样,您可以使用这个函数:

    function makeDate(s) {
        var date = new Date(s);
        if (date.toISOString(date).substr(0,7) != s.substr(0,7)) throw "Invalid date";
        return date;
    }
    
    dt = makeDate('2015-02-29T13:02:49.073Z');
    

    这个 makeDate 函数将替换普通的 new Date(...) 调用,但在传递无效日期字符串时也会在 Chrome 中引发错误。

    【讨论】:

      【解决方案6】:

      浏览器中的日期总是很棘手,我建议你使用类似时刻的 js lib:http://momentjs.com/

      那么你可以使用 .isValid() 方法作为例子:

      moment('03:55', 'HH:mm').isValid(); 
      moment('2012-05-25', 'YYYY-MM-DD').isValid();
      moment('2015-02-29T13:02:49.073Z', "YYYY-MM-DDTHH:mm:ss", true).isValid();
      

      【讨论】:

      • 据我所知,根本没有建议。
      • 最后一个测试了吗?
      猜你喜欢
      • 1970-01-01
      • 2021-06-28
      • 1970-01-01
      • 1970-01-01
      • 2017-04-22
      • 1970-01-01
      • 1970-01-01
      • 2021-08-21
      • 1970-01-01
      相关资源
      最近更新 更多