【问题标题】:Extracting timezone number using moment.js使用 moment.js 提取时区编号
【发布时间】:2017-12-19 22:03:06
【问题描述】:

我的网络应用客户端从 REST API 服务器接收 JSON 数据。

数据包含时区字符串值,例如“Etc/GMT-1”。 对于时间计算,我需要提取时区编号(就像 -1 一样)。 如果我使用parseInt(timezone);,返回值为NaN

我不确定 moment.js 是否可以处理这种格式并提取 GMT 数字。 我认为时区数据格式可能很灵活。 所以,我更喜欢使用 moment.js。

有没有办法使用 moment.js 提取数字?

【问题讨论】:

    标签: javascript timezone momentjs timezone-offset


    【解决方案1】:

    字符串"Etc/GMT-1" 是有效的 IANA 时区标识符。您可以在in the tzdb sourcesthe list on Wikipedia 中找到它。正如in the tzdb commentary 指出的那样,该标志与您的预期相反。这意味着 UTC+1,而不是 UTC-1。

    您还说过:“我认为时区数据格式可能很灵活。”实际上,如果您的数据包含任何 tzdb 区域标识符,您应该假设 所有 时区标识符也是有效的,包括更传统的形式,如 "America/Los_Angeles""Asia/Shanghai"。因此,您不应该尝试从字符串本身中提取任何内容。

    请务必记住,虽然某些区域有一个固定的偏移量,但大多数区域代表一系列偏移量以及它们之间的过渡点。因此,您不应该在不考虑时间点的情况下尝试从时区 id 获取单个偏移量。这也在 the timezone tag wiki 的主题“时区!=偏移”下进行了介绍。

    要将这些与moment.js 一起使用,您还需要moment-timezone 附加组件。例如:

    var timeZone = 'Etc/GMT-1';  // your time zone
    
    var m = moment.tz(timeZone);  // get the *current* time in the time zone.
    // or
    var m = moment.tz(input, timeZone); // get a *specific* time in the time zone.
    // or
    var m = someOtherMomentObject.clone().tz(timeZone); // convert to the time zone.
    
    var n = m.utcOffset();  // 60  (minutes West of GMT at the given point in time)
    
    var s = m.format('Z');  // "+01:00"  (offset as a string in ISO-8601 format)
    

    【讨论】:

      【解决方案2】:

      Etc/GMT-1 是一种标准格式。 Apple 有相关文档:Documentation

      仅供参考,正如this Stackoverflow answear 所说,Etc/GMT-1 应转换为 GMT+1。 如果您的输入总是 Etc/GMT#,您可以通过编写自己的单行函数来提取它:

      function extract(input_string){
          return input_string.substring(input_string.indexOf("Etc/GMT")+7);
      }
      

      【讨论】:

      • Apple 有一份它的副本。链接到的更好的副本是the one on GitHub held by Paul Eggert(当前的tzdb 维护者)。官方的tzdb 版本是here。此外,出于我在回答中指出的原因,我强烈反对从字符串中提取值。
      【解决方案3】:

      如果你也安装moment-timezone,你可以获得区域的偏移量:

      var offsetHours = moment.tz.zone("Etc/GMT-1").offsets[0] / 60
      

      offsetHours 变量的值将是-1。请注意,我必须除以 60,因为 API 以分钟为单位返回值。


      正如马特在 cmets 中提醒的那样,通常时区有多个有效偏移量,具体取决于日期 - 由于夏令时更改,甚至政客决定更改其国家的偏移量 - 所以最好根据具体瞬间,如documentation中所述:

      moment.tz.zone('Etc/GMT-1').offset(1403465838805);
      

      参数1403465838805是距离1970-01-01T00:00Z的毫秒数。

      特别是Etc/GMT 时区,因为它们没有偏移变化,所以没有区别,但对于其他时区,最好使用瞬间。

      【讨论】:

      • 谨慎使用这种方法。对于Etc/GMT* 区域,您可以使用第一个偏移量。但对于其他区域,第一个条目可能是 LMT 值。最好在特定时间点询问偏移量,而不是评估偏移量数组。
      • @MattJohnson 确实!我已将此信息添加到答案中,非常感谢!
      【解决方案4】:

      遇到了同样的问题,所以创建了一个带有 [ label, value ] 的数组用于自动完成。享受吧。

      // npm install -S moment-timezone
      
      import moment from 'moment-timezone'
      import timezones from '<path-to-node_modules>/node_modules/moment-timezone/data/unpacked/latest.json'
      
      // Build Timezone Array for autocomplete
      const TIMEZONES = timezones.zones.map( i => {
        let abbrs = i.abbrs.filter((el, index) => i.abbrs.indexOf(el) === index)
        return { label : `${i.name.replace('_',' ')} ( ${abbrs} )`, value: i.name}
      })

      【讨论】:

        猜你喜欢
        • 2015-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-23
        • 2016-07-24
        • 2023-03-14
        • 1970-01-01
        • 2020-08-28
        相关资源
        最近更新 更多