Django 使用当前时区的 UTC 偏移量

Django use UTC offsets for current timezone

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

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

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

有没有一种方法可以仅使用 UTC 偏移来使用 timezone.activate()

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

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

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

不能仅通过偏移量来识别时区。时区标识符看起来像 "America/Los_Angeles",而不仅仅是 UTC-8。这是一个很常见的错误。在 the timezone tag wiki.

的 "time zone != offset" 下阅读更多内容

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

  1. 使用像 jsTimeZoneDetect or moment-timezone 这样的库来 猜测 浏览器的时区,然后让用户选择他们的时区,默认为猜测值。然后,您可以在 server-side 代码中将所选或猜测的时区与 Django 或其他软件一起使用。

  2. 只向客户端发送 UTC,在浏览器中使用 JavaScript 将 UTC 时间转换为本地时间。 (浏览器理解 行为 它所在的本地时区 运行,即使它很难 识别 它。)这里要注意的是 - 由于 this bug,较旧的浏览器可能会错误地转换较旧的日期。但在大多数情况下,这仍然是一种合理的方法。