【问题标题】:javascript- How do I parse a Date with moment.js(or alternative library) to pick out 31st Feb or 31st June e.t.c. as invalid?javascript-如何使用 moment.js(或替代库)解析日期以选择 2 月 31 日或 6 月 31 日等。无效?
【发布时间】:2015-11-24 00:02:04
【问题描述】:

如何使用 moment.js(或替代库)解析 Date 以将 2 月 31 日或 6 月 31 日 e、t、c 视为无效?

我知道如果我这样做了

moment("20-02-2000");

它说

Moment {_isAMomentObject: true, _i: "20-02-2000", 
_isUTC: false, _locale: Locale, _d: Invalid Date}

所以它可以检测到无效的日期,很好

虽然我使用的是 yyyy-mm-dd

我似乎无法让它解析日期

moment("2000-02-31");
Moment {_isAMomentObject: true, _i: "2000-02-31", 
_f: "YYYY-MM-DD", _isUTC: false, _pf: Object…}

^^ 没有关于无效日期的内容

moment("2000-02-40");
Moment {_isAMomentObject: true, _i: "2000-02-40", 
_f: "YYYY-MM-DD", _isUTC: false, _pf: Object…}

^^ 没有关于无效日期的内容

moment("2000-40-01");
Moment {_isAMomentObject: true, _i: "2000-40-01", 
_f: "YYYY-MM-DD", _isUTC: false, _pf: Object…}

^^ 没有关于无效日期的内容

添加

var v=moment("2000-02-31");

v.toDate()
Thu Mar 02 2000 00:00:00 GMT+0000 (GMT Standard Time)

^^ 我看到如果我给出一个无效的日期,比如 2 月 31 日,它会使其正常化,但我希望它只是说无效。

我正在寻找一个函数,我给它“2000-31-02”它说无效日期。

我已经看到 moment.js 被建议作为 javascript 的 Date 构造函数的替代方案。我查看了 moment.js,因为 javascript 的 Date 构造函数也解析了 31st Feb 而没有说 invalid javascript Date.parse assumes 31 days in February and all months? 。所以我希望 moment.js 能够做到这一点。如果可以,那怎么做?如果没有,那么有没有替代 moment.js 的方法呢?

我正在寻找一个可以导入的库,而不是重新发明轮子。

【问题讨论】:

  • 如果你用“YYYY-MM-DD”解析这样的无效,然后转身并以相同的格式格式化它们,它会给你返回相同(无效)的字符串,还是正常化2 月 31 日到 3 月 3 日?
  • @Pointy 我只是在我的 q 中添加了一点来测试它,我看到它对其进行了规范化,但我并不是在寻找它来规范化无效日期。我只是想让它检测/说无效日期。
  • 我的意思是,如果您返回的字符串与您提供的字符串不同,那么日期一定是无效的。

标签: javascript datetime momentjs


【解决方案1】:

有 isValid 方法,但你也应该指定格式,to moment..

例如moment("2000-02-31", "YYYY-MM-DD").isValid()

有趣的是,在输入时刻点时,javascript 控制台没有显示 isValid()。或moment.prototype。

文档说

Moment 原型通过 moment.fn 暴露出来

isValid 确实显示了 moment.fn。

而且它是正确的,甚至包括几个世纪以来的闰年规则,如果一个世纪可以被 4 和 400 整除,那么它就是闰年。

moment("2000-02-31", "YYYY-MM-DD").isValid()
false

moment("2000-02-28", "YYYY-MM-DD").isValid()
true    

moment("2100-02-28", "YYYY-MM-DD").isValid()
true

moment("2100-02-29", "YYYY-MM-DD").isValid()
false

moment("2000-02-29", "YYYY-MM-DD").isValid()
true

必须是大写的 Ds

moment("2000-02-40","YYYY-MM-dd").isValid()
true

moment("2000-02-40","YYYY-MM-DD").isValid()
false

您可能想使用正则表达式来检查它是 yyyy-mm-dd 还是 mm-dd-yyyy 等,因为它仍然接受 2000.9 或斜杠/任何分隔符

moment("2000/02/20","YYYY-MM-DD").isValid()
true
moment("2000/52/20","YYYY-MM-DD").isValid()
false
moment("2000.9","YYYY-MM-DD").isValid()
true

