如何在python中使不知道日期时间的时区知道

2024-04-26 11:31:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要做什么

我有一个不知道时区的datetime对象,为了能够将它与其他知道时区的datetime对象进行比较,我需要添加一个时区。我不想将我的整个应用程序转换为不知道这个遗留案例的时区。

我尝试过的

首先,为了说明问题:

Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> import pytz
>>> unaware = datetime.datetime(2011,8,15,8,15,12,0)
>>> unaware
datetime.datetime(2011, 8, 15, 8, 15, 12)
>>> aware = datetime.datetime(2011,8,15,8,15,12,0,pytz.UTC)
>>> aware
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> aware == unaware
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes

首先,我试过阿斯蒂美宗:

>>> unaware.astimezone(pytz.UTC)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: astimezone() cannot be applied to a naive datetime
>>>

这次失败并不奇怪,因为它实际上是在试图进行一次转换。替换似乎是一个更好的选择(根据Python: How to get a value of datetime.today() that is "timezone aware"?):

>>> unaware.replace(tzinfo=pytz.UTC)
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> unaware == aware
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
>>> 

但正如您所看到的,replace似乎设置了tzinfo,但没有使对象意识到。我已经准备好在解析输入字符串之前对其进行修改,使其具有时区(如果重要的话,我将使用dateutil进行解析),但这似乎是难以置信的笨拙。

另外,我在Python2.6和Python2.7中都尝试过这种方法,结果是一样的。

上下文

我正在为一些数据文件编写解析器。如果日期字符串没有时区指示器,则需要支持旧格式。我已经修复了数据源,但仍然需要支持遗留数据格式。由于各种业务BS的原因,不能一次性转换遗留数据。一般来说,我不喜欢硬编码默认时区的想法,在这种情况下,它似乎是最好的选择。我有充分的信心知道所有的遗留数据都是UTC格式的,所以我准备接受在这种情况下违约的风险。


Tags: 对象mostdatetimestdincallfileoffsetlast
3条回答

一般来说,要使原始日期时区知道,请使用localize method

import datetime
import pytz

unaware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0)
aware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0, pytz.UTC)

now_aware = pytz.utc.localize(unaware)
assert aware == now_aware

对于UTC时区,实际上不需要使用localize,因为没有夏令时计算要处理:

now_aware = unaware.replace(tzinfo=pytz.UTC)

有效。(.replace返回一个新的日期时间;它不修改unaware。)

我从警觉到警觉

dt_unaware = dt_aware.replace(tzinfo=None)

你知道吗

from pytz import timezone
localtz = timezone('Europe/Lisbon')
dt_aware = localtz.localize(dt_unware)

但之前的回答也是一个很好的解决方案。

所有这些示例都使用外部模块,但是您可以仅使用datetime模块来实现相同的结果,如this SO answer

from datetime import datetime
from datetime import timezone

dt = datetime.now()
dt.replace(tzinfo=timezone.utc)

print(dt.replace(tzinfo=timezone.utc).isoformat())
'2017-01-12T22:11:31+00:00'

依赖性更少,没有pytz问题。

注意:如果您希望将其与python3和python2一起使用,也可以将其用于时区导入(硬编码为UTC):

try:
    from datetime import timezone
    utc = timezone.utc
except ImportError:
    #Hi there python2 user
    class UTC(tzinfo):
        def utcoffset(self, dt):
            return timedelta(0)
        def tzname(self, dt):
            return "UTC"
        def dst(self, dt):
            return timedelta(0)
    utc = UTC()

相关问题 更多 >