Python: 检查解析的日期时间是否有正确的时区

Python: Check if parsed datetime has correct timezone

所以,我知道 ISO 格式的日期时间 - 2020-03-15T18:00:00+04:00

我想解析它并验证 tzinfo 是 "Asia/Dubai" (UTC+04:00)。不幸的是,dateutil & datetime 没有给我足够好的 tzinfo 解析对象的属性,我可以很容易地验证。

>>> from datetime import datetime
>>> from dateutil.parser import isoparse
>>> import pytz
>>> 
>>> dts = "2020-03-15T18:00:00+04:00"
>>> dt = datetime.fromisoformat(dts)
>>> dt.tzinfo
datetime.timezone(datetime.timedelta(seconds=14400))
>>> dt.tzinfo == pytz.timezone("Asia/Dubai")
False
>>> 
>>> dt = isoparse(dts)
>>> dt.tzinfo
tzoffset(None, 14400)
>>> dt.tzinfo == pytz.timezone("Asia/Dubai")
False

我找不到如何处理 tzoffset 对象以便我可以轻松地将它与时区字符串进行比较。

欢迎向正确的方向提出任何建议或评论或推动。

我找到了一个我不喜欢的解决方法(比较时区应该更简单一些,但是,是的,这是一个困难的域),基于

>>> tz = pytz.timezone("Asia/Dubai")
>>> datetime.utcoffset(dt) == tz.utcoffset(dt.replace(tzinfo=None))
True

问题的答案,"Is the parsed datetime 'Asia/Dubai'",特别是当你的概念 'Asia/Dubai' 意味着 pytz.timezone("Asia/Dubai") 总是 "no",因为 dateutil 永远不会附加该时区为您从 ISO 8601 日期时间解析的内容。

一个原因是您正在解析的字符串没有足够的信息来确定生成它的规则集 - 考虑 "Asia/Tibilisi" 和 "Asia/Dubai" 都使用 UTC+4 , 但它们不代表相同的时区。

那么问题来了:你为什么需要知道这些信息?

如果您只想使用 "Asia/Dubai" 中的日期时间,最好的办法是将它们转换为 .astimezone:

from dateutil import tz
from dateutil.parser import isoparse

_DUBAI = tz.gettz("Asia/Dubai")
def parse_as_dubai(dt_str):
    dt = isoparse(dt_str)
    if dt.tzinfo is None:
        raise ValueError(f"No time zone offset in {dt_str}")
    return dt.astimezone(_DUBAI)

请注意,只要您解析了 时区 ,这将始终准确,无论输入字符串最初是否在 "Asia/Dubai"。如果没有给出时区,使用 astimezone 将使用正在解析日期时间的系统的系统本地时间,这不是您想要的。

如果出于某种原因您需要 验证 原始日期时间与 "Asia/Dubai" 具有相同的偏移量(不确定您为什么需要这个,但我想它可能表明日期时间的来源存在问题),然后转换为 "Asia/Dubai" 并检查偏移量是否是您的最佳选择。您可以在上面的代码中添加额外的错误检查:

from dateutil import tz
from dateutil.parser import isoparse

_DUBAI = tz.gettz("Asia/Dubai")
def parse_as_dubai(dt_str):
    dt = isoparse(dt_str)
    if dt.tzinfo is None:
        raise ValueError(f"No time zone offset in {dt_str}")
    rv = dt.astimezone(_DUBAI)
    if dt.utcoffset() != rv.utcoffset():
        raise ValueError(f"{dt_str} not generated in Asia/Dubai!")
    return rv

最后一点,我强烈建议您不要使用 pytz 而是使用 dateutil.tz,特别是因为您已经在使用 dateutil 进行解析。您可以阅读有关 in this article.

原因的更多信息