Python:strftime() UTC 偏移量在 Windows 中无法按预期工作

Posted

技术标签:

【中文标题】Python:strftime() UTC 偏移量在 Windows 中无法按预期工作【英文标题】:Python: strftime() UTC Offset Not working as Expected in Windows 【发布时间】:2014-09-30 23:43:17 【问题描述】:

每次使用:

time.strftime("%z")

我明白了:

Eastern Daylight Time

但是,我想要 +HHMM 或 -HHMM 形式的 UTC 偏移量。我什至尝试过:

time.strftime("%Z")

仍然产生:

Eastern Daylight Time

我已阅读与 strftime() 相关的其他几篇文章,并且 %z 似乎总是以正确的 +HHMM 或 -HHMM 格式返回 UTC 偏移量。如何让 strftime() 以 python 3.3 的 +HHMM 或 -HHMM 格式输出?

编辑:我正在运行 Windows 7

【问题讨论】:

我无法重现您观察到的内容:In [2]: time.strftime("%z") Out[2]: '-0500'。你能给我们更多的细节吗?你在说什么contradicts the documentation。 @PatrickCollins 我也没有得到偏移量,而是 'Mitteleuropäische Sommerzeit'(Windows 8、Python 2.7、3.3 和 3.4)。 对于 Python 2.6.6、2.7.2、3.2.2 和 3.3.2,我在 Windows 7 time.strftime("%z") -> "Eastern Daylight Time" 上得到了类似的结果。 很遗憾,Windows 下的库不支持%z,Python 依赖于这些库。见msdn.microsoft.com/en-us/library/fe06s4ak.aspx Window 对%z 的错误结果是一个未解决的错误:bugs.python.org/issue20010 【参考方案1】:

有关正确的解决方案,请参阅abarnert’s answer below。


您可以使用time.altzone 以秒为单位返回负偏移量。例如,我现在在 CEST (UTC+2),所以我得到这个:

>>> time.altzone
-7200

并把它放在你想要的格式:

>>> ':0>2:0>2'.format('-' if time.altzone > 0 else '+', abs(time.altzone) // 3600, abs(time.altzone // 60) % 60)
'+0200'

正如 cmets 中提到的 abarnert,time.altzone 在 DST 处于活动状态时给出偏移量,而 time.timezone 在 DST 处于非活动状态时给出。要确定使用哪个,您可以执行 J.F. Sebastian 建议的 in his answer to a different question。所以你可以像这样得到正确的偏移量:

time.altzone if time.daylight and time.localtime().tm_isdst > 0 else time.timezone

正如他所建议的那样,您可以在 Python 3 中使用以下内容来使用 datetime.timezone 获得所需的格式:

>>> datetime.now(timezone.utc).astimezone().strftime('%z')
'+0200'

【讨论】:

这是一个很好的答案。我编辑是因为您的代码有一些语法错误。我认为还值得指出 MarkRansom 的评论:“不幸的是,Windows 下的库不支持 %z,而 Python 依赖于这些库。参见 msdn.microsoft.com/en-us/library/fe06s4ak.aspx”跨度> @Raeven 您尝试的编辑没有解决任何问题,因此被拒绝。 // 是整数除法,是 Python 中的有效运算。您的编辑破坏了代码以产生所需的输出。 这很奇怪。当您的代码失败时,我的编辑运行良好。但是,我正在运行 Python 3。我猜你正在运行 Python 2? @Raeven 不,它适用于 Python 3 和 2。你得到什么错误? 我必须收回它。它现在对我有用。我第一次肯定没有完全复制你的文字。【参考方案2】:

使用time.timezone 获取以秒为单位的时间偏移量。

使用格式化:

("-" if time.timezone > 0 else "+") + time.strftime("%H:%M", time.gmtime(abs(time.timezone)))

将其转换为 +/-HH:MM 格式。

顺便说一句,这不应该是一个错误吗?根据strftimedocs.

我还认为this SO 答案可能会帮助您将区域偏移字符串转换为 HH:MM 格式。但由于"%z" 没有按预期工作,我觉得它没有实际意义。

注意:time.timezone 不受夏令时影响。

【讨论】:

考虑到问题是关于东部夏令时的偏移量,我认为他不想“对夏令时免疫”。 (不幸的是,我认为这个问题没有明确说明他实际上确实想要什么,但我不认为就是这样。)【参考方案3】:

在 2.x 中,如果您查看 time.strftime 的文档,他们甚至没有提及 %z。它根本不保证存在,更不用说跨平台保持一致了。事实上,正如footnote 1 所暗示的那样,它留给了C 的strftime 函数。另一方面,在3.x 中,他们确实提到了%z,并且解释它不能按您期望的方式工作的脚注并不容易看到;那是an open bug。

但是,在 2.6+(包括所有 3.x 版本)中,datetime.strftime 保证支持 %z 作为“+HHMM 或 -HHMM 形式的 UTC 偏移量(如果对象是幼稚的)。”因此,这是一个非常简单的解决方法:使用datetime 而不是time。究竟如何改变事情取决于你到底想做什么——使用Python-dateutiltz然后datetime.now(tz.tzlocal()).strftime('%z')是获取本地时区格式为格林威治标准时间偏移的方法,但如果你试图格式化完整的时候细节会有点不同。

如果您查看源代码,time.strftime 基本上只是检查格式字符串中是否为平台有效的说明符并调用本机 strftime 函数,而 datetime.strftime 对不同的说明符有一堆特殊处理,包括%z;特别是,它会在将内容传递给strftime 之前将%z 替换为utcoffset 的格式化版本。代码从 2.7 开始改过几次,甚至彻底重组过一次,但在 3.5 之前的主干中基本相同。

【讨论】:

在 Python 3 上,仅使用 stdlib:datetime.now(timezone.utc).astimezone().strftime('%z')【参考方案4】:

毫无疑问,此错误仍然存​​在,目前可用的最新 Windows 版本是 Win 10 Version 1703(Creators)。然而,随着时间的推移,有一个可爱的日期和时间库,名为pendulum,它可以满足问题的要求。 Sébastien Eustace(该产品的主要作者?)向我展示了这一点。

>>> pendulum.now().strftime('%z')
'-0400'

除非另有说明,否则钟摆假定为 UTC/GMT,并将时区与日期时间对象保持一致。还有许多其他可能性,其中包括:

>>> pendulum.now(tz='Europe/Paris').strftime('%z')
'+0200'
>>> pendulum.create(year=2016, month=11, day=5, hour=16, minute=23, tz='America/Winnipeg').strftime('%z')
'-0500'
>>> pendulum.now(tz='America/Winnipeg').strftime('%z')
'-0500'

【讨论】:

以上是关于Python:strftime() UTC 偏移量在 Windows 中无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

Python - 给定时间戳UTC和UTC偏移量的时区名称

Python 中给定 TimeZone 的标准 UTC 偏移量(无 DST)

在 Python 中获取计算机的 UTC 偏移量

在python中获取给定日期和UTC偏移量的GMT时间

如何在 python 和 django 中使用 Pytz 根据给定的 UTC 偏移量转换数据和时间?

从 UTC 偏移量获取时区名称