【问题标题】:Any way to parse a time string using Moment.js but ignore timezone info?任何使用 Moment.js 解析时间字符串但忽略时区信息的方法?
【发布时间】:2014-10-15 06:40:05
【问题描述】:

考虑到时区问题的数量,我本以为能够找到这个问题的答案,但没有任何成功。

有没有办法使用moment.js 来解析 ISO-8601 字符串,但是否在我的本地 timzeone 中对其进行了解析?本质上,我想忽略 ISO 字符串中提供的时区信息。

例如,如果我在 EDT 时区:

var x = moment( "2012-12-31T00:00:00+0000" );

会给我: "2012-12-30T19:00:00-5000"

我希望忽略时区信息,让它给我相当于当地时间 (EDT) 的“2012-12-31T00:00:00-5000”的时间。

【问题讨论】:

    标签: javascript datetime momentjs


    【解决方案1】:

    我不认为你真的想忽略偏移量。那最终只会用您当地时区的偏移量替换您提供的偏移量 - 这将导致完全不同的时刻。

    也许您只是在寻找一种方法来保留指定的时区?如果是这样,则使用moment.parseZone 函数。例如:

    var m = moment.parseZone("2012-12-31T00:00:00+0000");
    var s = m.format();   // "2012-12-31T00:00:00+00:00"
    

    您也可以使用moment.utc 实现此目的。不同之处在于moment.parseZone 将保留您给它的任何偏移量,而moment.utc 将在您给它一个非零偏移量时调整为 UTC。

    【讨论】:

    • 您想要这样做是有充分理由的。生日。服务器向用户发送属性生日日期时间设置为午夜的用户。用户根本不在乎他们在哪个时区或任何东西。很容易将所有日期以 UTC 存储在您的数据库中,并使网络服务器使用 ISO-8601 中的 UTC 修改所有出站日期。但是很难做到这一点并修改对象的单个属性以不将时区属性添加到值中。
    • @klatzib - 当然,我可以看到。我以前什至可能这样做过。 :) 但我认为依靠客户端功能来解决服务器端问题是一种黑客行为。以 ISO-8601 扩展格式格式化生日(或其他日历日期)的唯一正确方法是 YYYY-MM-DD,没有时间或偏移量。
    • 好吧,事实证明,自从我上次阅读文档以来,我的 ORM 添加了对简单日期数据类型的支持,而不是之前仅支持日期时间。我想现在真的没有借口了。德拉特。
    • 哦!其实现在想起来了。我确实检查了,但这没关系,因为我使用的是.Net,它只是将日期字段作为 DateTime 对象处理,反序列化时时间设置为 00:00:00。我的服务器转换为 UTC 是针对 DateTime 类型的,因此对于运行 .Net 网络服务器的人来说,除了基于添加到属性的某些属性的 UTC 转换的每个属性异常的额外复杂模式之外,没有办法解决它。
    • @klatzib - 是的,这很棘手,但它是可行的。您可以设置DateTimeZoneHandling.RoundTripKind 并依赖DateTimeKind 正确设置为Unspecified(用于生日),但它仍会在午夜显示时间。至少这将(大部分)在 moment.js 中正常工作。除非,当然,如果你在巴西并且日期是在 DST 春天向前过渡......你总是可以写一个自定义的 JsonConverter,或者只是使用 Noda Time 和 LocalDate 对象......但是我们在这里从 OP 中脱离话题。如果需要,请随时提出新问题。 :)
    【解决方案2】:

    我通过提供 format 作为第二个参数并使用 Moment 的 escaping characters 方法解决了这个问题,并在时区周围加上方括号。

    moment("2016-01-01T05:00:00-05:00", "YYYY-MM-DDTHH:mm:ss[Z]").startOf("hour").format()
    

    这仍将使用您当地的时区创建时刻对象,但不会进行任何类型的自动时区计算。因此,无论提供什么时区,上面的示例都会给您早上 5 点。

    【讨论】:

      【解决方案3】:

      我知道我迟到了,我有同样的问题,我的搜索并没有让我更接近。我分解并阅读了文档,并且有一个字符串+格式的选项:

      String + Format docs

      时刻(字符串,字符串);

      时刻(字符串,字符串,字符串);

      时刻(字符串,字符串,布尔值);

      时刻(字符串,字符串,字符串,布尔值);

      还有更多的话,那么这个:

      除非您指定时区偏移量,否则解析字符串将在当前时区创建日期。

      moment("2010-10-20 4:30",       "YYYY-MM-DD HH:mm");   // parsed as 4:30 local time
      moment("2010-10-20 4:30 +0000", "YYYY-MM-DD HH:mm Z"); // parsed as 4:30 UTC
      

      让我暂停的部分是用于解析本地时间的示例省略了 +0000,这让我认为输入字符串需要将其删除,但事实并非如此。

      示例:

      var time = "2012-12-31T00:00:00+0000";
      var x = moment(time); // Sun Dec 30 2012 19:00:00 GMT-0500
      var y = moment(time,'YYYY-MM-DD'); //Mon Dec 31 2012 00:00:00 GMT-0500
      

      【讨论】:

        【解决方案4】:

        如果你确定你的输入字符串是 ISO-8601 格式,你可以去掉最后 5 位数字并在 Moment 构造函数中使用它。

        var input = "2012-12-31T00:00:00+0000"
        input = input.substring(0, input.length-5)
        moment(input).toString()
        > "Mon Dec 31 2012 00:00:00 GMT-0600"
        

        【讨论】:

        • 是的 - 这几乎也是我想出的,但对解决方案不太满意。会认为 momentjs 或 moment-timezone 中有一些东西可以做到这一点,而我不必求助于字符串操作。
        【解决方案5】:

        您可以通过使用moment.utc() 而不是moment() 创建一个新时刻来完全忽略浏览器的时区。

        例如,如果您尝试纯粹使用浏览器当前时间的 UTC 日期/时间,但想丢弃其时区数据,您可以使用以下方法将浏览器的当前时间重新创建为 UTC 格式:

        let nowWithTimezone = moment();
        let nowInUtc = moment.utc(nowWithTimezone.format('MM/DD/YYYY HH:mm'), 'MM/DD/YYYY HH:mm');
        

        关于moment.utc()的更多文档:https://momentjs.com/docs/#/parsing/utc/

        【讨论】:

          【解决方案6】:

          有正当理由去做 OP 要求的事情。使用 Moment 执行此操作的最简单方法是使用其 parseZone(date) 方法。无需担心字符串操作或多次调用。它有效地解析日期字符串,就好像它在浏览器的本地时区中一样。

          【讨论】:

            【解决方案7】:

            对于 MomentJS 来说这是一项艰巨的任务,它基本上也取决于您当前的时区。

            对于这个特定任务,文档也很模糊,我解决这个问题的方法是在将日期转换为 JSON 格式之前添加几个小时。

            var dt = moment("Sun Sep 13 2015 00:00:00 GMT-0400", "ddd MMM DD YYYY HH:mm:ss GMT-0400", false);
            var date = dt.add(2, 'hour').toJSON();
            console.log(date); //2015-09-13T00:00:00.000Z
            

            【讨论】:

              【解决方案8】:

              Momentjs 默认逻辑将使用本地时区格式化给定时间。为了格式化原始日期,我写了一个函数:

              https://github.com/moment/moment/issues/2788#issuecomment-321950638

              【讨论】:

                【解决方案9】:

                使用moment.parseZone进行转换而不考虑时区。

                const moment = require('moment')
                
                const dateStr = '2020-07-21T10:00:00-09'
                
                const date = moment.parseZone(dateStr)
                
                console.log(date.format('MM-DD-YY HH:mm A')) // 07-21-20 10:00 AM
                

                Try herelink to docs

                【讨论】:

                  【解决方案10】:

                  最好的方法是使用:

                  dt = moment("Wed Sep 16 2015 18:31:00 GMT-0400", "ddd MMM DD YYYY HH:mm:ss GMT-0400",true);
                  

                  并再次显示转换为所需的时区:

                   dt.utcOffset("-04:00").toString()
                   output > Wed Sep 16 2015 18:31:00 GMT-0400
                  

                  【讨论】:

                    猜你喜欢
                    • 2020-08-28
                    • 2012-06-10
                    • 2012-02-03
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-09-13
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-08-25
                    相关资源
                    最近更新 更多