Django 时区:有点困惑
我们在设置中有一个时区叫做“Europe/Moscow”。
目前,这个时区意味着夏令时(将来可能会有所变化,但现在是UTC+03/04)。
我明白这个时区是在保存日期到数据库时使用的,也是在提取日期时使用的。
现在,我需要把日期时间对象转换成ISO格式的字符串,并且要包含UTC的偏移量。该怎么做才对呢?
这些日期并没有包含时区的信息(也就是说,d.strftime('%z')是空的)。
我想我可以把它们转换成UTC格式,然后用+00:00来表示,但如果我不知道具体的日期是+03(莫斯科的冬天)还是+04(莫斯科的夏天),我该怎么把它们转换成UTC呢?
3 个回答
ISO-8601 这个标准其实并没有涉及“时区”的概念,它只关注日期和时间。为了方便,有时候时间会带上一个“偏移量”。
更麻烦的是,datetime
这个模块对时区的支持也不是很完善;datetime 对象的 tzinfo 属性是可选的,而且主流的 Python 并没有提供这个接口的具体实现。
通常的解决办法是始终使用 UTC 时间来处理所有事情,包括服务器也要设置为 UTC,而不是本地时间。这其实是个不错的主意;因为不同的用户只是喜欢以不同的方式来看时间(就像有人喜欢用 '42' 而不是 '0b101010' 来表示同一个数字)。
为了满足用户(合理的!)想要在本地时区查看时间的需求,你可以把他们喜欢的时区单独存储(如果大家都在莫斯科,可以设置一个全站的偏好),然后使用一个强大的时区库(比如 pytz)来进行本地时间的格式转换。
首先,运行 new_dt = datetime.replace(tzinfo=tz)
来创建一个带有时区信息的新 datetime
对象。然后,你可以使用 datetime.strftime()
方法,并加上 %z
来格式化时间。
需要注意的是,你不能直接把日期字符串转换回带时区的 datetime
对象,因为 datetime.strptime()
不支持 %z
。所以,你需要先创建一个没有时区信息的 datetime
对象和一个 tzinfo
对象,然后像之前那样用 datetime.replace(tzinfo=tz)
来添加时区信息。
这里有一些有用的外部库:
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) 的问题。
如果我不知道具体日期是+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'