Python:给定时区名称的所有可能时区缩写(反之亦然)
Python: All possible Timezone Abbreviations for given Timezone Name (and vise versa)
使用 pytz
,我知道如何获取列表 时区名称,但我想获取 所有每个时区名称可能时区缩写:
import pytz
list(pytz.common_timezones)
['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa',...]
我正在寻找的是任何 时区缩写,例如 PST 或 PDT ,忽略当前日期时间(例如现在),return 所有可能的 时区名称 ,在这种情况下,列表将包括 America/Los_Angeles.
谢谢
我使用 datetime
模块的 strftime
函数执行此操作,因为它有一个 %Z
格式说明符 returns 时区缩写。这是一个 filter
语句,可以满足您的需要:
>>> filter(lambda x: datetime.datetime.now(pytz.timezone(x)).strftime("%Z") == "PDT", pytz.common_timezones)
['America/Dawson',
'America/Los_Angeles',
'America/Tijuana',
'America/Vancouver',
'America/Whitehorse',
'Canada/Pacific',
'US/Pacific']
您可以将 "PDT"
替换为您需要的任何时区。请记住,您还需要导入 datetime
.
import pytz
for tzname in list(pytz.common_timezones):
print(pytz.timezone(tzname)._tzname)
Similar question
既然你想忽略当前的日期时间,听起来你想找
在 的任何时间使用给定缩写的任何时区
过去。该信息在 Olson 数据库中,可通过
皮茨。但是,pytz 将此信息存储在 private 属性中,
tzone._transition_info
:
import collections
import datetime as DT
import pytz
tzones = collections.defaultdict(set)
abbrevs = collections.defaultdict(set)
for name in pytz.all_timezones:
tzone = pytz.timezone(name)
for utcoffset, dstoffset, tzabbrev in getattr(
tzone, '_transition_info', [[None, None, DT.datetime.now(tzone).tzname()]]):
tzones[tzabbrev].add(name)
abbrevs[name].add(tzabbrev)
gettattr
的第三个(默认)参数是为了处理一些
时区,例如 Africa/Bujumbura
,从来没有任何转换。所以
这些情况下的缩写是当前缩写。
In [94]: tzones['PST']
Out[94]:
{'America/Bahia_Banderas',
'America/Boise',
'America/Creston',
'America/Dawson',
'America/Dawson_Creek',
'America/Ensenada',
'America/Hermosillo',
'America/Inuvik',
'America/Juneau',
'America/Los_Angeles',
'America/Mazatlan',
'America/Metlakatla',
'America/Santa_Isabel',
'America/Sitka',
'America/Tijuana',
'America/Vancouver',
'America/Whitehorse',
'Canada/Pacific',
'Canada/Yukon',
'Mexico/BajaNorte',
'Mexico/BajaSur',
'PST8PDT',
'Pacific/Pitcairn',
'US/Pacific',
'US/Pacific-New'}
In [95]: tzones['PDT']
Out[95]:
{'America/Boise',
'America/Dawson',
'America/Dawson_Creek',
'America/Ensenada',
'America/Juneau',
'America/Los_Angeles',
'America/Metlakatla',
'America/Santa_Isabel',
'America/Sitka',
'America/Tijuana',
'America/Vancouver',
'America/Whitehorse',
'Canada/Pacific',
'Canada/Yukon',
'Mexico/BajaNorte',
'PST8PDT',
'US/Pacific',
'US/Pacific-New'}
In [97]: abbrevs['America/Los_Angeles']
Out[97]: {'LMT', 'PDT', 'PPT', 'PST', 'PWT'}
与 一样,请注意时区缩写是不明确的——它们不一定映射到具有相同 utcoffset 的时区。例如,Asia/Shanghai
和 US/Central
都使用 CST
时区缩写。
In [242]: 'Asia/Shanghai' in tzones['CST']
Out[242]: True
In [243]: 'US/Central' in tzones['CST']
Out[243]: True
我喜欢 unutbu 的回答,这使我找到了对我有用的答案。我有用户的语言环境,所以我发现我可以用它来消除时区缩写之间的歧义。
换句话说,这解决了以下问题:
In [242]: 'Asia/Shanghai' in tzones['CST']
Out[242]: True
In [243]: 'US/Central' in tzones['CST']
Out[243]: True
此功能需要两个字母的国家代码:
def GetTimeZoneName(timezone, country_code):
#see if it's already a valid time zone name
if timezone in pytz.all_timezones:
return timezone
#if it's a number value, then use the Etc/GMT code
try:
offset = int(timezone)
if offset > 0:
offset = '+' + str(offset)
else:
offset = str(offset)
return 'Etc/GMT' + offset
except ValueError:
pass
#look up the abbreviation
country_tzones = None
try:
country_tzones = pytz.country_timezones[country_code]
except:
pass
set_zones = set()
if country_tzones is not None and len(country_tzones) > 0:
for name in country_tzones:
tzone = pytz.timezone(name)
for utcoffset, dstoffset, tzabbrev in getattr(tzone, '_transition_info', [[None, None, datetime.datetime.now(tzone).tzname()]]):
if tzabbrev.upper() == timezone.upper():
set_zones.add(name)
if len(set_zones) > 0:
return min(set_zones, key=len)
# none matched, at least pick one in the right country
return min(country_tzones, key=len)
#invalid country, just try to match the timezone abbreviation to any time zone
for name in pytz.all_timezones:
tzone = pytz.timezone(name)
for utcoffset, dstoffset, tzabbrev in getattr(tzone, '_transition_info', [[None, None, datetime.datetime.now(tzone).tzname()]]):
if tzabbrev.upper() == timezone.upper():
set_zones.add(name)
return min(set_zones, key=len)
这 returns CST 的正确时区:
>>> GetTimeZoneName('CST','CN')
'Asia/Shanghai'
>>> GetTimeZoneName('CST','US')
'America/Detroit'
更新 py3.9+(如 PEP615), the new zoneinfo 模块中所讨论可能有帮助:
from collections import defaultdict
from datetime import datetime as dt
from zoneinfo import available_timezones, ZoneInfo
now = dt.utcnow()
tz_key = lambda tz: ZoneInfo(tz).tzname(now)
tz_map = defaultdict(list)
for tz in available_timezones():
tz_map[tz_key(tz)].append(tz)
tz_map = {k: sorted(v) for k, v in tz_map.items()}
例如,print(tz_map['PDT'])
会产生:['America/Ensenada', 'America/Los_Angeles', 'America/Santa_Isabel', 'America/Tijuana', 'America/Vancouver', 'Canada/Pacific', 'Mexico/BajaNorte', 'PST8PDT', 'US/Pacific', 'US/Pacific-New']
注意:时区来自 locally-installed 时区数据。您还可以添加第一方 tzdata 库(不在标准库中,但由 python 的核心开发人员维护:使用 pip install tzdata
)。
使用 pytz
,我知道如何获取列表 时区名称,但我想获取 所有每个时区名称可能时区缩写:
import pytz
list(pytz.common_timezones)
['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa',...]
我正在寻找的是任何 时区缩写,例如 PST 或 PDT ,忽略当前日期时间(例如现在),return 所有可能的 时区名称 ,在这种情况下,列表将包括 America/Los_Angeles.
谢谢
我使用 datetime
模块的 strftime
函数执行此操作,因为它有一个 %Z
格式说明符 returns 时区缩写。这是一个 filter
语句,可以满足您的需要:
>>> filter(lambda x: datetime.datetime.now(pytz.timezone(x)).strftime("%Z") == "PDT", pytz.common_timezones)
['America/Dawson',
'America/Los_Angeles',
'America/Tijuana',
'America/Vancouver',
'America/Whitehorse',
'Canada/Pacific',
'US/Pacific']
您可以将 "PDT"
替换为您需要的任何时区。请记住,您还需要导入 datetime
.
import pytz
for tzname in list(pytz.common_timezones):
print(pytz.timezone(tzname)._tzname)
Similar question
既然你想忽略当前的日期时间,听起来你想找
在 的任何时间使用给定缩写的任何时区
过去。该信息在 Olson 数据库中,可通过
皮茨。但是,pytz 将此信息存储在 private 属性中,
tzone._transition_info
:
import collections
import datetime as DT
import pytz
tzones = collections.defaultdict(set)
abbrevs = collections.defaultdict(set)
for name in pytz.all_timezones:
tzone = pytz.timezone(name)
for utcoffset, dstoffset, tzabbrev in getattr(
tzone, '_transition_info', [[None, None, DT.datetime.now(tzone).tzname()]]):
tzones[tzabbrev].add(name)
abbrevs[name].add(tzabbrev)
gettattr
的第三个(默认)参数是为了处理一些
时区,例如 Africa/Bujumbura
,从来没有任何转换。所以
这些情况下的缩写是当前缩写。
In [94]: tzones['PST']
Out[94]:
{'America/Bahia_Banderas',
'America/Boise',
'America/Creston',
'America/Dawson',
'America/Dawson_Creek',
'America/Ensenada',
'America/Hermosillo',
'America/Inuvik',
'America/Juneau',
'America/Los_Angeles',
'America/Mazatlan',
'America/Metlakatla',
'America/Santa_Isabel',
'America/Sitka',
'America/Tijuana',
'America/Vancouver',
'America/Whitehorse',
'Canada/Pacific',
'Canada/Yukon',
'Mexico/BajaNorte',
'Mexico/BajaSur',
'PST8PDT',
'Pacific/Pitcairn',
'US/Pacific',
'US/Pacific-New'}
In [95]: tzones['PDT']
Out[95]:
{'America/Boise',
'America/Dawson',
'America/Dawson_Creek',
'America/Ensenada',
'America/Juneau',
'America/Los_Angeles',
'America/Metlakatla',
'America/Santa_Isabel',
'America/Sitka',
'America/Tijuana',
'America/Vancouver',
'America/Whitehorse',
'Canada/Pacific',
'Canada/Yukon',
'Mexico/BajaNorte',
'PST8PDT',
'US/Pacific',
'US/Pacific-New'}
In [97]: abbrevs['America/Los_Angeles']
Out[97]: {'LMT', 'PDT', 'PPT', 'PST', 'PWT'}
与 Asia/Shanghai
和 US/Central
都使用 CST
时区缩写。
In [242]: 'Asia/Shanghai' in tzones['CST']
Out[242]: True
In [243]: 'US/Central' in tzones['CST']
Out[243]: True
我喜欢 unutbu 的回答,这使我找到了对我有用的答案。我有用户的语言环境,所以我发现我可以用它来消除时区缩写之间的歧义。
换句话说,这解决了以下问题:
In [242]: 'Asia/Shanghai' in tzones['CST']
Out[242]: True
In [243]: 'US/Central' in tzones['CST']
Out[243]: True
此功能需要两个字母的国家代码:
def GetTimeZoneName(timezone, country_code):
#see if it's already a valid time zone name
if timezone in pytz.all_timezones:
return timezone
#if it's a number value, then use the Etc/GMT code
try:
offset = int(timezone)
if offset > 0:
offset = '+' + str(offset)
else:
offset = str(offset)
return 'Etc/GMT' + offset
except ValueError:
pass
#look up the abbreviation
country_tzones = None
try:
country_tzones = pytz.country_timezones[country_code]
except:
pass
set_zones = set()
if country_tzones is not None and len(country_tzones) > 0:
for name in country_tzones:
tzone = pytz.timezone(name)
for utcoffset, dstoffset, tzabbrev in getattr(tzone, '_transition_info', [[None, None, datetime.datetime.now(tzone).tzname()]]):
if tzabbrev.upper() == timezone.upper():
set_zones.add(name)
if len(set_zones) > 0:
return min(set_zones, key=len)
# none matched, at least pick one in the right country
return min(country_tzones, key=len)
#invalid country, just try to match the timezone abbreviation to any time zone
for name in pytz.all_timezones:
tzone = pytz.timezone(name)
for utcoffset, dstoffset, tzabbrev in getattr(tzone, '_transition_info', [[None, None, datetime.datetime.now(tzone).tzname()]]):
if tzabbrev.upper() == timezone.upper():
set_zones.add(name)
return min(set_zones, key=len)
这 returns CST 的正确时区:
>>> GetTimeZoneName('CST','CN')
'Asia/Shanghai'
>>> GetTimeZoneName('CST','US')
'America/Detroit'
更新 py3.9+(如 PEP615), the new zoneinfo 模块中所讨论可能有帮助:
from collections import defaultdict
from datetime import datetime as dt
from zoneinfo import available_timezones, ZoneInfo
now = dt.utcnow()
tz_key = lambda tz: ZoneInfo(tz).tzname(now)
tz_map = defaultdict(list)
for tz in available_timezones():
tz_map[tz_key(tz)].append(tz)
tz_map = {k: sorted(v) for k, v in tz_map.items()}
例如,print(tz_map['PDT'])
会产生:['America/Ensenada', 'America/Los_Angeles', 'America/Santa_Isabel', 'America/Tijuana', 'America/Vancouver', 'Canada/Pacific', 'Mexico/BajaNorte', 'PST8PDT', 'US/Pacific', 'US/Pacific-New']
注意:时区来自 locally-installed 时区数据。您还可以添加第一方 tzdata 库(不在标准库中,但由 python 的核心开发人员维护:使用 pip install tzdata
)。