在Python中将时区感知的日期时间转换为本地时间

60 投票
5 回答
83237 浏览
提问于 2025-04-16 14:32

如何将一个带时区的日期时间对象转换为本地时区的相应不带时区的日期时间对象?

我这个应用程序使用的是Django(不过,这实际上是一个通用的Python问题):

import iso8601

....

date_str="2010-10-30T17:21:12Z"

....

d = iso8601.parse_date(date_str)

foo = app.models.FooModel(the_date=d)
foo.save()

这导致Django抛出一个错误:

raise ValueError("MySQL backend does not support timezone-aware datetimes.")

我需要的是:

d = iso8601.parse_date(date_str)
local_d = SOME_FUNCTION(d)
foo = app.models.FooModel(the_date=local_d)

SOME_FUNCTION应该是什么呢?

5 个回答

3

一个便携且可靠的解决方案应该使用时区数据库。要获取本地时区,可以使用pytztzinfo对象,建议使用tzlocal模块

#!/usr/bin/env python
import iso8601
import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
aware_dt = iso8601.parse_date("2010-10-30T17:21:12Z") # some aware datetime object
naive_local_dt = aware_dt.astimezone(local_timezone).replace(tzinfo=None)

注意:可能会有人想用类似下面的方式:

#!/usr/bin/env python3
# ...
naive_local_dt = aware_dt.astimezone().replace(tzinfo=None)

但如果本地时区的UTC偏移量是变化的,而Python在某个平台上没有使用历史时区数据库,这种方法可能会失败。

75

在最近的Django版本中(至少是1.4.1):

from django.utils.timezone import localtime

result = localtime(some_time_object)
98

一般来说,如果想把一个带时区的日期时间转换成不带时区的(本地)日期时间,我会使用 pytz 模块和 astimezone 方法来转换成本地时间,然后用 replace 方法把日期时间变成不带时区的:

In [76]: import pytz

In [77]: est=pytz.timezone('US/Eastern')

In [78]: d.astimezone(est)
Out[78]: datetime.datetime(2010, 10, 30, 13, 21, 12, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)

In [79]: d.astimezone(est).replace(tzinfo=None)
Out[79]: datetime.datetime(2010, 10, 30, 13, 21, 12)

不过,因为你提到的这个日期时间似乎是在 UTC 时区,所以你可以这样做:

In [65]: d
Out[65]: datetime.datetime(2010, 10, 30, 17, 21, 12, tzinfo=tzutc())

In [66]: import datetime

In [67]: import calendar

In [68]: datetime.datetime.fromtimestamp(calendar.timegm(d.timetuple()))
Out[68]: datetime.datetime(2010, 10, 30, 13, 21, 12)

顺便说一下,存储日期时间时,使用不带时区的 UTC 日期时间可能更好,而不是不带时区的本地日期时间。这样,你的数据就和本地时间无关,只有在必要的时候才转换成本地时间或其他时区。这有点像尽量使用 Unicode,只有在必要时才进行编码。

所以如果你同意存储不带时区的 UTC 日期时间是最好的方法,那么你只需要定义:

local_d = d.replace(tzinfo=None)

撰写回答