Django 时区:有点困惑

4 投票
3 回答
6002 浏览
提问于 2025-04-16 22:15

我们在设置中有一个时区叫做“Europe/Moscow”。

目前,这个时区意味着夏令时(将来可能会有所变化,但现在是UTC+03/04)。

我明白这个时区是在保存日期到数据库时使用的,也是在提取日期时使用的。

现在,我需要把日期时间对象转换成ISO格式的字符串,并且要包含UTC的偏移量。该怎么做才对呢?

这些日期并没有包含时区的信息(也就是说,d.strftime('%z')是空的)。

我想我可以把它们转换成UTC格式,然后用+00:00来表示,但如果我不知道具体的日期是+03(莫斯科的冬天)还是+04(莫斯科的夏天),我该怎么把它们转换成UTC呢?

3 个回答

1

ISO-8601 这个标准其实并没有涉及“时区”的概念,它只关注日期和时间。为了方便,有时候时间会带上一个“偏移量”。

更麻烦的是,datetime 这个模块对时区的支持也不是很完善;datetime 对象的 tzinfo 属性是可选的,而且主流的 Python 并没有提供这个接口的具体实现。

通常的解决办法是始终使用 UTC 时间来处理所有事情,包括服务器也要设置为 UTC,而不是本地时间。这其实是个不错的主意;因为不同的用户只是喜欢以不同的方式来看时间(就像有人喜欢用 '42' 而不是 '0b101010' 来表示同一个数字)。

为了满足用户(合理的!)想要在本地时区查看时间的需求,你可以把他们喜欢的时区单独存储(如果大家都在莫斯科,可以设置一个全站的偏好),然后使用一个强大的时区库(比如 pytz)来进行本地时间的格式转换。

3

首先,运行 new_dt = datetime.replace(tzinfo=tz) 来创建一个带有时区信息的新 datetime 对象。然后,你可以使用 datetime.strftime() 方法,并加上 %z 来格式化时间。

需要注意的是,你不能直接把日期字符串转换回带时区的 datetime 对象,因为 datetime.strptime() 不支持 %z。所以,你需要先创建一个没有时区信息的 datetime 对象和一个 tzinfo 对象,然后像之前那样用 datetime.replace(tzinfo=tz) 来添加时区信息。

这里有一些有用的外部库:

http://pytz.sourceforge.net/

http://code.google.com/p/parsedatetime/

http://labix.org/python-dateutil

你也可以在 Stack Overflow 上搜索更多关于 (Python OR django OR appengine) AND (datetime OR timezone OR date OR time OR tzinfo) 的问题。

5

如果我不知道具体日期是+03(莫斯科冬季)还是+04(莫斯科夏季),我该如何将它们转换为UTC时间呢?

其实不需要手动转换成UTC,pytz这个库会帮你处理这些问题。

下面是将没有时区信息的日期时间转换为带时区偏移的ISO格式的代码:

from datetime import datetime
from pytz import timezone

server_timezone = timezone('Europe/Moscow')

server_timezone.localize(datetime(2011, 1, 1)).isoformat()
>>> '2011-01-01T00:00:00+03:00'

server_timezone.localize(datetime(2011, 7, 1)).isoformat()
>>> '2011-07-01T00:00:00+04:00'

撰写回答