在Javascript中使用时区和夏令时

我的单页JavaScript应用程序通过REST调用以JSON格式检索数据。 日期使用标准ISO8601格式的UTC时区格式化,例如2011-02-04T19:31:09Z

在注册服务时,用户从下拉列表中选择他们的时区。 此时区可能与用户浏览器的时区不同。 JavaScript应用程序一直知道用户所选的时区是什么。

我知道如何将UTC字符串转换为日期。 我知道Javascript只代表当地时区的日期。

但是我遇到了麻烦,不知道如何显示格式化为用户本地时区以外的时区的日期 。 它必须在所有日期记录DST。 在内部,我想处理所有日期为UTC,并且只在显示时间转换为另一个时区中日期的字符串表示形式。 我需要显示用户个人资料中选择的时区中的日期,而不是他们浏览器的时区。

我已经尝试过用服务器发送用户浏览器时区和用户配置文件时区之间的时区偏移差(以毫秒为单位)。 但是我发现我不能只发送一个偏移值,但需要发送每个日期的偏移量来说明DST中的变化。

有关如何显示不同时区格式的日期的任何建议或示例代码? 我迄今为止发现的选项:

  • 服务器将日期作为已在正确时区格式化的字符串发送,并且不在客户端上完成日期解析或操作。 如果不是不可能的话,这就使得客户做某些事情变得困难。
  • 使用一个库,如https://github.com/mde/timezone-js,其中包括整个Olson TZ数据库到Javascript中。 这意味着更长的加载时间,更多的内存使用等
  • 发送到客户端的每个日期发送timezoneOffsetMillis值。 这会导致混乱的JSON数据和非最佳的REST接口。
  • 有没有更简单或更好的解决方案?


    2是一个坏主意,正如你指出的那样,它会增加加载时间。 如果我是你,我会做1和3的组合。我不同意这会导致JSON数据混乱或REST接口不是最优的。

    这是一个经典的权衡,为了简化客户端代码,在协议中接受更复杂的一点。


    快进到2015年,当涉及到使用特定区域设置格式化其他时区的日期时 ,有两种选择。

    在此示例中,我使用法语区域设置,并将使用2016年3月27日(UTC + 5)日期,2h15 ,这在西欧没有观察到(由于DST更改 ,时钟从2h00移至3h00),这是错误。

    为了获得最大的便携性,请使用moment.js库。 时刻与捆绑80+语言环境。

  • 使用时间戳和UTC偏移量:

    moment(1459026900000).utcOffset(300).locale('fr').format("LLLL")
    // "dimanche 27 mars 2016 02:15"
    
  • 使用整数数组(请注意,即时,月是基于0的,就像在本地JS Date对象中一样)

    moment.utc([2016,3-1,27,2,15]).locale('fr').format("LLLL")
    // "dimanche 27 mars 2016 02:15"
    
  • 您可以通过在http://momentjs.com/上的浏览器开发工具中运行代码来测试这些方法。

    这里最棘手的部分是使用moment.utc创建一个UTC标志的时刻日期对象,这意味着当该日期被格式化时,它不会被转换为用户的时区,而只是原样显示(并且由于UTC没有观察到DST,它不容易出现DST错误)。

    未来的本地解决方案:使用Intl对象

    (注意截至2015年底,Chrome,Firefox,IE11支持该解决方案,但Safari 9仍不支持该解决方案)

    使用整数数组:

        new Intl.DateTimeFormat('fr-FR', { timeZone: 'UTC', weekday: 'long',
              month: 'long', year: 'numeric', day: 'numeric', hour: 'numeric',
              minute: 'numeric' })
          .format(Date.UTC(2016,3-1,27,2,15))
        // "dimanche 27 mars 2016 02:15"
    

    这里的关键是再次使用Date.UTCtimeZone: 'UTC'来确保提供的日期不会转换为用户的本地时区。


    请注意,在这两种情况下,我们都使用UTC方法,只是为了确保日期不会被转换使用。 尽管意识到这些日期是假的UTC日期(它们表示给定的任意时区中的时间,而不是UTC时间),并且应仅用于日期格式化和显示,这一点很重要 - 不应该传递。


    有同样的问题。 我猜是#1解决方案。 您应该将特定容器中的日期(年,月,日,小时)的所有组件从客户端发送到服务器

    链接地址: http://www.djcxy.com/p/9623.html

    上一篇: Working with timezones and daylight savings time in Javascript

    下一篇: Data Mapper pattern: where to put a checkLogin method for a User Model?