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 格式。
顺便说一句,这不应该是一个错误吗?根据strftime
docs.
我还认为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 中给定 TimeZone 的标准 UTC 偏移量(无 DST)