Python标准库datetime库tzinfo类详解(5/6)

tzinfo对象

datetime.tzinfo

用于表示时区信息。

它是datetime模块中用于处理时区的一个抽象层。通过实现这个抽象基类,可以创建表示特定时区的对象,并将其用于datetime对象中。

这是一个抽象基类,也就是说该类不应被直接实例化。 请定义 tzinfo 的子类来捕获有关特定时区的信息。

例:

# 在这个例子中,US_Eastern_TZInfo 是一个继承自 tzinfo 的子类,用于表示美国东部时区的信息。

class US_Eastern_TZInfo(tzinfo):

    def utcoffset(self, dt):

        return timedelta(hours=-5)

    def dst(self, dt):

        return timedelta(hours=1)

    def tzname(self, dt):

        return "EST"

tzinfo 的(某个实体子类)的实例可以被传给 datetime 和 time 对象的构造器。 这些对象会将它们的属性视为对应于本地时间,并且 tzinfo 对象支持展示本地时间与 UTC 的差值、时区名称以及 DST 差值的方法,都是与传给它们的日期或时间对象的相对值。

你需要派生一个实体子类,并且(至少)提供你使用 datetime 方法所需要的标准 tzinfo 方法的实现。 datetime 模块提供了 timezone,这是 tzinfo 的一个简单实体子类,它能以与 UTC 的固定差值来表示不同的时区,例如 UTC 本身或北美的 EST 和 EDT。

Special requirement for pickling: A tzinfo subclass must have an __init__() method that can be called with no arguments, otherwise it can be pickled but possibly not unpickled again. This is a technical requirement that may be relaxed in the future.

一个 tzinfo 的实体子类可能需要实现以下方法。 具体需要实现的方法取决于感知型 datetime 对象如何使用它。 如果有疑问,可以简单地全都实现。

方法

1、tzinfo.utcoffset(dt)

用于计算一个包含指定时区信息的日期或时间(dt)对象相对于UTC(协调世界时)的偏移量。

这个方法返回一个timedelta对象,表示偏移量时间差。

具体来说,utcoffset(dt)返回 一个表示偏移量的时间差,单位是秒。如果该时区比UTC早,则返回的时间差是正数;如果比UTC晚,则返回的时间差是负数。

这表示与 UTC 的 总计 时差;举例来说,如果一个 tzinfo 对象同时代表时区和 DST 调整,则 utcoffset() 应当返回两者的和。 如果 UTC 时差不确定则返回 None。 在其他情况下返回值必须为一个 timedelta 对象,其取值严格限制于 -timedelta(hours=24) 和 timedelta(hours=24) 之间(差值的幅度必须小于一天)。 大多数 utcoffset() 的实现看起来可能像是以下两者之一:

return CONSTANT                 # fixed-offset class

return CONSTANT + self.dst(dt)  # daylight-aware class

如果 utcoffset() 返回值不为 None,则 dst() 也不应返回 None。

默认的 utcoffset() 实现会引发 NotImplementedError。

在 3.7 版更改: UTC 时差不再限制为一个整数分钟值。

例:

from datetime import datetime, timedelta, timezone

# 创建一个包含指定时区信息的datetime对象

dt_with_tz = datetime(2023, 1, 1, tzinfo=timezone(timedelta(hours=5)))

# 使用utcoffset()方法获取UTC偏移量

offset = dt_with_tz.tzinfo.utcoffset(dt_with_tz)

print(f"UTC offset: {offset}")

输出:UTC offset: 5:00:00

2、tzinfo.dst(dt)

用于计算给定日期时间对象的夏令时调整量。

这个方法返回 一个timedelta对象,表示在夏令时期间需要添加或送去的小时数。

将夏令时(DST)调整返回为一个 timedelta 对象,如果 DST 信息未知则返回 None。

如果 DST 未启用则返回 timedelta(0)。 如果 DST 已启用则将差值作为一个 timedelta 对象返回(参见 utcoffset() 了解详情)。 请注意 DST 差值如果可用,就会直接被加入 utcoffset() 所返回的 UTC 时差,因此无需额外查询 dst() 除非你希望单独获取 DST 信息。 例如,datetime.timetuple() 会调用其 tzinfo 属性的 dst() 方法来确定应该如何设置 tm_isdst 旗标,而 tzinfo.fromutc() 会调用 dst() 来在跨越时区时处理 DST 的改变。

一个可以同时处理标准时和夏令时的 tzinfo 子类的实例 tz 必须在此情形中保持一致:

tz.utcoffset(dt) - tz.dst(dt)

必须为具有同样的 tzinfo 子类实例且 dt.tzinfo == tz 的每个 datetime 对象 dt 返回同样的结果,此表达式会产生时区的“标准时差”,它不应取决于具体日期或时间,只取决于地理位置。 datetime.astimezone() 的实现依赖此方法,但无法检测违反规则的情况;确保符合规则是程序员的责任。 如果一个 tzinfo 子类不能保证这一点,也许可以重载 tzinfo.fromutc() 的默认实现以便在任何情况下与 astimezone() 正确配合。

大多数 dst() 的实现可能会如以下两者之一:

def dst(self, dt):

    # a fixed-offset class:  doesn't account for DST

    return timedelta(0)

或者:

def dst(self, dt):

    # Code to set dston and dstoff to the time zone's DST

    # transition times based on the input dt.year, and expressed

    # in standard local time.

    if dston <= dt.replace(tzinfo=None) < dstoff:

        return timedelta(hours=1)

    else:

        return timedelta(0)

默认的 dst() 实现会引发 NotImplementedError。

在 3.7 版更改: DST 差值不再限制为一个整数分钟值。

示例:

from datetime import tzinfo, timedelta

import datetime

# 在这个例子中,US_Eastern_TZInfo 是一个继承自 tzinfo 的子类,用于表示美国东部时区的信息。

class US_Eastern_TZInfo(tzinfo):

    def utcoffset(self, dt):

        return timedelta(hours=-5)

    def dst(self, dt):

        return timedelta(hours=1)

    def tzname(self, dt):

        return "EST"

eastern_tz = US_Eastern_TZInfo()

dt = datetime.datetime(2023, 7, 5, 12, 0, 0, tzinfo=eastern_tz)

dst_adjustment = eastern_tz.dst(dt)

print(dst_adjustment) # 输出:1:00:00

3、tzinfo.tzname(dt)

用于获取一个日期或时间所在的时区的名称。

将对应于 datetime 对象 dt 的时区名称作为字符串返回。 datetime 模块没有定义任何字符串名称相关内容,也不要求名称有任何特定含义。

例如 "GMT", "UTC", "-500", "-5:00", "EDT", "US/Eastern", "America/New York" 都是有效的返回值。 如果字符串名称未知则返回 None。

请注意这是一个方法而不是一个固定的字符串,这主要是因为某些 tzinfo 子类可能需要根据所传入的特定 dt 值返回不同的名称,特别是当 tzinfo 类要负责处理夏令时的时候。

默认的 tzname() 实现会引发 NotImplementedError。

这些方法会被 datetime 或 time 对象调用,用来与它们的同名方法相对应。 datetime 对象会将自身作为传入参数,而 time 对象会将 None 作为传入参数。 这样 tzinfo 子类的方法应当准备好接受 dt 参数值为 None 或是 datetime 类的实例。

当传入 None 时,应当由类的设计者来决定最佳回应方式。 例如,返回 None 适用于希望该类提示时间对象不参与 tzinfo 协议处理。 让 utcoffset(None) 返回标准 UTC 时差也许会更有用处,因为并没有其他可用于发现标准时差的约定惯例。

当传入一个 datetime 对象来回应 datetime 方法时,dt.tzinfo 与 self 是同一对象。 tzinfo 方法可以依赖这一点,除非用户代码直接调用了 tzinfo 方法。 此行为的目的是使得 tzinfo 方法将 dt 解读为本地时间,而不需要担心其他时区的相关对象。

示例:

from datetime import tzinfo, timedelta

import datetime

# 在这个例子中,US_Eastern_TZInfo 是一个继承自 tzinfo 的子类,用于表示美国东部时区的信息。

class US_Eastern_TZInfo(tzinfo):

    def utcoffset(self, dt):

        return timedelta(hours=-5)

    def dst(self, dt):

        return timedelta(hours=1)

    def tzname(self, dt):

        return "EST"

eastern_tz = US_Eastern_TZInfo()

dt = datetime.datetime(2023, 7, 5, 12, 0, 0, tzinfo=eastern_tz)

tzname = eastern_tz.tzname(dt)

print(tzname) # 输出:EST

还有一个额外的 tzinfo 方法,某个子类可能会希望重载它:

4、tzinfo.fromutc(dt)

用于将一个UTC时间转换为表示特定时区的本地时间。

这个方法接受一个datetime对象作为参数,并返回 一个表示该时间在特定时区中的本地时间的datetime对象。

例:

from datetime import tzinfo, timedelta, datetime  

  

class US_Eastern_TZInfo(tzinfo):  

    def utcoffset(self, dt):  

        return timedelta(hours=-5)  

    def fromutc(self, dt):  

        return dt + self.utcoffset(dt)  

    # ... 其他方法省略 ...  

  

eastern_tz = US_Eastern_TZInfo()  

dt_utc = datetime(2023, 7, 5, 12, 0, 0)  

dt_local = eastern_tz.fromutc(dt_utc)  

print(dt_local)  # 输出: 2023-07-05 07:00:00

此方法会由默认的 datetime.astimezone() 实现来调用。 当被其调用时,dt.tzinfo 为 self,并且 dt 的日期和时间数据会被视为表示 UTC 时间,fromutc() 的目标是调整日期和时间数据,返回一个等价的 datetime 来表示 self 的本地时间。

大多数 tzinfo 子类应该能够毫无问题地继承默认的 fromutc() 实现。 它的健壮性足以处理固定差值的时区以及同时负责标准时和夏令时的时区,对于后者甚至还能处理 DST 转换时间在各个年份有变化的情况。

一个默认 fromutc() 实现可能无法在所有情况下正确处理的例子是(与 UTC 的)标准时差取决于所经过的特定日期和时间,这种情况可能由于政治原因而出现。 默认的 astimezone() 和 fromutc() 实现可能无法生成你希望的结果,如果这个结果恰好是跨越了标准时差发生改变的时刻当中的某个小时值的话。

更多详情参见官方文档:datetime --- 基本日期和时间类型 — Python 3.12.1 文档

  • 25
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值