【问题标题】:MomentJs output Date of toDate() is incorrectMomentJs 输出 toDate() 的日期不正确
【发布时间】:2015-11-24 11:54:59
【问题描述】:

我已经开始在 Angular/Typescript 项目中使用 momentJs。 (包括在以任何方式相关的情况下,尽管我非常怀疑)

在我调用的模块的 run 方法中

moment.locale(window.navigator.language);

在我的实例中正确地将语言环境设置为 en-GB。再往下,我使用 moment 来解析 GB 时间。

执行以下操作时:

var mom = moment("24/11/2015 00:00:00");

例如。这使用在时刻全局上设置的默认值填充一个新的时刻对象(如果我理解它应该如何正常工作)。妈妈的日期设置为 2016-12-11T00:00:00.000Z。这显然意味着它在 en-US 中解析给定的字符串,而不是在此调用之前通过 Locale 在默认设置中设置的 en-GB。我在配置/设置时刻有什么遗漏的东西会使它不起作用吗? 我还检查了变量的 _locale 属性。 mom._locale 设置为 en-gb,我可以看到 L、LL、LLL 等格式都是 en-GB 格式的值(应该是)。

运行 mom.toDate();不出所料地返回由 moment 对象内部存储的 2016 年日期。

一些我忘记包含的杂项信息:

我正在使用来自 NuGet 的最新版本的 momentjs(在撰写本文时版本为 2.10.6),并且我在我的 HTML 中包含了 moment-with-locales.js

【问题讨论】:

    标签: javascript angularjs momentjs


    【解决方案1】:

    使用任何最新版本的 MomentJS,您应该会在控制台中看到原因:

    弃用警告:时刻构造回退到 js 日期。这是不鼓励的,将在即将发布的主要版本中删除。更多信息请参考https://github.com/moment/moment/issues/1407

    除非您指定格式字符串,否则 MomentJS 依赖于 Date 对象的解析,不幸的是,无论语言环境如何,Date 对象都将与使用 / 的字符串一起采用美国格式。 Date 的诸多不妥之处之一。

    您需要使用格式字符串,或以Date 使用的简化 ISO-8601 格式提供字符串。来自Parse > String

    从字符串创建时刻时,我们首先检查字符串是否与已知的 ISO 8601 格式匹配,如果未找到已知格式,则回退到 new Date(string)

    var day = moment("1995-12-25");
    

    警告:浏览器对解析字符串的支持不一致。因为没有规范应该支持哪些格式,所以在某些浏览器中有效的在其他浏览器中无效。

    为了获得一致的结果解析除 ISO 8601 字符串之外的任何内容,您应该使用字符串 + 格式。

    【讨论】:

    • 有趣的是,moment("24/11/2015 00:00:00", window.navigator.language); 有效,但没有记录。文档说您可以将语言环境作为 第三个 参数传递,而不是第二个。
    • 有趣。我正在研究获取该时刻存储在其语言环境信息中的语言格式并将其作为第二个参数传递,但这似乎是一个更优雅的解决方案(即使未记录)
    • 有趣的是,当格式传入 navigator.language(在我的实例中为 en-GB)时,它实际上将 24/11/2015 解析为值为 22/01/2015 的日期对象所以它并没有抱怨解析,但似乎将其解析为日期对象有点错误。我将继续努力让语言环境格式过时。
    • @Skintkingle:啊,你说得对,我应该检查一下日期!顺便说一句:github.com/moment/moment/issues/2770(我刚刚编辑过,一开始就搞错了)。
    • 哈,哈哈,哈哈哈。我们都准备好接受黑客攻击了吗? 3、2、1。回答!
    【解决方案2】:

    所以我通过从时刻获取语言环境数据并将其传递给格式参数来解决这个问题。考虑到“24/11/2015 00:00:00”的示例输入,我的格式如下:

    var format = moment.localeData().longDateFormat('L') + " " + moment.localeData().longDateFormat("LTS");
    

    这会生成“DD/MM/YYYY HH:mm:ss”的格式掩码。

    您可以混合和匹配您想要的任何格式,这将是特定于您设置 moment.locale("") 的语言环境(假设您已经设置了语言环境信息)

    这是一个疯狂的解决方法,我很惊讶在解析时没有将语言环境信息假定为默认值。 TJCrowder 在 Github 上提出了一个问题,我建议任何关心的人都应该发表评论。 https://github.com/moment/moment/issues/2770

    【讨论】:

      【解决方案3】:

      您最好将格式直接传递给 moment 并事先验证字符串。这最终将减少您需要进行的调试工作,让您立即启动并运行。

      var mom = moment("24/11/2015 00:00:00", "DD/MM/YYYY HH:mm:ss");

      您可以尝试新的(ish)Intl API,但浏览器支持有限(IE11+),所以我建议让用户在下拉菜单中选择月份或强制他们以某种方式输入。

      【讨论】:

      • 当我不知道正在使用的语言环境时有什么建议(因此当时无法对格式进行硬编码)。我的理解是设置语言环境将使用已经初始化的语言环境信息,并且传递导航器语言将(通常)获取当前用户的语言格式。此外,您的解析格式为 en-US,当用户区域设置为 en-GB(或不使用该格式的任何内容)时,这是不需要的
      • 我已经交换了解析格式。数据从何而来?如果它是用户提供的,您需要对其进行验证,例如强制用户以某种方式输入,或选择格式。如果它来自数据库,则希望它附有有关其格式化方式的信息。如果没有,那就是手动改进数据的情况……
      • 我不明白为什么我应该将用户输入限制为不是他们的语言环境的格式。这与整个全球化概念背道而驰。我绝对需要验证他们是否输入了有效的日期,但我不应该将其限制为可能不是他们的语言环境的非常具体的日期格式。
      • 啊,对不起。自动检测日期格式是一项棘手的工作,如果您真的担心它是使用月份的下拉菜单或允许用户选择格式,则容易得多。 window.navigator.language 不适合选择日期格式,因为它无法确定要使用哪种英语国家格式。 Intl API 更好,但仅支持 IE11+。 developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
      猜你喜欢
      • 2021-03-05
      • 2019-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多