【问题标题】:How to check if a datetime object is localized with pytz?如何检查日期时间对象是否使用 pytz 本地化?
【发布时间】:2011-08-13 17:05:59
【问题描述】:

我想存储一个具有本地化 UTC 时区的日期时间对象。可以给存储 datetime 对象的方法一个非本地化的 datetime (naive) 对象或已经本地化的对象。如何确定是否需要本地化?

缺少 if 条件的代码:

class MyClass:
  def set_date(self, d):
    # what do i check here?
    # if(d.tzinfo):
      self.date = d.astimezone(pytz.utc)
    # else:
      self.date = pytz.utc.localize(d)

【问题讨论】:

    标签: python datetime timezone pytz


    【解决方案1】:

    如何确定是否需要本地化?

    来自datetime docs:

    • 一个日期时间对象 d 知道 iff:

      d.tzinfo is not None and d.tzinfo.utcoffset(d) is not None
      
    • d 很天真,如果:

      d.tzinfo is None or d.tzinfo.utcoffset(d) is None
      

    虽然如果 d 是一个代表 UTC 时区时间的日期时间对象,那么您可以在这两种情况下使用:

    self.date = d.replace(tzinfo=pytz.utc)
    

    无论d 是时区感知还是幼稚,它都能正常工作。

    注意:don't use datetime.replace() method with a timezone with a non-fixed utc offset(可以与 UTC 时区一起使用,否则应使用tz.localize() 方法)。

    【讨论】:

    • @Geekfish:不知道。所有理智的实现都应该返回非 None 值或引发异常。
    • 由于 Python 3.6 astimezone 可以在幼稚的实例上调用,并且它采用系统时区。
    • @Mitar:是的。很不幸。
    • @pablete:这是一个有效的问题。如果您对此感觉强烈,可以提交补丁,例如:def is_naive(self): return self.tzinfo is None or self.tzinfo.utcoffset(self) is Nonedevguide.python.org
    • @ryanjdillon:utcoffset method on tzinfo(相对于datetime)需要一个日期时间参数,因此答案中的代码是正确的。
    【解决方案2】:

    如果要检查日期时间对象 'd' 是否已本地化,请检查 d.tzinfo,如果为 None,则不进行本地化。

    【讨论】:

    • 但是如果它有一个不是来自 pytz 的 tzinfo 对象呢?
    • 注意:只检查d.tzinfo is not None是不够的。另外,d.tzinfo.utcoffset(d) should not be None for d to be called an aware datetime object.
    • 这个答案是不正确的,这里是日期时间官方文档中何时天真或有意识的定义:“时间或日期时间类型的对象可能是天真或有意识的。日期时间对象 d知道 d.tzinfo 是否不是 None 并且 d.tzinfo.utcoffset(d) 不返回 None。如果 d.tzinfo 是 None,或者如果 d.tzinfo 不是 None 但 d.tzinfo.utcoffset(d) 返回 None, d 是幼稚的。如果 t.tzinfo 不是 None 并且 t.tzinfo.utcoffset(None) 不返回 None,则时间对象 t 知道。否则,t 是幼稚的。"
    【解决方案3】:

    这是一个总结最佳答案的函数。

    def tz_aware(dt):
        return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None
    

    【讨论】:

    • 其余时间返回None?
    • 只要说return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None就足够了
    【解决方案4】:

    这是一个更完整的函数,用于将时间戳 obj 转换或强制转换为 utc。如果它达到异常,则意味着时间戳未本地化。由于在代码中始终使用 UTC 是一种很好的做法,因此此函数在持久性的入门级非常有用。

    def convert_or_coerce_timestamp_to_utc(timeobj):
            out = timeobj
            try:
                out = timeobj.astimezone(pytz.utc) # aware object can be in any timezone
            except (ValueError,TypeError) as exc: # naive
                out = timeobj.replace(tzinfo=pytz.utc)
            return out
    

    J.F. Sebastian 回答中的“try catch”中的一个小补充是附加的 catch 条件,没有它,函数不会捕获所有幼稚的情况。

    【讨论】:

    • 为什么你也会看到TypeError?我没有看到其他答案中提到过。
    • 正如我所写,如果没有额外的捕获,并非所有幼稚的案例都会被捕获。这只是基于直接经验的补充。我最初只处理第一个捕获,并且一些天真的时间戳通过了:)
    • 如果您在此处展示一个抛出 TypeError 的天真的对象的具体示例,则可以改进答案。
    • 到目前为止已经提到过 - 由于 Python 3.6 astimezone 可以在幼稚的实例上调用并且它假定系统时区。因此,如果没有特定的检查,您的实施是危险的。
    猜你喜欢
    • 2010-11-25
    • 2017-04-24
    • 2011-02-07
    • 1970-01-01
    • 2010-10-13
    • 2012-06-12
    • 2016-05-03
    • 1970-01-01
    • 2020-07-03
    相关资源
    最近更新 更多