我很好奇如何打电话给#34;规范"在某些时区选择器上提供的时区偏移(如果有甚至这样的事情,作为规范偏移,我甚至不确定)。
例如,在Windows XP上,您可以看到,对于Eastern Time (US & Canada)
,下拉列表始终显示GMT-05:00
这实际上在全年都不正确,因为当夏令时生效时, UTC
的偏移量仅为-4:00
。另一方面,每个人都提到US/Eastern
距离UTC 5小时。我想知道如何调用-5:00
。电子邮件时间标识符?典型的时区偏移?
此外,如果我使用pytz创建US/Eastern
时区,是否可以抓取-5:00
,无论实际的现在时间是否在DST与否?我的意思是......我想知道是否有某种功能,或者某种东西可以获得-5:00
,无论我今天或在中间运行8月(启用DST
且实际偏移量仅为-4:00
)
的图片
提前谢谢。
答案 0 :(得分:2)
如果我们将“规范”表示不在DST中的日期的utcoffset,则问题将减少为查找不是DST的日期(对于每个时区)。
我们可以先尝试当前日期。如果不是DST,那么我们很幸运。如果是,那么我们可以逐步查看utc过渡日期列表(存储在tzone._utc_transition_times
中)直到我们找到一个不是DST的日期:
import pytz
import datetime as DT
utcnow = DT.datetime.utcnow()
canonical = dict()
for name in pytz.all_timezones:
tzone = pytz.timezone(name)
try:
dstoffset = tzone.dst(utcnow, is_dst=False)
except TypeError:
# pytz.utc.dst does not have a is_dst keyword argument
dstoffset = tzone.dst(utcnow)
if dstoffset == DT.timedelta(0):
# utcnow happens to be in a non-DST period
canonical[name] = tzone.localize(utcnow, is_dst=False).strftime('%z')
else:
# step through the transition times until we find a non-DST datetime
for transition in tzone._utc_transition_times[::-1]:
dstoffset = tzone.dst(transition, is_dst=False)
if dstoffset == DT.timedelta(0):
canonical[name] = (tzone.localize(transition, is_dst=False)
.strftime('%z'))
break
for name, utcoffset in canonical.iteritems():
print('{} --> {}'.format(name, utcoffset))
# All timezones have been accounted for
assert len(canonical) == len(pytz.all_timezones)
产量
...
Mexico/BajaNorte --> -0800
Africa/Kigali --> +0200
Brazil/West --> -0400
America/Grand_Turk --> -0400
Mexico/BajaSur --> -0700
Canada/Central --> -0600
Africa/Lagos --> +0100
GMT-0 --> +0000
Europe/Sofia --> +0200
Singapore --> +0800
Africa/Tripoli --> +0200
America/Anchorage --> -0900
Pacific/Nauru --> +1200
请注意,上面的代码访问私有属性tzone._utc_transition_times
。这是pytz中的实现细节。由于它不是公共API的一部分,因此不保证在未来版本的pytz中存在。实际上,对于当前版本的pytz中的所有时区都不存在 - 特别是,对于没有DST转换时间的时区,例如'Africa/Bujumbura'
,它不存在。 (这就是我为什么要先检查utcnow是否恰好在非DST时间段内的原因。)
如果您想要一种不依赖私有属性的方法,我们可以简单地将utcnow
游回一天,直到我们找到一个非DST时间段的日子。代码会比上面的代码慢一点,但是因为你真的只需要运行一次这段代码来收集所需的信息,所以它真的无关紧要。
以下是不使用_utc_transition_times
代码的代码:
import pytz
import datetime as DT
utcnow = DT.datetime.utcnow()
canonical = dict()
for name in pytz.all_timezones:
tzone = pytz.timezone(name)
try:
dstoffset = tzone.dst(utcnow, is_dst=False)
except TypeError:
# pytz.utc.dst does not have a is_dst keyword argument
dstoffset = tzone.dst(utcnow)
if dstoffset == DT.timedelta(0):
# utcnow happens to be in a non-DST period
canonical[name] = tzone.localize(utcnow, is_dst=False).strftime('%z')
else:
# step through the transition times until we find a non-DST datetime
date = utcnow
while True:
date = date - DT.timedelta(days=1)
dstoffset = tzone.dst(date, is_dst=False)
if dstoffset == DT.timedelta(0):
canonical[name] = (tzone.localize(date, is_dst=False)
.strftime('%z'))
break
for name, utcoffset in canonical.iteritems():
print('{} --> {}'.format(name, utcoffset))
# All timezones have been accounted for
assert len(canonical) == len(pytz.all_timezones)