Django将UTC偏移用于当前时区

时间:2016-01-12 01:26:49

标签: django timezone

Django尝试通过在UTC内部存储日期并将其转换为客户端的时区进行显示来解决时区问题。理论上这听起来很好,直到你意识到两件大事:

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

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

问题在于:Django使用get_current_timezone()从最后一次调用timezone.activate()时从值集中检索数据。 timezone.activate()将timezone对象作为参数。

有没有办法只使用UTC偏移量timezone.activate()

1 个答案:

答案 0 :(得分: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中的“time zone!= offset”下阅读更多内容。

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

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

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