Django尝试通过在UTC内部存储日期并将其转换为客户端的时区进行显示来解决时区问题。理论上这听起来很好,直到你意识到两件大事:
考虑到这两个问题,我假设一个简单的解决方案是完全忽略时区,DST等,而是依赖于客户端当前的UTC偏移量。在每个页面加载时,客户端上的JavaScript将使用客户端的当前UTC偏移更新客户端的cookie,Django中的中间件将为每个请求加载该值。
问题在于:Django使用get_current_timezone()
从最后一次调用timezone.activate()
时从值集中检索数据。 timezone.activate()
将timezone对象作为参数。
有没有办法只使用UTC偏移量timezone.activate()
?
答案 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”下阅读更多内容。
只有两种正确的方法可以处理这种情况:
使用jsTimeZoneDetect或moment-timezone等库来猜测浏览器的时区,然后让用户选择他们的时区,默认为猜测值。然后,您可以使用Django或其他任何方式在服务器端代码中使用选定或猜测的时区。
仅向客户端发送UTC,使用JavaScript在浏览器中执行从UTC到本地时间的转换。 (浏览器理解运行它的本地时区的行为,即使它识别它也有问题。)这里的问题是 - 旧的浏览器可能会转换为旧版本由于this bug,日期不正确。但在大多数情况下,这仍然是一种合理的方法。