【发布时间】:2012-12-01 18:15:30
【问题描述】:
我想知道 Python 库 pytz 中时区参数的所有可能值。怎么办?
【问题讨论】:
-
版主说明:请将您的问题保留为问题。相反,您可以在回答帖子中编写自己的解决方案。
我想知道 Python 库 pytz 中时区参数的所有可能值。怎么办?
【问题讨论】:
您可以使用pytz.all_timezones 列出所有可用的时区:
In [40]: import pytz
In [41]: pytz.all_timezones
Out[42]:
['Africa/Abidjan',
'Africa/Accra',
'Africa/Addis_Ababa',
...]
还有pytz.common_timezones:
In [45]: len(pytz.common_timezones)
Out[45]: 403
In [46]: len(pytz.all_timezones)
Out[46]: 563
【讨论】:
all_timezones,pytz also providescommon_timezones。
'Asia/Shanghai'。
(datetime(2017,2,13,14,29,29, tzinfo=pytz.timezone('Asia/Shanghai')) - datetime(2017,2,13,14,29,29, tzinfo=pytz.timezone('UTC'))).total_seconds()(结果是 not -28800)。我会避免使用 pytz——dateutil.tz 提供了类似的功能,但使用了 OS 时区数据库并且没有此类问题。
不要创建自己的列表 - pytz 有一个内置集合:
import pytz
set(pytz.all_timezones_set)
>>> {'Europe/Vienna', 'America/New_York', 'America/Argentina/Salta',..}
然后您可以应用时区:
import datetime
tz = pytz.timezone('Pacific/Johnston')
ct = datetime.datetime.now(tz=tz)
>>> ct.isoformat()
2017-01-13T11:29:22.601991-05:00
或者如果你已经有一个datetime对象是TZ感知(不幼稚):
# This timestamp is in UTC
my_ct = datetime.datetime.now(tz=pytz.UTC)
# Now convert it to another timezone
new_ct = my_ct.astimezone(tz)
>>> new_ct.isoformat()
2017-01-13T11:29:22.601991-05:00
【讨论】:
时区名称是指定时区的唯一可靠方法。
您可以在此处找到时区名称列表:http://en.wikipedia.org/wiki/List_of_tz_database_time_zones 请注意,此列表包含许多别名,例如 US/Eastern 代表正确称为 America/New_York 的时区。
如果您想以编程方式从 zoneinfo 数据库创建此列表,您可以从 zoneinfo 数据库中的 zone.tab 文件编译它。我认为 pytz 没有获取它们的 API,而且我也不认为它很有用。
【讨论】:
这里是国家代码、名称、大洲、首都和 pytz 时区的 Python 列表。
countries = [
{'timezones': ['Europe/Paris'], 'code': 'FR', 'continent': 'Europe', 'name': 'France', 'capital': 'Paris'}
{'timezones': ['Africa/Kampala'], 'code': 'UG', 'continent': 'Africa', 'name': 'Uganda', 'capital': 'Kampala'},
{'timezones': ['Asia/Colombo'], 'code': 'LK', 'continent': 'Asia', 'name': 'Sri Lanka', 'capital': 'Sri Jayewardenepura Kotte'},
{'timezones': ['Asia/Riyadh'], 'code': 'SA', 'continent': 'Asia', 'name': 'Saudi Arabia', 'capital': 'Riyadh'},
{'timezones': ['Africa/Luanda'], 'code': 'AO', 'continent': 'Africa', 'name': 'Angola', 'capital': 'Luanda'},
{'timezones': ['Europe/Vienna'], 'code': 'AT', 'continent': 'Europe', 'name': 'Austria', 'capital': 'Vienna'},
{'timezones': ['Asia/Calcutta'], 'code': 'IN', 'continent': 'Asia', 'name': 'India', 'capital': 'New Delhi'},
{'timezones': ['Asia/Dubai'], 'code': 'AE', 'continent': 'Asia', 'name': 'United Arab Emirates', 'capital': 'Abu Dhabi'},
{'timezones': ['Europe/London'], 'code': 'GB', 'continent': 'Europe', 'name': 'United Kingdom', 'capital': 'London'},
]
完整列表: Gist Github
希望,它会有所帮助。
【讨论】:
编辑:如果您不进一步否决此答案,我将不胜感激。此答案错误,但我宁愿将其保留为历史记录。虽然 pytz 接口是否容易出错是有争议的,但它可以做 dateutil.tz 不能做的事情,尤其是在过去或未来的夏令时方面。我在"Time zones in Python"的文章中诚实地记录了我的经历。
如果您使用的是类 Unix 平台,我建议您避免使用 pytz,而只查看 /usr/share/zoneinfo。 dateutil.tz 可以利用那里的信息。
以下代码显示了 pytz 可以给出的问题。当我第一次发现它时,我感到很震惊。 (有趣的是,在 CentOS 7 上 yum 安装的 pytz 并没有出现这个问题。)
import pytz
import dateutil.tz
from datetime import datetime
print((datetime(2017,2,13,14,29,29, tzinfo=pytz.timezone('Asia/Shanghai'))
- datetime(2017,2,13,14,29,29, tzinfo=pytz.timezone('UTC')))
.total_seconds())
print((datetime(2017,2,13,14,29,29, tzinfo=dateutil.tz.gettz('Asia/Shanghai'))
- datetime(2017,2,13,14,29,29, tzinfo=dateutil.tz.tzutc()))
.total_seconds())
-29160.0
-28800.0
即pytz 创建的时区是真正的当地时间,而不是人们观察到的标准当地时间。上海符合+0800,而不是pytz建议的+0806:
pytz.timezone('Asia/Shanghai')
<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>
编辑:感谢 Mark Ransom 的评论和反对,现在我知道我使用 pytz 的方式是错误的。总之,您不应该将pytz.timezone(…) 的结果传递给datetime,而应该将datetime 传递给它的localize 方法。
尽管有他的论点(而且我没有更仔细地阅读 pytz 文档,这很糟糕),但我将保留这个答案。我以一种方式回答了这个问题(如何枚举支持的时区,虽然不是用 pytz),因为我认为 pytz 没有提供正确的解决方案。尽管我的想法是错误的,但这个答案仍然提供了一些信息,恕我直言,这对对此问题感兴趣的人可能有用。 Pytz 的正确 做事方式是违反直觉的。哎呀,如果pytz创建的tzinfo不应该被datetime直接使用,它应该是不同的类型。 pytz 界面设计得很糟糕。 Mark提供的链接显示,不仅仅是我,很多人都被pytz界面误导了。
【讨论】:
pytz 没什么问题,只是你用错了。附言这根本不是问题的答案。
datetime 接口,而不是pytz。 datetime 没有预料到 智能 时区对象,所以它的接口没有正确初始化它们。
datetime 是标准 Python 库的一部分,应该遵循 datetime 接口的是 pytz,反之亦然。如果有人可以在没有达成共识的情况下以他们认为更好的方式实现某些接口,那么就不会有强大的软件。
pytz 无法跟随datetime 接口,因为datetime 接口有缺陷。该界面的作者没有预料到参数多年来变化的时区问题。仅仅因为它是标准 Python 发行版的一部分并不意味着它是完美的。
它们似乎由 here 找到的 tz 数据库时区填充。
【讨论】:
pytz 提供对the tz database 的访问(它是维基百科数据的来源)。
可从 Python3.9 获得:
zoneinfo,Python3.9 中的新模块,适用于 IANA 数据库。 为了获取所有可用的时区,首先:
pip install tzdata
然后:
import zoneinfo
print(zoneinfo.available_timezones())
【讨论】:
您会在此处找到所有pytz 支持的时区:
https://gist.github.com/heyalexej/8bf688fd67d7199be4a1682b3eec7568
【讨论】:
在我看来,这是 pytz 库的设计缺陷。使用偏移量指定时区应该更可靠,例如
pytz.construct("UTC-07:00")
它为您提供加拿大/太平洋时区。
【讨论】: