为什么“datetime”模块在时区中以这种方式运行?

why does `datetime` module behave this way with timezones?

提问人:Jagerber48 提问时间:10/28/2023 最后编辑:FObersteinerJagerber48 更新时间:10/29/2023 访问量:75

问:

我正在尝试使用时间和时区。我所在的时区,并且我的计算机 (Windows) 配置为该时区。US/Mountain

import datetime
import zoneinfo

utc = zoneinfo.ZoneInfo('UTC')
mt = zoneinfo.ZoneInfo('US/Mountain')

print(datetime.datetime.now())
print(datetime.datetime.now().astimezone(mt))
print(datetime.datetime.now().astimezone(utc))

# 2023-10-27 13:17:18.840857
# 2023-10-27 13:17:18.840857-06:00
# 2023-10-27 19:17:18.840857+00:00

最后一行是让我感到困惑的那行。我以为代码会创建一个时区朴素对象,然后将其转换为时区感知对象,但不会改变时间的“值”。但在这里你可以看到,这会导致 6 小时被添加到时间值中,就好像 生成的时间是一个山地时间对象一样。datetime.datetime.now()astimezone(utc)astimezone(utc)datetime.datetime.now()

Python 日期时

评论

0赞 Scott Hunter 10/28/2023
所以你不这么认为,在不同的时区代表相同的时间?2023-10-27 13:17:18.840857-06:002023-10-27 19:17:18.840857+00:00
0赞 Corralien 10/28/2023
怎么了?您的幼稚时间与您的当地时间相同,因此 UTC 相差 6 小时。
0赞 Jagerber48 10/28/2023
@Corralien 幼稚的日期时间是否假定为本地时区?我以为幼稚的物体与“没有”时区相关联。
0赞 Suraj Shourie 10/28/2023
什么本地时间,没有时区的时间,甚至意味着什么?在此方案中,我假设选择系统时区作为默认时区datetime
4赞 Corralien 10/28/2023
@Jagerber48。否,幼稚日期/时间没有关联的时区,但如果您决定将其转换为可识别的日期/时间,则默认使用您的本地时区。如果要指定如何解释朴素的日期时间,请使用replaceastimezone

答:

2赞 Savir 10/28/2023 #1

答案不在于什么确实是返回一个没有的幼稚时区,而在于当提供的日期是幼稚时,该做什么。.now()tzinfo.astimezone

该方法将查找您的本地(您计算机的时区)并将其用于幼稚的日期时间。.astimezone

        mytz = self.tzinfo
        if mytz is None:
            mytz = self._local_timezone()
            myoffset = mytz.utcoffset(self)

链接到 GitHub 中的当前代码

因此,它将(sort-of/kinda/lots-of-buts)表现得好像您提供了本地化为计算机配置时区的日期时间。

1赞 Jagerber48 10/28/2023 #2

请参阅 astimezone 上的文档

返回一个带有新 tzinfo 属性 tz 的 datetime 对象,调整日期和时间数据,使结果与 self 的 UTC 时间相同,但采用 tz 的本地时间。

如果提供,tz 必须是 tzinfo 子类的实例,并且其 utcoffset() 和 dst() 方法不得返回 None。如果 self 是幼稚的,则假定它表示系统时区中的时间。

...

如果只想在不调整日期和时间数据的情况下将时区对象 tz 附加到日期时间 dt,请使用 。如果只想在不转换日期和时间数据的情况下从可识别的日期时间 dt 中删除时区对象,请使用 。dt.replace(tzinfo=tz)dt.replace(tzinfo=None)

如果我使用,我会得到预期的行为:replace

import datetime
import zoneinfo

utc = zoneinfo.ZoneInfo('UTC')
mt = zoneinfo.ZoneInfo('US/Mountain')

print(datetime.datetime.now())
print(datetime.datetime.now().replace(tzinfo=mt))
print(datetime.datetime.now().replace(tzinfo=utc))

# 2023-10-27 13:45:35.897159
# 2023-10-27 13:45:35.897159-06:00
# 2023-10-27 13:45:35.897159+00:00

我的代码中发生的事情是,当我使用模块时,确实会从我的系统时间推断出一个时区,然后使用该时区将时间转换为同一时间。 是用于在不进行调整的情况下“插入”时区的函数。astimezone()datetimeutcreplace