【问题标题】:Django use UTC offsets for current timezoneDjango 使用当前时区的 UTC 偏移量
【发布时间】:2016-01-12 01:26:49
【问题描述】:

Django 尝试通过在内部以 UTC 存储日期并将其转换为客户端的时区来显示来解决时区问题。这在理论上听起来不错,直到您意识到两个主要的事情:

  • 许多时区可以并且确实存在于同一 UTC 偏移量内。
  • 由于没有时区HTTP头,我们需要手动确定客户端的时区,这需要使用JavaScript。但是,JavaScript 只能可靠地确定客户端的 UTC 偏移量,可能无法猜出正确的时区。

考虑到这两个问题,我假设一个简单的解决方案是完全忽略时区、DST 等,而是依赖客户端当前的 UTC 偏移量。在每次页面加载时,客户端上的 JavaScript 将使用客户端当前的 UTC 偏移量更新客户端的 cookie,而 Django 中的中间件将为每个请求加载该值。

这是问题所在:Django 使用 get_current_timezone() 从上次调用 timezone.activate() 时设置的值中检索数据。 timezone.activate() 将时区对象作为参数。

有没有办法使用timezone.activate() 仅带有 UTC 偏移量?

【问题讨论】:

  • "但是,JavaScript 只能可靠地确定客户端的 UTC 偏移量,可能无法猜出正确的时区。"好吧,它只能确定客户端在任意时间点的UTC偏移量。即使现在有多个时区具有相同的 UTC 偏移量,这通常也可用于检测正确的时区。

标签: django timezone


【解决方案1】:

您描述的解决方案是获取客户端当前的 UTC 偏移量并通过 cookie 或其他某种机制发送回服务器,这是一种常见的方法。不幸的是,它有缺陷。仅仅因为人们这样做并不意味着它是一个好主意。

问题在于您从客户端收集的偏移量是针对特定时间的。但是,您可能不会在服务器上使用同一时间。

例如,您可以在客户端调用new Date().getTimezoneOffset(),它会为您提供480 的值,即UTC 以西480 分钟,或者UTC-08:00(注意符号反转)。因此,您将 480 传递给服务器,以 UTC 从数据库加载日期,并应用偏移量。除了,您加载的日期可能是几个月前的日期,而那个日期的客户偏移量是UTC-07:00。因此,您应用了错误的偏移量,并且生成的结果值与应有的值相差一个小时。

时区不能仅通过偏移量来识别。时区标识符看起来像"America/Los_Angeles",而不仅仅是UTC-8。这是一个非常常见的错误。在the timezone tag wiki 中的“时区!= 偏移量”下阅读更多信息。

处理这种情况只有两种正确的方法:

  1. 使用jsTimeZoneDetectmoment-timezone 之类的库猜测浏览器的时区,然后让用户选择他们的时区,默认为猜测值。然后,您可以在您的服务器端代码中使用选定或猜测的时区与 Django 或其他任何东西。

  2. 仅向客户端发送 UTC,在浏览器中使用 JavaScript 将 UTC 转换为本地时间。 (浏览器了解其运行的本地时区的行为,即使它在识别时遇到问题。)这里的问题是 - 旧浏览器可能会转换旧浏览器由于this bug,日期不正确。但在大多数情况下,这仍然是一种合理的方法。

【讨论】:

  • 这正是我需要看到的。最终,我是否让用户选择他们的时区,而不是根据时刻时区的猜测,取决于平衡用户友好性和用户需求与系统中这些日期的重要性。我不认为日期的准确性会如此重要,以至于我不能依赖有根据的猜测。
  • 仅供参考 - tz 猜测刚刚添加到上一个版本中,所以如果您有文件问题,请执行此操作。 API 是moment.tz.guess()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
  • 2017-10-18
  • 2014-02-04
  • 2016-04-24
  • 2018-03-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多