pytz 和 Etc/GMT-5

13 投票
3 回答
4738 浏览
提问于 2025-04-16 06:00

我在理解“Etc/GMT-5”时区和UTC之间的转换时遇到了一些问题。

>>> dt = datetime(2009, 9, 9, 10, 0) # September 9 2009, 10:00
>>> gmt_5 = pytz.timezone("Etc/GMT-5")
>>> gmt_5.localize(dt)
datetime.datetime(2009, 9, 9, 10, 0, tzinfo=<StaticTzInfo 'Etc/GMT-5'>)

到目前为止一切都很好,但当我尝试把它转换成UTC时:

>>> gmt_5.localize(dt).astimezone(pytz.utc)
datetime.datetime(2009, 9, 9, 5, 0, tzinfo=<UTC>)

所以对我来说,从GMT-5的10:00转换到UTC时,我得到的是05:00?我本来期待pytz会给我15:00。

我错过了什么吗?

编辑:我确认美国东部时区的转换效果正如我所期待的那样:

>>> eastern = pytz.timezone("US/Eastern")
>>> eastern.localize(dt)
datetime.datetime(2009, 9, 9, 10, 0, tzinfo=...) # Too long
>>> pytz.utc.normalize(eastern.localize(dt).astimezone(pytz.utc))
datetime.datetime(2009, 9, 9, 14, 0, tzinfo=<UTC>)

编辑2:我确认当我使用Etc/GMT+5时,我得到的是15:00,这正是我从Etc/GMT-5中期待得到的结果。这是pytz的一个bug吗?

3 个回答

1

为什么会出现这种时间反转?

你看到的这种情况是因为“IANA时区数据库”中对“Etc/GMT-5”时区的定义。“Etc/GMT-5”时区实际上是UTC偏移量的反向表示,这意味着它代表的是比UTC时间慢5小时的固定时区。

在“Etc/GMT-5”时区,正的偏移量表示比UTC时间慢,而负的偏移量则表示比UTC时间快。这和我们通常理解的时区表示方式正好相反。

当你使用“Etc/GMT-5”时区来本地化一个日期时间(dt)时,你实际上是把它设置为10:00,并且这个时间的UTC偏移量是-5小时。所以在“Etc/GMT-5”时区,10:00相当于UTC时间的15:00(10:00 - 5小时)。

但是,当你使用astimezone(pytz.timezone("UTC"))方法把这个本地时间转换为UTC时,它会考虑原时区的UTC偏移量。由于“Etc/GMT-5”时区的偏移量是-5小时,转换为UTC时实际上会在原时间上加5小时。所以,“Etc/GMT-5”中的10:00变成了UTC的05:00(10:00 + 5小时)。

这种行为与IANA时区数据库中对时区的定义是一致的,在那里“Etc/GMT”时区的偏移量是反向的。

解决方案/变通方法

如果你需要把一个GMT-5的日期时间转换为UTC 0,可以使用pytz库来处理时区转换。

这个策略就是反转你的GMT符号,也就是说,如果你想要“GMT-5”,那么你需要输入“GMT+5”(“Etc/GMT+5”)作为你想转换的日期时间的时区。

下面是你可以怎么做……

from datetime import datetime
import pytz


# Create a datetime object with a GMT-5 timezone.
gmt_minus_5_timezone = pytz.timezone("Etc/GMT+5")
gmt_minus_5_datetime = gmt_minus_5_timezone.localize(datetime(2023, 8, 1, 12, 0, 0))

# Convert the GMT-5 datetime to UTC (UTC+0).
utc_timezone = pytz.timezone("UTC")
utc_datetime = gmt_minus_5_datetime.astimezone(utc_timezone)

print(gmt_minus_5_datetime)
# Output: 2023-08-01 12:00:00-05:00 (Notice the -05:00, which represents GMT-5).

print(utc_datetime)
# Output: 2023-08-01 17:00:00+00:00 (The converted datetime in UTC, which is UTC+0).

谢谢!

1

这个错误报告解释了这种情况。显然,他们知道这个问题是反向的,但这样做是为了不破坏兼容性。

21

这显然是一个和POSIX有关的事情。根据维基百科的说法:

为了符合POSIX的标准,那些以“Etc/GMT”开头的时区,其符号和大多数人预期的正好相反。在这种标准下,位于GMT以西的时区是正号,而位于GMT以东的时区是负号。

撰写回答