Python Django时区:感觉有点困惑

Python Django时区:感觉有点困惑,python,django,datetime,timezone,utc,Python,Django,Datetime,Timezone,Utc,因此,我们的环境中有“欧洲/莫斯科”TZ。 目前,这意味着夏时制(这在未来将会改变,但目前是UTC+03/04) 我知道在将日期保存到数据库和提取日期时会使用此TZ 现在,我必须将datetime对象序列化为ISO字符串,包括UTC偏移量。正确的做法是什么 日期不包含TZ信息(即d.strftime(“%z”)为空) 我想我可以将它们转换为UTC并以+00:00进行序列化,但是如果我不知道具体日期是+03(莫斯科冬季)还是+04(莫斯科夏季)第一次运行new\u dt=datetime.repl

因此,我们的环境中有“欧洲/莫斯科”TZ。 目前,这意味着夏时制(这在未来将会改变,但目前是UTC+03/04)

我知道在将日期保存到数据库和提取日期时会使用此TZ

现在,我必须将datetime对象序列化为ISO字符串,包括UTC偏移量。正确的做法是什么

日期不包含TZ信息(即d.strftime(“%z”)为空)


我想我可以将它们转换为UTC并以+00:00进行序列化,但是如果我不知道具体日期是+03(莫斯科冬季)还是+04(莫斯科夏季)

第一次运行
new\u dt=datetime.replace(tzinfo=tz)
来创建一个新的时区感知
datetime
。然后用
%z
运行
datetime.strftime()

请注意,然后不能将日期字符串直接转换回时区感知的日期时间--
datetime。strtime()
不支持
%z
。因此,您需要创建一个简单的
datetime
和一个
tzinfo
,然后像以前一样执行
datetime.replace(tzinfo=tz)

一些有用的外部库:

另外,请尝试在堆栈溢出上搜索更多关于(Python或django或appengine)和(datetime或timezone或date或time或tzinfo)的问题。

ISO-8601没有“时区”的概念,只有日期和时间,为了方便起见,时间可以用“偏移量”表示

更让人恼火的是,
datetime
只是半心半意地点头承认时区;datetime对象上的tzinfo属性是可选的,主线python不提供该接口的任何实现

对此的标准答案是始终在UTC中执行所有操作;包括将服务器设置为UTC,而不是本地时间。这其实是个不错的主意;不同的不是时间,而是个人用户更喜欢阅读这些时间的方式(这类似于更喜欢“42”而不是“0b101010”)

您可以将首选时区(如果每个人都在莫斯科,可能只是一个站点范围内的首选时区)与实际时间分开存储,以满足用户(合理!)查看本地时区时间的愿望,然后您可以使用一个强大的时区库(如)对本地时间进行格式化

如果我不知道具体日期是+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'

这些都是正确和可以理解的。不幸的是,该站点已经运行了一段时间(我刚刚加入团队),日期已经在Django存储的数据库中,欧洲/莫斯科处于设置中。那么,我能从这些数据中恢复UTC时间吗?这是你的问题吗?从您最初的问题中不清楚您是否正在尝试将数据库从localtime迁移到UTC。如果是这样,你应该更新你的问题。我不是在迁移数据库。我必须以ISO格式输出数据库中具有正确偏移量的日期时间。我认为,问题的最后一句明确指出:“如果我不知道具体日期是+03(莫斯科冬季)还是+04(莫斯科夏季)”,那么如何将它们转换为UTC,方法是说
new\u dt=datetime.replace(tzinfo=tz)
你所说的
tz
是什么意思?我知道这个日期是Django为了“欧洲/莫斯科”而保存的。我如何将其转换为UTC/什么?什么应该被传递为
tz
?看看它发布的
pytz
链接,它有一堆
tzinfo
项,用于实时时区,你可以作为
tzinfo
部分传递到该函数。我接受了@sayap更具体的回答,但我感谢你的早期提示,并在这里投了赞成票。