【问题标题】:Comparing a time in UTC with a time in Eastern time using Python使用 Python 比较 UTC 时间和东部时间的时间
【发布时间】:2012-05-18 10:40:49
【问题描述】:

我正在尝试使用 Python datetime 模块比较两次,但我似乎无法在 UTC 中创建时区感知 time 对象。

>>> import pytz, datetime
>>> UTC_TZ = pytz.utc
>>> EASTERN_TZ = pytz.timezone('America/New_York')
>>> d1 = datetime.time(10, tzinfo = UTC_TZ)
>>> d1
datetime.time(10, 0, tzinfo=<UTC>)
>>> d2 = datetime.time(10, tzinfo = EASTERN_TZ)
>>> d2
datetime.time(10, 0, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
>>> d1 < d2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware times

这是一个错误吗?我需要使用特殊的 UTC 时区吗?怎么回事?

【问题讨论】:

    标签: python datetime timezone pytz


    【解决方案1】:

    感谢 wberry 解决这个问题,但为了得到一个简明的答案,我将在这里总结一下。

    根据 datetime 文档,在比较两个 datetime.time 对象时:“如果两个比较对象都知道并且具有不同的 tzinfo 属性,则首先通过减去它们的 UTC 偏移量来调整比较对象(从 self.utcoffset() 获得)”

    在您给出的示例中,比较会引发 TypeError,因为 EASTERN_TZ.utcoffset() 返回 None。 utcoffset 为 None 因为美国东部遵守夏令时,因此与 UTC 的时间偏移量取决于 datetime.time 中不可用的日期。

    您应该使用 datetime.datetime 对象进行跨时区比较:

    >>> import pytz, datetime
    >>> UTC_TZ = pytz.utc
    >>> EASTERN_TZ = pytz.timezone('America/New_York')
    >>> d1 = datetime.datetime(2012, 1, 1, 10, 0, tzinfo=UTC_TZ)
    >>> d2 = datetime.datetime(2012, 1, 1, 10, 0, tzinfo=EASTERN_TZ)
    >>> d1 < d2
    True
    

    【讨论】:

    • 您不应该将 tzinfo 参数用于具有 DST 的时区。使用EASTERN_TZ.localize(naive_dt, is_dst=None).astimezone(pytz.utc) 获取要比较的日期时间对象。 .astimezone() 不是必需的,但最好始终在内部使用 UTC 时间并仅在 IO 上将其转换为其他时区
    • 请注意,在 3.3 中,朴素时间实例和有意识时间实例之间的相等比较不会引发 TypeError。
    【解决方案2】:

    您收到错误是因为您尝试测量一个可与特定 UTC 时刻相关联的 time 对象与另一个“幼稚”且无法与特定 UTC 时刻相关联的 time 对象之间的差异.解决方法是让两个比较对象都具有偏移感知能力,或者两者都幼稚。

    下面使用datetime 对象,但基本上是相同的想法。

    import datetime, time, pytz
    
    EST = pytz.timezone('America/New_York')
    UTC = pytz.timezone('Etc/UTC')
    dt1 = datetime.datetime.fromtimestamp(time.time(), EST)
    # ... time passes
    dt2 = datetime.datetime.fromtimestamp(time.time(), UTC)
    elapsed = dt2 - dt1
    

    【讨论】:

    • 那么这是 Python 中的错误吗?文档说“时间或日期时间类型的对象 d 可能是天真或有意识的。如果 d.tzinfo 不是 None 并且 d.tzinfo.utcoffset(d) 不返回 None,则 d 知道。如果 d.tzinfo 是 None,或者如果 d.tzinfo 不是 None 但 d.tzinfo.utcoffset(d) 返回 None,则 d 是幼稚的。"如果这是正确的,那么为什么在我的示例中 d1 说它是偏移天真的?
    • @ChrisB.,测试UTC_TZ,看看它是否为utcoffset返回None
    • @Mark Ransom:它没有。它返回datetime.timedelta(0)
    • 不知道为什么,但是使用 EASTERN_TZ 创建的 datetime.time 对象对于 utcoffset 返回 None,然后导致 TypeError。
    • 我的猜测是因为 America/New_York 的 UTC 偏移量不能仅从 time 对象计算;您需要datetime 来确定夏令时是否有效。
    【解决方案3】:

    我猜问题是 UTC 被认为不是任何时区,或者“偏移天真”,也许?我建议在进行任何比较之前将所有内容都转换为 UTC。

    显然,您需要知道输入和输出的时区,但您应该尝试将您的内部表示全部保持为 UTC,并且可能只存储每个用户的时区并在需要时进行转换。从长远来看,它会省去很多麻烦。

    另外,你不应该这样做。最好用

    timezone.localize(dt)
    

    如此处所述:http://pytz.sourceforge.net/#localized-times-and-date-arithmetic

    【讨论】:

    • EASTERN_TZ.localize(datetime.time(10)) 给我TypeError: unsupported operand type(s) for +: 'datetime.time' and 'datetime.timedelta'
    • @ChrisB.: 同一时区可能在不同日期有不同的 UTC 偏移量,即 tz + datetime.time() 不足以找出正确的 UTC 偏移量,您需要 tz + datetime.datetime 假设给定时间存在并且它没有歧义。
    猜你喜欢
    • 2016-07-26
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 1970-01-01
    • 2018-05-04
    相关资源
    最近更新 更多