22

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

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

我知道如何将 UTC 字符串转换为日期。我了解 Javascript 仅代表本地时区的日期。

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

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

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

  1. 服务器将日期作为已在正确时区格式化的字符串发送,并且在客户端上不进行日期解析或操作。这使得在客户端上做某些事情即使不是不可能也很困难。
  2. 使用诸如https://github.com/mde/timezone-js之类的库,它将整个 Olson TZ 数据库包含到 Javascript 中。这意味着更长的加载时间更多的内存使用等。
  3. 将 timezoneOffsetMillis 值与发送给客户端的每个日期一起发送。这会导致混乱的 JSON 数据和非最佳的 REST 接口。

有没有更简单或更好的解决方案?

4

3 回答 3

5

2 是一个坏主意,因为正如您所指出的,它会增加加载时间。如果我是你,我会做 1 和 3 的组合。我不同意这会使 JSON 数据变得混乱或 REST 接口不是最佳的。

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

于 2011-02-05T05:07:04.067 回答
4

快进到 2015 年,当涉及到使用特定 locale 从其他时区格式化日期时,有两个选项。

在示例中,我使用法语语言环境并将使用 (UTC+5) 日期 2016 年 3 月 27 日 2h15 ,这在西欧没有观察到(由于 DST 变化,时钟从 2h00 移动到 3h00),这是常见的来源错误。

为了获得最大的可移植性,请使用moment.js库。Moment 附带80 多种语言环境

  1. 使用时间戳和 UTC 偏移量:

    moment(1459026900000).utcOffset(300).locale('fr').format("LLLL")
    // "dimanche 27 mars 2016 02:15"
    
  2. 使用整数数组(注意,月份是从 0 开始的,就像在原生 JS 日期对象中一样)

    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 时间),并且应该仅用于日期格式和显示 - 不应传递。

于 2015-11-04T14:04:46.573 回答
0

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

于 2011-03-16T09:17:18.583 回答