使用Python dateutil,如何判断时区字符串是否“有效”?

问题描述 投票:0回答:4

我使用以下代码将 UTC 时间转换为本地时间:

def UTC_to_local(timezone_str, datetime_UTC):
    """
    convert UTC datetime to local datetime. Input datetime is naive
    """
    try:
        from_zone = dateutil.tz.gettz('UTC')
        to_zone = dateutil.tz.gettz(timezone_str)

        datetime_UTC = datetime_UTC.replace(tzinfo=from_zone)

        # Convert time zone
        datetime_local = datetime_UTC.astimezone(to_zone)

    except Exception as e:
        raise

    return datetime_local

如果我给出了正确的 timezone_str (例如“美国/芝加哥”),它就会按预期工作。 但即使我给出了意想不到的 timezone_str (例如,“America/Chicago1”或“Americaerror/Chicago”),仍然没有例外,它只是返回不同的数字!我认为为意外的时区字符串获取异常比仅仅“做出最佳猜测”更合理。

此外,我发现(使用IPYTHON):

In [171]: tz.gettz("America/Chicago")
Out[171]: tzfile('/usr/share/zoneinfo/America/Chicago')

In [172]: tz.gettz("America/Chicago1")
Out[172]: tzstr('America/Chicago1')

In [173]: tz.gettz("Americaerror/Chicago")
          (None)
python timezone
4个回答
17
投票

解决方案#1:如果你可以使用pytz

import pytz

if timezone_str in pytz.all_timezones:
    ...
else:
    raise ValueError('Invalid timezone string!')

解决方案#2:

import os
import tarfile
import dateutil.zoneinfo

zi_path = os.path.abspath(os.path.dirname(dateutil.zoneinfo.__file__))
zonesfile = tarfile.TarFile.open(os.path.join(zi_path, 'dateutil-zoneinfo.tar.gz'))
zonenames = zonesfile.getnames()

if timezone_str in zonenames:
    ...
else:
    raise ValueError('Invalid timezone string!')

4
投票

Sergey 的答案很好,但如果您选择解决方案#1,那么最好使用

pytz.all_timezones_set

if location in pytz.all_timezones_set
    ...

以下是两者的速度对比:

In [14]: %timeit "Asia/Omsk" in pytz.all_timezones
3.09 µs ± 7.66 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [15]: %timeit "Asia/Omsk" in pytz.all_timezones_set
96.5 ns ± 0.0991 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

注意:签入速度

pytz.all_timezones
取决于搜索到的项目。我选择了列表中间的一项(
Asia/Omsk
是 593 项中的第 296 项)。


4
投票

从 python 3.9 开始,

zoneinfo
是内置模块,您可以测试它而无需像
pytz
这样的外部模块:

from zoneinfo import available_timezones

valid_timezone = "America/Los_Angeles"
invalid_timezone = "spam"

def timezone_is_valid(timezone_string):
  return timezone_string in available_timezones()

timezone_is_valid(valid_timezone)  # Returns True
timezone_is_valid(invalid_timezone)  # Returns False

0
投票

您还可以尝试创建一个

zoneinfo.ZoneInfo
对象并捕获
zoneinfo.ZoneInfoNotFoundError
异常,如果字符串无效,则会引发该异常。

https://docs.python.org/3/library/zoneinfo.html#zoneinfo.ZoneInfo

from zoneinfo import ZoneInfo, ZoneInfoNotFoundError

def is_valid_timezone(tz: str) -> bool:
    try:
        ZoneInfo(tz)
        return True
    except ZoneInfoNotFoundError:
        return False

# Example usage
print(is_valid_timezone("America/New_York"))  # True
print(is_valid_timezone("Invalid/Timezone"))  # False

这比使用

zoneinfo.available_timezones
更好。请参阅 Python 文档中的警告:

注意:此功能可能会打开大量文件,最好 确定时区路径上的文件是否是有效时区的方法 就是读开头的“魔弦”。

https://docs.python.org/3/library/zoneinfo.html#zoneinfo.available_timezones

© www.soinside.com 2019 - 2024. All rights reserved.