如何制作时区感知日期时间对象

新手上路,请多包涵

我需要做什么

我有一个不知道时区的 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

首先,我尝试了 astimezone:

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

失败并不奇怪,因为它实际上是在尝试进行转换。替换似乎是一个更好的选择(根据 How do I get a value of datetime.today() in Python 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 进行解析),但这看起来非常笨拙。

另外,我在 Python 2.6 和 Python 2.7 中都尝试过,结果相同。

语境

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

原文由 Mark Tozzi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 581
2 个回答

一般来说,要让一个简单的 datetime 时区感知,使用 localize 方法

 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 。)

原文由 unutbu 发布,翻译遵循 CC BY-SA 3.0 许可协议

所有这些示例都使用外部模块,但您可以仅使用 datetime 模块获得相同的结果,如 本 SO 答案 中所示:

 from datetime import datetime, timezone

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

print(dt.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()

原文由 kang 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题