【讨论】:

    【解决方案2】:

    建议的格式 (YYYY-DD-MM) 必须重新格式化为 YYYY-MM-DD,否则 Javascript 日期构造函数将返回无效日期错误。

    因此,Date 构造函数仍将接受 2000-02-31 并将其转换为 2001-03-02。所以你必须对其进行预处理。

    当您对字符串进行了预处理并拥有 Date 构造函数的有效格式后,您可以使用以下代码转换为日期。下面的代码还让您有机会检查日期字符串是否有效以及年份是否为闰年。

    var dso = {
        convert:function(d) {
            // Converts the date in d to a date-object. The input can be:
            //   a date object: returned without modification
            //  an array      : Interpreted as [year,month,day].
            //   a number     : Interpreted as number of milliseconds
            //                  since 1 Jan 1970 (a timestamp)
            //   a string     : Any format supported by the javascript engine, like
            //                  "YYYY/MM/DD", "MM/DD/YYYY", "Jan 31 2009" etc.
            //  an object     : Interpreted as an object with year, month and date
            //                  attributes.
            return (
                d.constructor === Date ? d :
                d.constructor === Array ? new Date(d[0],d[1]-1,d[2]) :
                d.constructor === Number ? new Date(d) :
                d.constructor === String ? new Date(d) :
                typeof d === "object" ? new Date(d.year,d.month-1,d.date) :
                NaN
            );
        },
        isvalid(d,f) {
          // optional formats possible, see switch statement
          var m = [0,31,28,31,30,31,30,31,31,30,31,30,31], t,a;
          if (d.constructor == String) {
            d = d.replace("/","-").replace(".","-").replace(", ","-").replace(",","-").replace(" ","");
            t = d.split("-"), t[0] = parseInt(t[0]), t[1] = parseInt(t[1]), t[2] = parseInt(t[2]);
            switch(f) {
              case "yyyy-dd-mm":
                a = (dso.leapyear(t[0])?1:0);
                if (t[2] > 12 || t[2] < 1) return false;
                if (t[1] < 1 || (t[1] + a) > m[parseInt(t[2])]) return false;
                break;
              case "dd-mm-yyyy":
                a = (dso.leapyear(t[2])?1:0);
                if (t[1] > 12 || t[1] < 1) return false;
                if (t[0] < 1 || (t[0] + a) > m[parseInt(t[1])]) return false;
                break;
              case "mm-dd-yyyy":
                a = (dso.leapyear(t[2])?1:0);
                if (t[0] > 12 || t[0] < 1) return false;
                if (t[1] < 1 || (t[1] + a) > m[parseInt(t[0])]) return false;
                break;
              case "mm-yyyy-dd":
                a = (dso.leapyear(t[1])?1:0);
                if (t[0] > 12 || t[0] < 1) return false;
                if (t[2] < 1 || (t[2] + a) > m[parseInt(t[0])]) return false;
                break;
              case "yyyy-mm-dd":
              default:
                a = (dso.leapyear(t[0])?1:0);
                if (t[1] > 12 || t[1] < 1) return false;
                if (t[2] < 1 || (t[2] + a) > m[parseInt(t[1])]) return false;
                break;
            }
            return true;
          }
        },
        leapyear: function(year) {
          if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0 || year == 4905 || year == 8228) return true;
          return false;
        }
    }
    

    【讨论】:

    • 加上一个 - 在我未经训练的眼睛看来,这看起来像是一些相当优雅的代码,我喜欢用三元 if 完成的 if else 阶梯。尽管我正在寻找一个常用的库,但这很好/有趣
    【解决方案3】:

    Moment.js 提供了isValid 方法来检查解析后的字符串是否有效。

    moment("2000-02-28").isValid(); //true

    moment("2000-02-31").isValid(); //false

    moment("2000-02-40").isValid(); //false

    这是您要寻找的行为吗?

    你可以在这里http://momentjs.com/docs/#/parsing/is-valid/阅读更多关于这个方法的信息

    【讨论】:

      【解决方案4】:

      您可以先使用moment().isValid() 检查 moment 是否认为日期有效。

      console.log(moment('2015-02-31').isValid());
      //false
      

      http://jsfiddle.net/nicholasduffy/uv8aqykm/

      http://momentjs.com/docs/#/parsing/string-format/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多