Python3的datetime模块和time模块

文章目录

  • 前言
  • 1. datetime 模块
    • 1.1 简介
    • 1.2 详解
      • 1.2.1 tzinfo类
      • 1.2.2 timezone类
        • 1.2.2.1 timezone对象实例方法
        • 1.2.2.2 timezone对象类属性
      • 1.2.3 timedelta类
        • 1.2.3.1 timedeltad对象的类属性
        • 1.2.3.2 timedelta类实例属性
        • 1.2.3.3 timedelta类实例方法
      • 1.2.4 data类
        • 1.2.4.1 date对象类方法
        • 1.2.4.2 date对象类属性
        • 1.2.4.3 date对象实例属性
        • 1.2.4.4 date对象实例方法
      • 1.2.5 time类
        • 1.2.5.1 time对象类属性
        • 1.2.5.2 time对象实例属性
        • 1.2.5.3 time对象类方法
        • 1.2.5.4 time对象实例方法
      • 1.2.6 datetime类
        • 1.2.6.1 datetime对象的类方法
        • 1.2.6.2 datetime 对象类属性
        • 1.2.6.3 datetime对象实例属性
        • 1.2.6.4 `datetime` 对象的实例方法
  • 2. time模块
    • 2.1 time模块简介
    • 2.2 time模块详解
      • 2.2.1 术语和约定
      • 2.2.2 time模块中的函数
      • 2.2.3 time模块中的常量

前言

Python3中用来处理日期和时间的模块有 datetimetime 等,这篇文章主要是对这两个模块的英文文档的翻译,以便以后查看之用。由于能力有限,有不正确的地方还请指正,谢谢!

1. datetime 模块

1.1 简介

该模块提供了用于以简单和复杂的方式操作日期和时间的类。虽然支持日期和时间算法,但是实现的重点是高效地提取用于输出格式化和操作的属性。相关的功能,也可以参考 timecalendar 模块。

有两种用于表示时间和日期的对象:naiveaware

aware 对象包含时区和是否是夏令时等信息,用以定位自身相对于其他 aware 对象的位置。

naive 对象不包含时区和是否是夏令时等信息,不能用于定位自身相对于其他时间、日期对象的位置。

一个naive 对象表示的是协调世界时(UTC)、本地时间或其他时区的时间,完全取决于程序本身,就像一个特定的数字是表示米、英里或者质量一样,完全取决于程序本身。naive 对象很容易理解和使用,但代价是忽略实现的某些方面。

对于需要 aware 对象的应用程序,datetimetime 对象有一个可选的时区信息属性 tzinfo,可以将其设置为抽象 tzinfo 类的子类的实例。这些 tzinfo 对象捕获关于UTC时间的偏移量、时区名称以及夏令时是否有效的信息。注意,datetime 模块只提供了一个具体的 tzinfo 类,即 timezone 类。时区类可以表示与UTC具有固定偏移量的简单时区,例如UTC本身或北美EST和EDT时区。在更深层次的细节上支持时区取决于应用程序。世界各地的时间调整规则更多的是政治性的,而不是理性的,并且变化频繁,除了UTC之外,没有适用于所有应用程序的标准。

datetime 模块包含如下几个类:

datetime.date

一个理想化的 naive 日期,假设现在的公历永远有效。

datetime.time

一个理想化的时间,独立于任何特定的一天,假设每天正好是 24*60*60 秒(这里没有闰秒的概念)。

datetime.datetime

日期和时间的组合。

datetime.delta

表示两个 datetimedatetime 实例之间的时间间隔,精确到微秒。

datetime.tzinfo

时区信息对象的抽象基类。datetimetime 类使用该抽象基类的子类来提供可定制的时间调整概念(例如考虑时区和/或夏令时)

datetime.timezone

datetime.tzinfo 抽象基类实现为与UTC有固定偏移量的类。

该模块还包含两个常量:

  • MINYEAR

    能表示的最小的年份,值为 1

  • MAXYEAR

    能表示的最大的年份,值为 9999

以上所有的这些对象均为不可变类型。并且,date 类型的对象总是 naive 的。

timedatetime 类型的对象可以是 naiveaware 的。 若 d 是一个 datetime 类型的对象,当 d.tzinfo 不是 None 并且 d.tzinfo.utcoffset(d) 的返回值不是 None 时, daware 的。如果 d.tzinfoNone, 或者 d.tzinfo 不是 None,但 d.tzinfo.utcoffset(d) 的返回值为 None 时,dnaive 的。若 t 是一个 time 类型的对象,当 t.tzinfo 不是 None 并且 t.tzinfo.utcoffset(None) 的返回值不是 None 时,taware 的,否则 tnaive 的。

naiveaware 之间的区别并不适用于 datetime.timedelta 对象。

该模块下的几个类之间的子类关系如下:

object
    timedelta
    tzinfo
        timezone
    time
    date
        datetime

1.2 详解

1.2.1 tzinfo类

这是一个抽象基类,意味着不应该直接实例化这个类。你需要从这个类派生一个具体的子类,并且(至少)提供你使用的 datetime 方法所需的标准 tzinfo 方法的实现。datetime 模块提供 tzinfo 的一个简单的具体子类timezone,它可以表示与UTC有固定偏移的时区,如UTC本身或北美EST和EDT。

tzinfo 子类的一个实例可以传递给 datetimetime 对象的构造函数并生成对应的实例对象。这些实例对象将它们的属性视为在本地时间,而 tzinfo 对象提供方法用以显示本地时间与UTC的偏移量、时区名称和DST偏移量,这些方法都与传递给它们的日期或时间对象相关。

用于 pickling 操作的特殊要求:tzinfo 子类必须有一个可以无参数调用的 __init__() 方法,否则它可以被pickled,但可能不能再次 unpickled。这是一个在将来可能会放宽的技术要求。

tzinfo 的一个具体子类可能需要实现以下方法。具体需要哪些方法取决于对 awaredatetime 对象的使用。如果有疑问,只需全部实现即可。

  • tzinfo.utcoffset(dt)

    返回以 timedelta 对象的实例表示的本地时间到UTC的偏移量。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 异常。

  • tzinfo.dst(dt)

    如果DST信息未知,则返回 None,否则返回以 timedelta 对象实例表示的夏令时(DST)调整(UTC以东为正,UTC以西为负)。如果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)
    

    必须对每个 datetime 对象的实例 dt 返回相同的结果 dt.tzinfo == tz。对于正确的 tzinfo 子类,此表达式生成的时区的 “标准偏移量” 不应取决于日期或时间,而只取决于地理位置。datetime.astimezone() 方法的实现依赖于此,但不能检测不符合规则的 dst() 方法,必须由程序员来确保 dst() 方法得到了正确实现。如果tzinfo 子类不能保证这一点,那么 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.  Then
    
        if dston <= dt.replace(tzinfo=None) < dstoff:
            return timedelta(hours=1)
        else:
            return timedelta(0)
    

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

  • tzinfo.tzname(dt)

    将与 datetime 对象实例 dt 对应的时区名称作为字符串返回。datetime 模块没有定义有关字符串名称的内容,并且没有要求它有任何特别的意思,例如 “GMT”、“UTC”、“-500”、“-5:00”、“EDT”、“US/Eastern” 都是有效的返回。如果字符串名称未知,则返回 None。注意,这是一种方法而不是固定字符串,主要是因为一些 tzinfo 子类希望根据传递的 dt 的具体值返回不同的名称,特别是如果 tzinfo 类正在考虑夏令时。

    默认实现的 tzname() 引发 NotImplementedError

这些方法由 datetimetime 实例对象调用,以对应其相同名称的方法。一个 datetime 对象传递自身作为参数,而一个 time 对象传递 None 作为参数。因此,tzinfo 子类的方法应该准备接受 None 或类 datetime 的实例 dt 作为参数。

当传递的是 None 时,由类设计器决定最佳响应。例如,如果类想要 time 对象不参与 tzinfo 协议,则返回None 是适当的。如果没有发现标准偏移量的其他约定, utcoffset(None) 返回标准UTC偏移量可能更有用。

当将 datetime 对象传递给datetime 对象实例的方法时,dt.tzinfoself 是同一个对象 。除非用户代码直接调用 tzinfo 方法,否则可以通过 dt.tzinfo 实现调用。这样可以使得 tzinfo 方法将 dt 解释为本地时间,而不是其他时区的时间。

还有一个子类可能希望覆盖的方法:

  • tzinfo.fromutc(dt)

    这是从默认的 datetime.astimezone() 实现中调用的。当从中调用时,dt.tzinfoself,并且 datetime 对象的实例 dt 的日期和时间数据被视为表示UTC时间。fromutc() 的目的是调整日期和时间数据,返回使用 datetime 对象实例表示的与UTC时间一致的本地时间。

    大多数 tzinfo 子类应该能够继承默认的 fromutc() 实现并且不会出问题。它足够强大得以能够处理固定偏移量的时区和既考虑标准时又考虑夏令时的时区,即使后者DST转换时间在不同年份有所不同。默认fromutc() 实现可能无法正确处理由于政治原因导致的标准偏移量(来自UTC)取决于特定的日期和时间的时区。如果结果是跨越标准偏移量变化的时间之一,则 astimezone()fromutc() 的默认实现可能无法产生所需的结果。

    跳过错误处理的代码,默认的 fromutc() 实现的行为与以下代码类似:

    def fromutc(self, dt):
        # raise ValueError error if dt.tzinfo is not self
        dtoff = dt.utcoffset()
        dtdst = dt.dst()
        # raise ValueError if dtoff is None or dtdst is None
        delta = dtoff - dtdst  # this is self's standard offset
        if delta:
            dt += delta   # convert to standard local time
            dtdst = dt.dst()
            # raise ValueError if dtdst is None
        if dtdst:
            return dt + dtdst
        else:
            return dt
    

    下面的代码是一些 tzinfo 类的子类实现:

    from datetime import tzinfo, timedelta, datetime
    
    ZERO = timedelta(0)
    HOUR = timedelta(hours=1)
    SECOND = timedelta(seconds=1)
    
    # 捕获平台的本地时间概的类。
    # (在UTC偏移量和/或DST规则在过去发生过更改的时区,可能会导致历史时间的值出现错误。)
    
    import time as _time
    
    STDOFFSET = timedelta(seconds = -_time.timezone)
    if _time.daylight:
        DSTOFFSET = timedelta(seconds = -_time.altzone)
    else:
        DSTOFFSET = STDOFFSET
    
    DSTDIFF = DSTOFFSET - STDOFFSET
    
    class LocalTimezone(tzinfo):
    
        def fromutc(self, dt):
            assert dt.tzinfo is self
            stamp = (dt - datetime(1970, 1, 1, tzinfo=self)) // SECOND
            args = _time.localtime(stamp)[:6]
            dst_diff = DSTDIFF // SECOND
            # Detect fold
            fold = (args == _time.localtime(stamp - dst_diff))
            return datetime(*args, microsecond=dt.microsecond,
                            tzinfo=self, fold=fold)
    
        def utcoffset(self, dt):
            if self._isdst(dt):
                return DSTOFFSET
            else:
                return STDOFFSET
    
        def dst(self, dt):
            if self._isdst(dt):
                return DSTDIFF
            else:
                return ZERO
    
        def tzname(self, dt):
            return _time.tzname[self._isdst(dt)]
    
        def _isdst(self, dt):
            tt = (dt.year, dt.month, dt.day,
                  dt.hour, dt.minute, dt.second,
                  dt.weekday(), 0, 0)
            stamp = _time.mktime(tt)
            tt = _time.localtime(stamp)
            return tt.tm_isdst > 0
    
    Local = LocalTimezone()
    
    
    # A complete implementation of current DST rules for major US time zones.
    
    def first_sunday_on_or_after(dt):
        days_to_go = 6 - dt.weekday()
        if days_to_go:
            dt += timedelta(days_to_go)
        return dt
    
    
    # US DST Rules
    #
    # This is a simplified (i.e., wrong for a few cases) set of rules for US
    # DST start and end times. For a complete and up-to-date set of DST rules
    # and timezone definitions, visit the Olson Database (or try pytz):
    # http://www.twinsun.com/tz/tz-link.htm
    # http://sourceforge.net/projects/pytz/ (might not be up-to-date)
    #
    # In the US, since 2007, DST starts at 2am (standard time) on the second
    # Sunday in March, which is the first Sunday on or after Mar 8.
    DSTSTART_2007 = datetime(1, 3, 8, 2)
    # and ends at 2am (DST time) on the first Sunday of Nov.
    DSTEND_2007 = datetime(1, 11, 1, 2)
    # From 1987 to 2006, DST used to start at 2am (standard time) on the first
    # Sunday in April and to end at 2am (DST time) on the last
    # Sunday of October, which is the first Sunday on or after Oct 25.
    DSTSTART_1987_2006 = datetime(1, 4, 1, 2)
    DSTEND_1987_2006 = datetime(1, 10, 25, 2)
    # From 1967 to 1986, DST used to start at 2am (standard time) on the last
    # Sunday in April (the one on or after April 24) and to end at 2am (DST time)
    # on the last Sunday of October, which is the first Sunday
    # on or after Oct 25.
    DSTSTART_1967_1986 = datetime(1, 4, 24, 2)
    DSTEND_1967_1986 = DSTEND_1987_2006
    
    def us_dst_range(year):
        # Find start and end times for US DST. For years before 1967, return
        # start = end for no DST.
        if 2006 < year:
            dststart, dstend = DSTSTART_2007, DSTEND_2007
        elif 1986 < year < 2007:
            dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006
        elif 1966 < year < 1987:
            dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986
        else:
            return (datetime(year, 1, 1), ) * 2
    
        start = first_sunday_on_or_after(dststart.replace(year=year))
        end = first_sunday_on_or_after(dstend.replace(year=year))
        return start, end
    
    
    class USTimeZone(tzinfo):
    
        def __init__(self, hours, reprname, stdname, dstname):
            self.stdoffset = timedelta(hours=hours)
            self.reprname = reprname
            self.stdname = stdname
            self.dstname = dstname
    
        def __repr__(self):
            return self.reprname
    
        def tzname(self, dt):
            if self.dst(dt):
                return self.dstname
            else:
                return self.stdname
    
        def utcoffset(self, dt):
            return self.stdoffset + self.dst(dt)
    
        def dst(self, dt):
            if dt is None or dt.tzinfo is None:
                # An exception may be sensible here, in one or both cases.
                # It depends on how you want to treat them.  The default
                # fromutc() implementation (called by the default astimezone()
                # implementation) passes a datetime with dt.tzinfo is self.
                return ZERO
            assert dt.tzinfo is self
            start, end = us_dst_range(dt.year)
            # Can't compare naive to aware objects, so strip the timezone from
            # dt first.
            dt = dt.replace(tzinfo=None)
            if start + HOUR <= dt < end - HOUR:
                # DST is in effect.
                return HOUR
            if end - HOUR <= dt < end:
                # Fold (an ambiguous hour): use dt.fold to disambiguate.
                return ZERO if dt.fold else HOUR
            if start <= dt < start + HOUR:
                # Gap (a non-existent hour): reverse the fold rule.
                return HOUR if dt.fold else ZERO
            # DST is off.
            return ZERO
    
        def fromutc(self, dt):
            assert dt.tzinfo is self
            start, end = us_dst_range(dt.year)
            start = start.replace(tzinfo=self)
            end = end.replace(tzinfo=self)
            std_time = dt + self.stdoffset
            dst_time = std_time + HOUR
            if end <= dst_time < end + HOUR:
                # Repeated hour
                return std_time.replace(fold=1)
            if std_time < start or dst_time >= end:
                # Standard time
                return std_time
            if start <= std_time < end - HOUR:
                # Daylight saving time
                return dst_time
    
    
    Eastern  = USTimeZone(-5, "Eastern",  "EST", "EDT")
    Central  = USTimeZone(-6, "Central",  "CST", "CDT")
    Mountain = USTimeZone(-7, "Mountain", "MST", "MDT")
    Pacific  = USTimeZone(-8, "Pacific",  "PST", "PDT")
    

1.2.2 timezone类

timezone 类是 tzinfo 的子类,其每个实例表示与UTC有固定偏移量的时区。注意,这个类的对象不能用于表示在一年中的不同日期使用不同偏移量的位置上的时区信息,或者在对民用时间进行了历史更改的位置上的时区信息。。

该类的构造方法如下:

class datetime.timezone(offset, name=None)

参数 offset 必须是表示本地时间和UTC时间差异的 timedelta 对象实例,并且必须严格介于 -timedelta(hours=24)timedelta(hours=24) 之间,否则,将会引发 ValueError 异常。

参数 name 是可选的。如果要为其指定一个值,则其必须是用于 datetime.tzname() 方法的返回值的一个字符串。

1.2.2.1 timezone对象实例方法

timezone 对象有如下几个实例方法:

  • timezone.utcoffset(dt)

    返回构造 timezone 实例时指定的固定值。而参数 dt 将会被忽略。返回值是一个表示本地时间与UTC时间差值的timedelta 对象实例。

  • timezone.tzname(dt)

    返回构造 timezone 实例时指定的固定值。如果在构造时未提供 name 参数,那么该方法的返回值由 offset 的值确定。如果 offsettimedelta(0),那么该方法的返回值为UTC;其他情况下,该方法的返回值是形如 UTC±HH:MM 的字符串,其中 ±offset 的符号,HHMM 分别表示 offset.hoursoffset.minutes

  • timezone.dst(dt)

    通常返回 None

  • timezone.fromutc(dt)

    返回 dt + offset 。其中 dt 必须是一个 awaretzinfo 属性为 selfdatetime 对象的实例。

1.2.2.2 timezone对象类属性

timezone 对象有一个类属性:

  • timezone.utc

    表示UTC时区,值为 timezone(timedelta(0))

1.2.3 timedelta类

一个 timedelta 对象表示两个日期或时间之间的持续时间(duration)。

class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

以上所有的参数都是可选的,并且默认值都是0,参数可以是整型或浮点型,可为正也可以为负。

一个timedelta 对象内部只存储 dayssecondsmicroseconds 这三个参数,其他参数均会被进行如下转换:

  • 每毫秒(millisecond)将被转化为1000微秒(microsecond)。
  • 每分钟(minute)将被转化为60秒(second)。
  • 每小时(hour)将被转化为3600秒(second)。
  • 每星期(week)将被转化为7天(day)。

然后,将 dayssecondsmicroseconds 进行如下的标准化处理,从而使得一个 timedelta 对象只有一种唯一的表示方式:

  • 0 <= microseconds < 1000000,即microseconds取值范围
  • 0 <= seconds < 3600*24(一天当中的秒数),即seconds的取值范围
  • -999999999 <= days <= 999999999,即days的取值范围

如果有浮点型的参数并且有小数微秒,则将所有参数剩余的小数微秒加起来,并使用 四舍六入五进偶 (round-half-to-even) 的规则进行进位处理。如果没有参数是浮点型,则转化和规范化过程是精确的(不会丢失任何信息)。

如果 days 的标准化值超出了指定的范围,则会引发 OverflowError 异常。

如果对上述的文字说明不太理解,看看下面的例子应该就明白了:

>>> from datetime import timedelta
>>> td = timedelta(10, 10, 10, 10, 10, 10, 10)
>>> td
datetime.timedelta(days=80, seconds=36610, microseconds=10010)

上例中timedelta 对象 td 的构造过程如下:

  1. 将毫秒转化为微秒:10 milliseconds = 1000*10 microseconds =10000 microseconds

  2. 将分钟转化为秒:10 minutes = 60*10 seconds = 600 seconds

  3. 将小时转化为秒:10 hours = 3600*10 seconds = 36000 seconds

  4. 将星期转化为天:10 weeks = 7*10 days = 70 days

  5. 计算毫秒和微秒之和得到 microseconds参数的值:10000 microseconds + 10 microseconds = 10010 microseconds

  6. 计算分钟、小时和秒之和得到seconds参数的值:600 seconds + 36000 seconds + 10 seconds = 36610 seconds

  7. 计算星期和天之和得到days参数的值:70 days + 10days = 80 days

  8. 判断microseconds、seconds和days参数的值是否在规定的取值范围内,即 0

    0timedelta 对象 td 的表示形式:

    datetime.timedelta(days=80, seconds=36610, microseconds=10010)

我们再来看下一个例子:

>>> td1 = timedelta(10, 10, 10, 1000, 10, 25, 10)
>>> td1
datetime.timedelta(days=81, seconds=4211, microseconds=10)
  1. 将毫秒转化为微秒:10 milliseconds = 1000*1000 microseconds =1000000 microseconds

  2. 将分钟转化为秒:10 minutes = 60*10 seconds = 600 seconds

  3. 将小时转化为秒:10 hours = 3600*25 seconds = 90000 seconds

  4. 将星期转化为天:10 weeks = 7*10 days = 70 days

  5. 计算毫秒和微秒之和得到 microseconds参数的值:1000000 microseconds + 10 microseconds = 1000010 microseconds

  6. 计算分钟、小时和秒之和得到seconds参数的值:600 seconds + 90000 seconds + 10 seconds = 90610 seconds

  7. 计算星期和天之和得到days参数的值:70 days + 10days = 80 days

  8. 判断microseconds、seconds和days参数的值是否在规定的取值范围内,即 0

    0timedelta 对象 td1 的表示形式:

    datetime.timedelta(days=81, seconds=4211, microseconds=10)

下面的例子将演示当 days 参数的值超过其取值范围时的情况:

>>> td2 = timedelta(days = 1000000000)
Traceback (most recent call last):
  File "", line 1, in <module>
OverflowError: days=1000000000; must have magnitude <= 999999999

1.2.3.1 timedeltad对象的类属性

timedelta 包含如下几个类属性:

  • timedelta.min

    表示最小timedelta对象 timedelta(-999999999)

  • timedelta.max
    表示最大timedelta对象 timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999)

  • timedelta.resolution

    表示不相等的两个timedelta对象的最小差值的timedelta 对象timedelta(microseconds=1)

>>> timedelta.max
datetime.timedelta(days=999999999, seconds=86399, microseconds=999999)
>>> timedelta.min
datetime.timedelta(days=-999999999)
>>> timedelta.resolution
datetime.timedelta(microseconds=1)

注意,由于要进行标准化处理,所以 timedelta.max > -timedelta.min,并且 -timedelta.max 不表示一个timedelta对象。

>>> timedelta.max > -timedelta.min
True
>>> -timedelta.max
Traceback (most recent call last):
  File "", line 1, in <module>
OverflowError: days=-1000000000; must have magnitude <= 999999999

1.2.3.2 timedelta类实例属性

timedelta实例包含如下几个只读属性:

  • days
  • seconds
  • microseconds
>>> td = timedelta(10, 10, 10, 10, 10, 10, 10)
>>> td.days
80
>>> td.seconds
36610
>>> td.microseconds
10010

1.2.3.3 timedelta类实例方法

timedelta实例对象有一个实例方法**timedelta.total_seconds()**,返回当前实例所表示持续时间总共包含的秒数:

>>> td = timedelta(10, 10, 10, 10, 10, 10, 10)
>>> td.total_seconds()
6948610.01001

1.2.4 data类

date 对象表示理想化日历中的日期(由年、月、日组成),即当前公历日日历在两个方向上无限扩展。第一年的1月1日被称为第一日,第一年的1月2日被称为第二日,以此类推。这与德肖维茨和林戈尔德的《历法计算》(Calendrical Calculations)中对 “预期公历” 的定义相吻合,它是所有计算的基本历法。要了解在格雷戈里公会和许多其他日历系统之间进行转换的算法,请参阅其具体内容。

class datetime.date(year, month, day)

所有参数都是必须的,并且必须为整数,各个参数的取值范围如下:

  • MINYEAR <= year <=MAXYEAR
  • 1 <= month <= 12
  • 1 <= day <= 给定的year和month参数中的天数

如果某个参数超过了取值范围,则引发 ValueError 异常。

1.2.4.1 date对象类方法

date 类包含如下几个类方法,均可用来构造一个date 类型的对象:

  • date.today()

    返回当前的本地日期,等于date.fromtimestamp(time.time())

  • date.fromtimestamp(timestamp)

    返回POSIX时间戳对应的本地日期,与 time.time() 返回的日期类似。如果时间戳超出了当前平台的C语言的 localtime() 函数支持的值的范围,那么可能会引发OverflowError 异常,如果localtime() 方法执行失败,则会引发OSError 异常。常见的做法是将年份限制在1970到2038之间。注意,对于在时间戳概念中包含闰秒的非posix系统,fromtimestamp() 会忽略闰秒。

  • date.fromordinal(ordinal)

    返回与给定的公历序数对应的 date 对象的实例,其中第一年1月1日的序数为1。如果不满足 1 <= ordinal <= date.max.toordinal(),则会引发 ValueError 异常。对于任意日期 d,date.fromordinal(d.toordinal()) == d。

  • date.fromisoformat(date_string)

    返回字符串 date_string 所表示的 date 对象实例,其中 date_string 中的日期的格式与date.isoformat() 返回的日期格式一致。具体来说,这个函数支持格式为YYYY-MM-DD 的字符串。

    注意,这并不支持解析任意的ISO 8601字符串——它只是作为date.isoformat() 的反向操作。

>>> from datetime import date
>>> date.today()
datetime.date(2019, 2, 28)
>>> import time as _time
>>> date.fromtimestamp(_time.time())
datetime.date(2019, 2, 28)
>>> date.today().toordinal()
737118
>>> date.fromordinal(737118)
datetime.date(2019, 2, 28)
>>> date_str = date.today().isoformat()
>>> date_str
'2019-02-28'
>>> date.fromisoformat(date_str)
datetime.date(2019, 2, 28)

1.2.4.2 date对象类属性

date 类包含如下几个类属性:

  • date.min

    可表示的最小的日期:date(MINYEAR, 1, 1)

  • date.max

    可表示的最大的日期:date(MAXYEAR, 12, 31)

  • date.resolution

    两个不相等的date 对象的最小差值,等于timedelta(days=1)

  • date.year

>>> date.min
datetime.date(1, 1, 1)
>>> date.max
datetime.date(9999, 12, 31)
>>> date.resolution
datetime.timedelta(days=1)

1.2.4.3 date对象实例属性

date 对象的实例有如下几个只读实例属性:

  • year

    date 实例对象所表示的日期的年份

  • month

    date 实例对象所表示的日期的月份

  • day

    date 实例对象所表示的日期的天

>>> d = date.today()
>>> d.year
2019
>>> d.month
2
>>> d.day
28

date 实例对象支持如下操作:

操作 结果
date2 = date1 + timedelta date2表示给date1增加 timedeltla.days 天。(1)
date2 = date1 - timedelta 计算date2,使得date2 + timedelta == date1。(2)
timedelta = date1 - date2 计算date1和date2之间的差值。(3)
date1 < date2 如果date1是比date2更早的时间,则date1小于date2。(4)

注解:

(1). 如果 timedelta.days < 0,则 date2在日期上向后移动(即date2是比date1更早的日期);如果 timedelta.days == 0,则date2与date1相等(即date2和date1表示相同的日期);如果timedelta.days > 0,则date2在日期上向前移动(即date2是比date1更晚的日期)。之后,timedelta.seconds 和 timedelta.microseconds 将会被忽略。如果 date2.year 小于 MINYEAR 或大于 MAXYEAR,则会引发 OverflowError 异常。

(2). 这不完全等同于 date1 + (-timedelta),因为 -timedelta 在单独的情况下可能会溢出,而 date2 - timedelta不会。timedelta.seconds 和 timedelta.microseconds 将会被忽略。

(3). 结果是精确的,并且不会溢出。之后,timedelta.seconds 和 timedelta.microseconds 都是0,并且 date2 + timedelta == date1。

(4). 只有当date1.toordinal() < date2.toordinal() 时,date1 < date2。为了防止比较操作回退到默认的比较对象地址的方式,如果另一比较对象不是 date 对象实例,通常会引发 TypeError 异常。但是,如果另一个比较对象具有 timetuple() 属性,则会返回 NotImplemented 。这个钩子为其他种类的日期对象实现混合型比较提供了机会,否则,将一个 date 对象实例与一个不同类型的对象进行非相等(==)或不等(!=)比较时,将会引发 TypeError 异常。

date 对象的实例可以作为字典的键。在布尔上下文中,所有的 date 对象实例均会被当作 True

1.2.4.4 date对象实例方法

date实例对象有如下几个实例方法:

  • date.replace(year=self.year, month=self.month, day=self.day)

    将原实例对象中的属性值替换为由关键字参数指定的新的值,其他属性值保持不变。

    >>> d = date.today()
    >>> d
    datetime.date(2019, 2, 28)
    >>> d.replace() # 不指定参数,则返回相同的对象
    datetime.date(2019, 2, 28)
    >>> d.replace(2018) # 只替换年份
    datetime.date(2018, 2, 28)
    >>> d.replace(2018, 1, 17) # 替换年份、月份和日
    datetime.date(2018, 1, 17)
    
  • date.timetuple()

    返回一个 time.struct_time 对象实例,类似于 time.localtime() 的返回值。其中,hours,minuts和seconds参数的值为0,DST flag的值为 -1。如果 d 是一个date对象的实例,那么,d.timetuple() 等价于以下表达式:

    ime.struct_time((d.year, d.month, d.day, 0, 0, 0, d.weekday(), yday, -1))

    其中,yday = d.toordinal() - date(d.year, 1, 1) + 1 。

    >>> d = date.today()
    >>> d.timetuple()
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=60, tm_isdst=-1)
    >>> d.timetuple().tm_year
    2019
    >>> d.timetuple().tm_mon
    3
    >>> yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1
    >>> yday
    60
    >>> _time.struct_time((d.year, d.month, d.day, 0, 0, 0, d.weekday(), yday, -1))
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=60, tm_isdst=-1)
    >>> d1 = date(2019, 3, 1)
    >>> d1
    datetime.date(2019, 3, 1)
    >>> t = d1.timetuple()
    >>> for i in t:
    ...     print(i)
    ... 
    2019          # year
    3             # month
    1             # day
    0
    0
    0
    4             # weekday (0 = Monday)
    60            # 60th day in the year
    -1
    
  • date.toordinal()

    返回date 实例对象的预期公历序数,其中第一年的1月1日的序数为1。对于任何日期对象d, date.fromordinal(d.toordinal()) == d

    >>> date.today().toordinal()
    737119
    
  • date.weekday()

    返回当前日期在一周内的序号,即星期几,其中周一表示为0,周日表示为6。

    >>> date.today().weekday()
    4
    
  • date.isoweekday()

    返回当前日期在一周内的序号,即星期几,其中周一表示为1,周日表示为7。

    >>> date.today().isoweekday()
    5
    
  • date.isocalendar()

    返回一个包含给定日期对象的ISO year、ISO week number和ISO weekday的三元组。

    ISO日历是公历的一种变体。ISO年包括52或53个整周,其中一周从星期一开始到星期天结束。ISO年的第一周是一年中第一个包含星期四的(公历)日历周。这个周为周数1,并且这个周的星期四的ISO年和公历年相同。

    例如,2004年从星期四开始,因此ISO 2004年的第一周从2003年12月29日星期一开始,到2004年1月4日星期日结束,因此 date(2003,12,29).isocalendar() ==(2004, 1, 1)date(2004,1,4).isocalendar() ==(2004, 1, 7)

    >>> date(2003, 12, 29).isocalendar()
    (2004, 1, 1)
    >>> date(2004, 1, 4).isocalendar()
    (2004, 1, 7)
    >>> d = date.today
    >>> d
    datetime.date(2019, 3, 1)
    >>> ic = d.isocalendar()
    >>> for i in ic:
    ...     print(i)
    ... 
    2019       # ISO year
    9          # ISO week number
    5          # ISO day number (1 = Monday)
    
  • date.isoformat()

    以ISO 8601格式返回表示日期的字符串’YYYY-MM-DD’。例如,date(2002, 12, 4).isoformat() == '2002-12-04'

    >>> date.today().isoformat()
    '2019-03-01'
    
  • date.__str__()

    对date 的实例对象dstr(d) 等同于 d.isoformat()

    >>> date.today().isoformat()
    '2019-03-01'
    >>> str(date.today())
    '2019-03-01'
    >>> d.isoformat()
    '2019-03-01'
    
  • date.ctime()

    返回表示日期的字符串。例如 date(2002, 12, 4).ctime() == 'Wed Dec 400:00:00 2002' 。在原生的C函数ctime()time.ctime()调用它,但是date.ctime() 不调用它)遵守C标准的平台上,对于date的实例对象 dd.ctime() 等同于 time.ctime(time.mktime(d.timetuple()))

    >>> date.today().ctime()
    'Fri Mar  1 00:00:00 2019'
    >>> _time.ctime(_time.mktime(date.today().timetuple()))
    'Fri Mar  1 00:00:00 2019'
    
  • date.strftime(format)

    返回表示日期的字符串,日期格式由显式的格式化字符串指定。如果格式化代码中引用到了小时、分或秒,那么对应的值将被置为0。完整的格式化指令,请参考 strftime() and strptime() Behavior 。

    >>> d = date.today
    >>> d
    datetime.date(2019, 3, 1)
    >>> d.strftime('%d/%m/%y')
    '01/03/19'
    
  • date.__format__(format)

    date.strftime() 相同。同时,这也使得在使用 str.format() 时,可以使用带格式的字符串文本为日期对象指定格式字符串。完整的格式化指令,请参考 strftime() and strptime() Behavior 。

    >>> d = date.today
    >>> d
    datetime.date(2019, 3, 1)
    >>> 'The {1} is {0:%d}, the {2} is {0:%B}.'.format(d, "day", "month")
    'The day is 01, the month is March.'
    

1.2.5 time类

time 对象表示一天中的(本地)时间,独立于任何特定的一天,并且可以通过 tzinfo 对象进行调整。

class datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0 )

所有参数都是可选的。tzinfo 可以是 None 或者 tzinfo 抽象类的子类的实例;其他参数可以是整型,取值范围如下:

  • 0 <= hour < 24
  • 0 <= minute < 60
  • 0 <= second < 60
  • 0 <= microsecond < 1000000
  • fold 0或1

如果某个参数超过了其取值范围,会引发 ValueError 异常。除过tzinfo参数,其他参数的默认值均为0,tzinfo 参数的默认值是 None

1.2.5.1 time对象类属性

  • time.min

    可以表示的最早的时间,值为 time(0, 0)

    >>> time.min
    datetime.time(0, 0)
    
  • time.max

    可以表示的最晚的时间,值为 time(23, 59, 59, 999999)

    >>> time.max
    datetime.time(23, 59, 59, 999999)
    
  • time.resolution

    两个不相等的 time 对象的最小差值,即 timedelta(microseconds=1)

    不过需要注意, time 对象不支持算术运算。

    >>> time.resolution
    datetime.timedelta(microseconds=1)
    

time 对象实例支持如下操作:

  • time 对象实例之间的比较。

    如果 time 实例对象 a 是比 time 实例对象 b 更早的时间,则 a < b。如果一个操作数是 naive 的,而另一个操作数是 aware 的,那么在进行顺序比较时将会引发 TypeError 异常。对于相等比较,一个 naive 的实例永远不会等于一个 aware 的实例。

    如果两个操作数都是 aware 的,并且具有相同的 tzinfo 属性,那么将忽略共同的tzinfo 属性,并比较基本的 times 数据;如果两个操作数都是 aware 的并且具有不同的 tzinfo 属性,则首先通过减去它们的UTC偏移量(从self.utcoffset()获得)来调整比较数,然后再进行比较。为了防止混合类型之间的比较回退到默认的以对象地址进行的比较,当将time对象与其他类型的对象进行非相等(==)和不等(!=)比较时,会引发TypeError 异常。

  • 可以当作字典的键。

  • 可进行高效的 pickling 操作。

1.2.5.2 time对象实例属性

time 对象实例有如下几个只读属性:

  • time.hour

    time 对象实例中的小时(hour),范围为[0, 23]

  • time.minute

    time 对象实例中的分钟(minute),范围为[0, 59]

  • time.second

    time 对象实例中的秒(second),范围为[0, 59]

  • time.microseond

    time 对象实例中的微秒,范围为[0, 999999]

  • time.tzinfo

    time 构造方法中传递给 tzinfo 参数的对象。如果未给 tzinfo 参数传递值,则为 None

1.2.5.3 time对象类方法

time 对象有一个类方法 time.fromisoformat(time_string),并且这个方法也是 time 类的另一个构造方法。

classmethod time.fromisoformat(time_string)

该方法根据给定的time_string 参数的字符串值和这个字符串值的时间格式,返回一个 time 对象实例,其中 time_string 参数的值所表示的时间格式与 time.isoformat() 的返回值一致。具体来说,该函数支持格式为HH[:MM[:SS[.fff[fff]]] [+HH:MM[:SS[.ffffff]] 的字符串。

注意,该方法并不支持解析任意的ISO 8601字符串——它只是作为time.isoformat()的逆操作

1.2.5.4 time对象实例方法

time 对象有如下几个实例方法:

  • time.replace(hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, *, fold=0)

    返回由指定的关键字参数替换time 对象实例中同名属性值后的新的 time 对象实例。请注意,可以指定 tzinfo=None 来从 aware 时间创建 naive 时间,并且在此过程中不会进行时间数据的转换。

    >>> t = time(14, 30, 15, 500)
    >>> t
    datetime.time(14, 30, 15, 500)
    >>> t.replace(15, 50, 10, 300)
    datetime.time(15, 50, 10, 300)
    
  • time.isoformat(timespec=‘auto’)

    返回一个表示时间的字符串,这个字符串的格式为ISO 8601格式 HH:MM:SS.ffffff;如果 microsecond 为0,则格式为 HH:MM:SS;如果 utcoffset() 方法的返回值不为 None,则追加一个字符串,给出UTC偏移量, 其格式为 HH:MM:SS.ffffff+HH:MM[:SS[.ffffff];或者,如果 self.microsecond 是0, 则格式为 HH:MM:SS+HH:MM[:SS[.ffffff]]

    可选参数 timespec 指定要包含的时间的其他组件的数量(默认值是 auto )。它可以是以下值:

    • auto :如果 microsecond 为0,则与 second 相同,否则,与 microseconds 相同。
    • hours:包含 hour,格式为 HH
    • minutes:包含 hourminute,格式为 HH:MM
    • seconds:包含 hourminutesecond,格式为 HH:MM:SS
    • milliseconds:包含完整的时间格式,但是会忽略微秒,并表示为这样的格式 HH:MM:SS.sss
    • microseconds:包含完整的时间格式 HH:MM:SS.ffffff

    如果指定的 timespec 参数的值不在上述列举的范围内,则会引发 ValueError 异常。

    >>> t = time(1, 1, 1, 300)
    >>> t
    datetime.time(1, 1, 1, 300)
    >>> t.isoformat(timespec='milliseconds')
    '01:01:01.000'
    >>> t.isoformat(timespec='auto')
    '01:01:01.000300'
    >>> t.isoformat(timespec='hours')
    '01'
    >>> t.isoformat(timespec='minutes')
    '01:01'
    >>> t.isoformat(timespec='seconds')
    '01:01:01'
    >>> t.isoformat(timespec='microseconds')
    '01:01:01.000300'
    
  • time.__str__()

    对于一个 time 对象实例 tstr(t) 等同于 t.isoformat()

    >>> t = time(1, 1, 1, 200)
    >>> str(t)
    '01:01:01.000200'
    >>> t.isoformat()
    '01:01:01.000200'
    
  • time.strftime(format)

    返回表示时间的字符串,时间格式由显式的格式化字符串指定。完整的格式化指令,请参考 strftime() and strptime() Behavior 。

  • time.__format__(format)

    time.strftime() 方法功能相同。同时,这也使得在使用 str.format() 时,可以使用带格式的字符串文本为时间对象指定格式字符串。完整的格式化指令, strftime() and strptime() Behavior 。

  • time.utcoffset()

    返回使用 datetime.timedelta 对象实例表示的 time 实例对象的时区偏移量, UTC东部为正(UTC西部为负)。如果 tzinfoNone,则返回 None;否则返回 self.tzinfo.utcoffset(self) 的返回值;如果该方法的返回值不是 None 或者一个小于一天的 timedelta 对象,则会引发异常。

  • time.dst()

    返回 time 实例对象的DST偏移量。如果 tzinfoNone,则返回 None;否则返回 self.tzinfo.dst(self) 的返回值;如果DST未生效,则返回值为 datetime.timedelta(0),如果DST生效,则返回使用 datetime.timedelta 对象实例表示的DST偏移量。如果该方法的返回值不是 None 或者一个小于一天的 timedelta 对象,则会引发异常。

  • time.tzname()

    返回 time 实例对象的时区名称。如果 tzinfoNone,则返回 None;否则返回 self.tzinfo.tzname(None) ;如果该方法的返回值不是 None 或者一个字符串对象,则会引发异常。

>>> class GMT1(tzinfo):
...     def utcoffset(self, dt):
...         return timedelta(hours=1)
...     def dst(self, dt):
...         return timedelta(0)
...     def tzname(self, dt):
...         return 'Europe/Prague'
... 
>>> t = time(12, 10, 30, tzinfo=GMT1())
>>> t
datetime.time(12, 10, 30, tzinfo=<__main__.GMT1 object at 0x108171588>)
>>> gmt = GMT1()
>>> t.isoformat()
'12:10:30+01:00'
>>> t.dst()
datetime.timedelta(0)
>>> t.tzname()
'Europe/Prague'
>>> t.utcoffset()
datetime.timedelta(seconds=3600)
>>> t1 = time(13, 40, 14) # tzinfo参数值为None
>>> t1.utcoffset()        # 返回值为None
>>> t1.tzname()           # 返回值为None
>>> t1.dst()              # 返回值为None

1.2.6 datetime类

datetime 对象是一个包含 date 对象和 time 对象所有信息的单个对象。像 date 对象一样,datetime 假设当前公历向两个方向扩展。像时间对象一样,datetime假设每天正好有3600*24秒。

datetime 类的构造函数如下:

class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0,tzinfo=None)

其中,yearmonthday 三个参数是必须的。tzinfo 可以是 Nonetzinfo 子类的实例。其余参数必须是整形,各自的取值范围如下:

  • MINYEAR <= year <= MAXYEAR
  • 1 <= month <= 12
  • 1 <= day <= 给定的年份内给定月份的天数
  • 0 <= hour < 24
  • 0 <= minute < 60
  • 0 <= second < 60
  • 0 <= microsecond < 1000000
  • fold 0或1

1.2.6.1 datetime对象的类方法

datetime 对象有如下几个类方法,同时,这些类方法也是 datetime 类的构造方法:

  • datetime.today()

    返回表示当前本地日期时间的datetime 对象,其中 tzinfo 参数值为 None。该方法的返回值等同于 datetime.fromtimestamp(time.time())

    >>> import time as _time
    >>> dt = datetime.today()
    >>> dt
    datetime.datetime(2019, 3, 1, 17, 38, 41, 90585)
    
  • datetime.now(tz=None)

    返回表示当前本地日期时间的datetime 对象。如果可选参数tzNone 或者未指定,该方法与 datetime.today() 方法相似。但是,如果可能,通过 time.time 时间戳可以提供更高的精度(例如,这在提供C gettimeofday() 函数的平台上是可能的)。

    如果 tz 参数不为 None,则其必须为 tzinfo 抽象基类的子类实例,并且当前日期和时间将被转换为使用 tz 指定的时区表示。这种情况下,结果等价于:

    tz.fromutc(datetime.utcnow().replace(tzinfo=tz))

    >>> class GMT1(tzinfo):
    ...     def utcoffset(self, dt):
    ...         return timedelta(hours=1)
    ...     def dst(self, dt):
    ...         return timedelta(0)
    ...     def tzname(self, dt):
    ...         return 'Europe/Prague'
    ... 
    >>> gmt = GMT1()
    >>> dt = datetime.now(tz=gmt)
    >>> str(dt)
    '2019-03-01 10:52:33.900215+01:00'
    
  • datetime.utcnow()

    返回当前UTC日期和时间, tzinfoNone。该方法类似于 datetime.now() ,但是返回的是表示当前UTC日期和时间的 naivedatetime 对象实例。要获取表示当前UTC日期和时间的 awaredatetime 对象实例,可以使用 datetime.now(timezone.utc)

    >>> dt2 = datetime.utcnow()
    >>> dt2
    datetime.datetime(2019, 3, 1, 10, 10, 52, 172822)
    >>> dt3 = datetime.now(tz=timezone.utc)
    >>> dt3
    datetime.datetime(2019, 3, 1, 10, 11, 20, 885170, tzinfo=datetime.timezone.utc)
    
  • datetime.fromtimestamp(timestamp, tz=None)

    返回POSIX时间戳对应的本地日期和时间,就像 time.time() 的返回值。如果可选参数 tzNone 或未指定,则时间戳将转换为平台的本地日期和时间,并且返回的datetime对象是 naive 的。

    如果 tz 不是 None,那么它必须是 tzinfo 抽象基类的子类的一个实例,并且时间戳被转换为 tz 的时区。在这种情况下,结果等价于:

    tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))

    如果时间戳超出平台C localtime()gmtime() 函数支持的值的范围,fromtimestamp() 可能会引发 OverflowError 异常。如果 localtime()gmtime() 执行失败,则会引发 OSError 异常。常见的做法是将年份限制在1970到2038之间。注意,对于在时间戳概念中包含闰秒的非posix系统,fromtimestamp() 会忽略闰秒,这可能使得两个相差1秒的时间戳产生相同的 datetime 实例对象。参见utcfromtimestamp ()

    >>> dt = datetime.now()
    >>> ts = dt.timestamp()
    >>> dt1 = datetime.fromtimestamp(ts)
    >>> dt1
    datetime.datetime(2019, 3, 1, 18, 24, 18, 317862)
    >>> dt2 = datetime.fromtimestamp(ts, tz=gmt)
    >>> dt2
    datetime.datetime(2019, 3, 1, 11, 24, 18, 317862, tzinfo=<__main__.GMT1 object at 0x108171668>)
    >>> str(dt1)
    '2019-03-01 11:24:18.317862+01:00'
    >>> str(dt2)
    '2019-03-01 11:24:18.317862+01:00'
    
  • datetime.utcfromtimestamp(timestamp)

    返回与POSIX时间戳对应的UTC datetime ,其中 tzinfoNone。如果时间戳超出了平台C gmtime()函数支持的值的范围,那么可能会导致 OverflowError 异常。如果gmtime() 执行失败则会引发 OSError 异常。常见的做法是将年份限制在1970到2038之间。

    要获取 awaredatetime 对象实例,可以调用 fromtimestamp() 方法:

    >>> ts = datetime.now().timestamp()
    >>> datetime.fromtimestamp(ts, timezone.utc)
    datetime.datetime(2019, 3, 1, 10, 33, 45, 746328, tzinfo=datetime.timezone.utc)
    

    在兼容POSIX的平台上,上述方法的返回值等价于以下表达式:

    >>> ts = datetime.now().timestamp()
    >>> datetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=ts)
    datetime.datetime(2019, 3, 1, 10, 33, 45, 746328, tzinfo=datetime.timezone.utc)
    

    但后者总是支持完整的年份范围:[MINYEAR, MAXYEAR] 。

  • datetime.fromordinal(ordinal)

    返回给定的公历序数对应的 datetime 对象实例,其中第一年的1月1日的序数为1。如果不满足 1 <= ordinal <= datetime.max.toordinal(),则会引发 ValueError 异常。其中返回的 datetime 对象实例的小时、分钟、秒和微秒都为0,tzinfo为 None

    >>> od = date.today().toordinal()
    >>> od
    737119
    >>> datetime.fromordinal(od)
    datetime.datetime(2019, 3, 1, 0, 0)
    
  • datetime.combine(date, time, tzinfo=self.tzinfo)

    返回一个新的 datetime 对象,其日期组件等于给定日期对象的日期组件,其时间组件等于给定时间对象的时间组件。如果提供了 tzinfo 参数,则使用其值设置结果的 tzinfo 属性,否则使用 time 参数的 tzinfo 属性。

    对于任意 datetime 对象 dd == datetime.combine(d.date(), d.time(), d.tzinfo)。如果 date 的值是 datetime 对象,则忽略其时间组件和 tzinfo 属性。

    >>> d = date.today()
    >>> d
    datetime.date(2019, 3, 1)
    >>> t = time(14, 30, 25)
    >>> t
    datetime.time(14, 30, 25)
    >>> ntd = datetime.combine(d, t)
    >>> ntd
    datetime.datetime(2019, 3, 1, 14, 30, 25)
    >>> ntd1 = datetime.combine(d, t, gmt)
    >>> ntd1
    datetime.datetime(2019, 3, 1, 14, 30, 25, tzinfo=<__main__.GMT1 object at 0x108171668>)
    >>> str(ntd1)
    '2019-03-01 14:30:25+01:00'
    
  • datetime.fromisoformat(date_string)

    date.isoformat()datetime.isoformat() 发出的格式之一返回 date_string 对应的 datetime 对象实例。具体来说,该函数支持如下格式的字符串:

    YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]]

    其中*可以匹配任何单个字符。

    警告:这并不支持解析任意的ISO 8601字符串——它只是作为datetime.isoformat()的反向操作。

    >>> dt = datetime.now()
    >>> dt.isoformat()
    '2019-03-01T19:04:18.736531'
    >>> dt.fromisoformat(dt.isoformat())
    datetime.datetime(2019, 3, 1, 19, 4, 18, 736531)
    >>> date_str = '2019-03-01 19:04:18'
    >>> dt.fromisoformat(date_str)
    datetime.datetime(2019, 3, 1, 19, 4, 18)
    
  • datetime.strptime(date_string, format)

    返回一个 date_string 对应的 datetime 对象实例。这相当于如下的表达式的值:

    datetime(*(time.strptime(date_string, format)[0:6]))

    如果 date_string 参数和 format 参数不能被 time.strptime() 解析,或者它们解析后的返回值不是一个时间元组,就会引发 ValueError 异常。有关格式化指令的完整列表,请参见 strftime() and strptime() Behavior.

    >>> dt = datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M")
    >>> dt
    datetime.datetime(2006, 11, 21, 16, 30)
    

1.2.6.2 datetime 对象类属性

  • datetime.min

    表示 datetime 对象实例能表示的最早的日期时间,等同于:

    datetime(MINYEAR, 1, 1, tzinfo=None)

  • datetime.max

    表示 datetime 对象实例能表示的最晚的日期时间,等同于:

    datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999,tzinfo=None)

  • datetime.resolution

    表示两个不相等的 datetime 对象实例的最小差值,等同于:

    timedelta(microseconds=1)

>>> datetime.min
datetime.datetime(1, 1, 1, 0, 0)
>>> datetime.max
datetime.datetime(9999, 12, 31, 23, 59, 59, 999999)
>>> datetime.resolution
datetime.timedelta(microseconds=1)

1.2.6.3 datetime对象实例属性

datetime 对象实例有如下几个只读属性:

  • datetime.year

    datetime 对象实例的年份

  • datetime.month

    datetime 对象实例的月份

  • datetime.day

    datetime 对象实例的天

  • datetime.hour

    datetime 对象实例的小时

  • datetime.minute

    datetime 对象实例的分钟

  • datetime.second

    datetime 对象实例的秒

  • datetime.microsecond

    datetime 对象实例的微秒

  • datetime.tzinfo

    datetime 对象实例的时区

  • datetime.fold

>>> dt = datetime.now(gmt)
>>> dt
datetime.datetime(2019, 3, 1, 12, 25, 58, 595967, tzinfo=<__main__.GMT1 object at 0x108171668>)
>>> dt.year
2019
>>> dt.month
3
>>> dt.day
1
>>> dt.hour
12
>>> dt.minute
25
>>> dt.second
58
>>> dt.microsecond
595967
>>> dt.tzinfo
<__main__.GMT1 object at 0x108171668>

datetime 对象实例支持如下操作:

Operation Result
datetime2 = datetime1 + timedelta (1)
datetime2 = datetime1 - timedelta (2)
timedelta = datetime1 - datetime2 (3)
datetime1 < datetime2 (4) 比较两个datetime 对象实例

(1). 如果 timedelta.days > 0,那么datetime2表示比datetime1更晚的时间;如果如果timedelta.days < 0, 那么datetime2表示比datetime1更早的时间。datetime2与datetime1的 tzinfo 属性值相同,并且 datetime2 - datetime1 == timedelta。如果datetime2.year 大于MAXYEAR或者datetime2.year小于MINYEAR,将会引发 OverflowError 异常。注意,即使 datetime1是 aware 的,在计算过程中,也不会出现时区的调整。

(2). 表示计算出一个 datetime 对象实例datetime2,使得 datetime2 + timedelta == datetime1。另外,datetime2与datetime1的 tzinfo 属性值相同,并且即使datetime1是 aware 的,在计算完以后,也不会出现时区的调整。

(3). 只有当两个操作数都是 aware的,或者两个操作数都是 naive 的,才可以定义从一个 datetime 对象实例中减去另一个 datetime 对象实例。如果其中一个是 aware 的,而另一个是 naive 的,则会引发 TypeError 异常。

如果两者都是 naive 的,或者都是有 aware 的,并且具有相同的 tzinfo 属性,则将会忽略 tzinfo 属性,并且结果会是一个 timedelta 对象实例 t,使得 datetime2 + t == datetime1。在这种情况下不会做时区调整。

如果两者都是有 aware 的,并且具有不同的 tzinfo 属性,那么在计算 a-b 时会先将a和b转换为 naive的UTC日期时间然后再进行计算。在不会溢出的情况下,结果将等于:

(a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset())。

(4). 当datetime1表示的是比datetime2更早的时间时,我们认为 datetime1小于datetime2。如果一个比较对象是 naive 的,而另一个比较对象是 aware的,那么如果尝试进行顺序比较时,则会引发 TypeError 异常。对于相等比较,naivedatetime 对象实例永远不等于 awaredatetime 对象实例。

如果两个比较数都是 aware 的,并且具有相同的 tzinfo 属性,则忽略公共 tzinfo 属性并比较基准日期时间。如果两个比较数都是 aware 的并且具有不同的 tzinfo 属性,则首先通过减去它们的UTC偏移量(从self.utcoffset()获得)来调整比较数。

注意,为了防止比较退回到比较对象地址的默认模式,如果另一个操作数不是datetime对象,那么datetime比较通常会引发 TypeError 异常。但是,如果另一个比较数具有timetuple()属性,则引发 NotImplemded 异常。这个钩子为其他类型的日期对象提供了实现混合类型比较的机会。如果另一个比较数不具有 timetuple() 属性,当将datetime对象与另一种类型的对象进行比较时,则会引发 TypeError 异常,除非是进行相等比较(==)或不相等比较(!=)。

datetime 对象实例可以作为字典的键。在布尔型上下文中, datetime 对象实例总是被当作 True

1.2.6.4 datetime 对象的实例方法

  • datetime.date()

    返回与 datetime对象实例有相同的year、month和day属性的 date 对象实例。

    >>> dt = datetime.now()
    >>> dt
    datetime.datetime(2019, 3, 2, 16, 47, 22, 670443)
    >>> dt.date()
    datetime.date(2019, 3, 2)
    
  • datetime.time()

    返回与 datetime对象实例有相同的hour、minute、second、microsecond、fold属性的 time 对象实例,并且tzinfo属性为None

    >>> dt = datetime.now()
    >>> dt
    datetime.datetime(2019, 3, 2, 16, 52, 34, 189630)
    >>> t = dt.time()
    >>> t
    datetime.time(16, 52, 34, 189630)
    >>> t.tzinfo is None
    True
    
  • datetime.timetz()

    返回与 datetime对象实例有相同的hour、minute、second、microsecond、fold和tzinfo属性的 time 对象实例

    >>> dt = datetime.now(tz=gmt)
    >>> dt
    datetime.datetime(2019, 3, 2, 9, 54, 56, 808581, tzinfo=<__main__.GMT1 object at 0x108171668>)
    >>> t = dt.timetz()
    >>> t
    datetime.time(9, 54, 56, 808581, tzinfo=<__main__.GMT1 object at 0x108171668>)
    >>> dt.tzinfo == t.tzinfo
    True
    
  • datetime.replace(year=self.year, month=self.month, day=self.day, hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, ** fold=0*)

    返回由指定的关键字参数替换datetime 对象实例中同名属性值后的新的 datetime 对象实例。请注意,可以指定 tzinfo=None 来从 awaredatetime 对象实例创建 naivedatetime 对象实例,而不需要转换日期和时间数据。

    >>> dt = datetime.now()
    >>> dt
    datetime.datetime(2019, 3, 2, 17, 2, 16, 122112)
    >>> new_dt = dt.replace(year=2008, month=3, day=8, hour=14, minute=30, second=45, microsecond=9000, tzinfo=gmt, fold=1)
    >>> new_dt
    datetime.datetime(2008, 3, 8, 14, 30, 45, 9000, fold=1, tzinfo=<__main__.GMT1 object at 0x108171668>)
    
  • datetime.astimezone(tz=None)

    返回带有新 tzinfo 属性 tzdatetime 对象实例,调整日期和时间数据使结果与 self 的UTC时间相同,但为用 tz 表示的本地时间。

    如果为 tz 参数提供非 None 值,则该值必须是 tzinfo 子类的实例,并且其 utcoffset()dst() 方法不得返回 Noneself 必须是 aware 的(self.tzinfo不能是None,以及self.utcoffset()不能返回None)。

    如果不带参数调用(或tz=None),则假定使用系统本地时区。转换后的 datetime 实例的tzinfo属性将设置为 timezone 的实例,其带有从操作系统获取的时区名称和偏移量。

    如果self.tzinfotz 参数值相同,则 self.astimezone(tz) 等于 self ,并且日期和时间数据不会调整。否则结果是使用时区 tz 表示的本地时间,表示与 tz 相同的UTC时间。astz = dt.astimezone(tz) 之后,astz -astz.utcoffset()通常具有与dt - dt.utcoffset()相同的日期和时间数据。类 tzinfo 的讨论解释了无法实现的在夏令时转换边界的情况(仅当 tz 同时建模标准时和夏令时的时候才出现问题)。

    如果你只想在不调整日期和时间数据的情况下将时区对象 tz 附加到 datetime 实例对象 dt,请使用 dt.replace(tzinfo=tz)。如果你只想从 awaredatetime 实例对象 dt 中删除时区对象而不转换日期和时间数据,请使用 dt.replace(tzinfo=None)

    请注意,可以在 tzinfo 子类中覆盖默认的 tzinfo.fromutc() 方法,以影响 astimezone() 返回的结果。忽略错误情况,astimezone() 的行为如下:

    def astimezone(self, tz):
        if self.tzinfo is tz:
            return self
        # Convert self to UTC, and attach the new time zone object.
        utc = (self - self.utcoffset()).replace(tzinfo=tz)
        # Convert from UTC to tz's local time.
        return tz.fromutc(utc)
    

    该方法使用示例:

    >>> class TestGMT(tzinfo):
    ...     def utcoffset(self, dt):
    ...         return timedelta(hours=1)
    ...     def dst(self, dt):
    ...         return timedelta(0)
    ...     def tzname(self, dt):
    ...         return 'Europe/Prague'
    ... 
    >>> gmt = TestGMT()
    >>> dt = datetime.now()
    >>> dt
    datetime.datetime(2019, 3, 4, 0, 43, 13, 363694)
    >>> dt1 = dt.astimezone()
    >>> dt1
    datetime.datetime(2019, 3, 4, 0, 43, 13, 363694, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), 'CST'))
    >>> dt1.tzinfo
    datetime.timezone(datetime.timedelta(seconds=28800), 'CST')
    >>> dt1.tzname()
    'CST'
    >>> dt2 = dt1.astimezone(tz=gmt)
    >>> dt2
    datetime.datetime(2019, 3, 3, 17, 43, 13, 363694, tzinfo=<__main__.TestGMT object at 0x10462e978>)
    >>> dt2.tzinfo
    <__main__.TestGMT object at 0x10462e978>
    >>> dt2.tzname()
    'Europe/Prague'
    
  • datetime.utcoffset()

    返回使用 datetime.timedelta 对象实例表示的 datetime 实例对象的时区偏移量。如果 datetime 对象实例的 tzinfo 属性为 None,则返回 None;否则返回 self.tzinfo.utcoffset(self) 的返回值;如果该方法的返回值不是 None 或者一个小于一天的 timedelta 对象,则会引发异常。

    >>> class GMT1(tzinfo):
    ...     def utcoffset(self, dt):
    ...         return timedelta(hours=1)
    ...     def dst(self, dt):
    ...         return timedelta(0)
    ...     def tzname(self, dt):
    ...         return 'Europe/Prague'
    ... 
    >>> gmt = GMT1()
    >>> dt = datetime.now(gmt)
    >>> dt
    datetime.datetime(2019, 3, 2, 18, 54, 39, 389884, tzinfo=<__main__.GMT1 object at 0x10751e390>)
    >>> dt.utcoffset()
    datetime.timedelta(seconds=3600)
    >>> dt1 = datetime.now()
    >>> dt1.utcoffset() is None
    True
    
  • datetime.dst()

    返回使用 datetime.timedelta 对象实例表示的 datetime 实例对象的时区偏移量。如果 datetime 对象实例的 tzinfo 属性为 None,则返回 None;否则返回 self.tzinfo.dst(self) 的返回值;如果该方法的返回值不是 None 或者一个小于一天的 timedelta 对象,则会引发异常。

    >>> dt = datetime.now(gmt)
    >>> dt.dst()
    datetime.timedelta(0)
    >>> dt1 = datetime.now()
    >>> dt1.dst() is None
    True
    
  • datetime.tzname()

    返回 datetime 实例对象的时区名称。如果 datetime 实例对象的 tzinfo 属性是 None,则返回 None,否则返回 self.tzinfo.tzname(self)。如果该方法的返回值不是 None 或者自一个字符串对象,则会引发异常。

    >>> dt = datetime.now(gmt)
    >>> dt.tzname()
    'Europe/Prague'
    >>> dt1 = datetime.now()
    >>> dt1.tzname() is None
    True
    
  • datetime.timetuple()

    返回一个 time.struct_time 对象实例,类似于 time.localtime() 的返回值。如果 d 是一个datetime对象的实例,那么,d.timetuple() 等价于以下表达式:

    time.struct_time((d.year, d.month, d.day, d.hour, d.minute, d.second, d.weekday(), yday, -1))

    其中,yday = d.toordinal() - date(d.year, 1, 1) + 1 。

    tm_isdst 的取值由 dst() 方法的返回值决定:如果 tzinfoNone 或者 dst() 的返回值是 Nonetm_isdst 的值将取-1;如果 dst() 方法的返回值是一个非零值,那么 tm_isdst 的值取1,否则,tm_isdst 的值取0。

    >>> dt = datetime.now(gmt)
    >>> dt.timetuple()
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=2, tm_hour=19, tm_min=0, tm_sec=35, tm_wday=5, tm_yday=61, tm_isdst=0)
    >>> dt1 = datetime.now()
    >>> dt1.timetuple()
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=3, tm_hour=1, tm_min=59, tm_sec=48, tm_wday=6, tm_yday=62, tm_isdst=-1)
    
  • datetime.utctimetuple()

    如果 datetime 实例 dnaive 的,那么这个方法的返回值与 timetuple() 方法的返回值相似,只是tm_isdst 被强制设置为0,而不管 d.dst()的返回值是什么。

    如果 daware 的,则通过减去 d.utcoffset(),将 d 规范化为UTC时间,然后返回这个规范化时间的struct_time,并且 tm_isdst 强制为0。请注意,如果 d.year 是MINYEAR或MAXYEAR,并且UTC调整超出了一年的边界,那么可能会引发 OverflowError 异常。

    >>> dt = datetime.now() # 当datetime实例是'naive'的时
    >>> dt.utctimetuple()
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=3, tm_hour=2, tm_min=40, tm_sec=7, tm_wday=6, tm_yday=62, tm_isdst=0)
    >>> dt1 = datetime.now(gmt)  # 当datetime实例是'aware'的时
    >>> dt1.utctimetuple()
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=2, tm_hour=18, tm_min=40, tm_sec=34, tm_wday=5, tm_yday=61, tm_isdst=0)
    >>> dt1.utctimetuple() == (dt1 - dt1.utcoffset()).timetuple()
    True
    
  • datetime.toordinal()

    返回日期的预期公历序号。与 self.date().toordinal() 的值相同。

    >>> dt = datetime.now()
    >>> dt.toordinal()
    737121
    >>> dt.date().toordinal()
    737121
    
  • datetime.timestamp()

    返回与 datetime 实例对应的POSIX时间戳。返回值是一个类似于time.time()返回值的浮点数。

    假定本地时间使用 navidatetime 实例表示,并且该方法依赖于平台的C语言的 mktime()函数执行转换。由于在许多平台上 datetime 支持的值比 mktime() 的范围更广,因此这种方法可能会在过去或未来很长一段时间内产生OverflowError 异常。

    对于 awaredatetime 实例,返回值由下面的表达式计算:

    (dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds()

    >>> import time as _time
    >>> dt = datetime.now()
    >>> dt.timestamp()
    1551552673.72456
    >>> _time.time()
    1551552686.284929
    
  • datetime.weekday()

    返回当前日期在一周内的序号,即星期几,其中周一表示为0,周日表示为6。

    >>> dt = datetime.now()
    >>> dt.weekday()
    6
    >>> dt.date().weekday()
    6
    
  • datetime.isoweekday()

    返回当前日期在一周内的序号,即星期几,其中周一表示为1,周日表示为7。

    >>> dt = datetime.now()
    >>> dt.isoweekday()
    7
    >>> dt.date().isoweekday()
    7
    
  • datetime.isocalendar()

    返回一个包含给定日期时间对象的ISO year、ISO week number和ISO weekday的三元组。

    >>> dt = datetime.now()
    >>> dt.isocalendar()
    (2019, 9, 7)
    >>> dt.date().isocalendar()
    (2019, 9, 7)
    
  • datetime.isoformat(sep=‘T’, timespec=‘auto’)

    返回一个使用 ISO 8601格式表示 datetime 实例的日期和时间的字符串。

    如果给定实例的 microsecond 属性值不是0,那么具体格式为 YYYY-MM-DDTHH:MM:SS.ffffff

    如果给定实例的 microsecond 属性值是0,那么具体格式为 YYYY-MM-DDTHH:MM:SS

    如果给定实例的 utcoffset 方法返回值不是 None,则会附加一个字符串用来给出UTC偏移量,此时,字符串格式如下:

    YYYY-MM-DDTHH:MM:SS.ffffff+HH:MM[:SS[.ffffff]]

    如果给定实例的 microsecond 属性值是0,字符串的格式如下:

    YYYY-MM-DDTHH:MM:SS+HH:MM[:SS[.ffffff]]

    可选参数 sep (默认值为’T’) 是一个单字符分隔符,用来分隔结果中的日期和时间部分,例如:

    >>> from datetime import tzinfo, timedelta, datetime
    >>> class TZ(tzinfo):
    ...     def utcoffset(self, dt): return timedelta(minutes=-399)
    ... 
    >>> datetime(2019, 3, 2, tzinfo=TZ()).isoformat(' ')
    '2019-03-02 00:00:00-06:39'
    

    可选参数 timespec 用来指定可选的时间组件数(默认值为’auto’)。该参数的取值可以是下列中的一个:

    • auto :如果 microsecond 为0,则与 second 相同,否则,与 microseconds 相同。
    • hours:包含 hour,格式为 HH
    • minutes:包含 hourminute,格式为 HH:MM
    • seconds:包含 hourminutesecond,格式为 HH:MM:SS
    • milliseconds:包含完整的时间格式,但是会忽略微秒,并表示为这样的格式 HH:MM:SS.sss
    • microseconds:包含完整的时间格式 HH:MM:SS.ffffff

    如果指定的 timespec 参数的值不在上述列举的范围内,则会引发 ValueError 异常。

    >>> dt = datetime.now()
    >>> dt.isoformat(timespec='minutes')
    '2019-03-03T03:56'
    >>> dt.isoformat(timespec='seconds')
    '2019-03-03T03:56:04'
    >>> dt.isoformat(timespec='milliseconds')
    '2019-03-03T03:56:04.772'
    >>> dt.isoformat(timespec='microseconds')
    '2019-03-03T03:56:04.772110'
    
  • datetime.__str__()

    对于 datetime 实例 dstr(d) 等同于 d.isoformat(' ')

    >>> dt = datetime.now()
    >>> str(dt)
    '2019-03-03 04:00:08.416914'
    >>> dt.isoformat(' ')
    '2019-03-03 04:00:08.416914'
    
  • datetimte.ctime()

    返回表示给定 datetime 实例日期和时间的字符串。例如 date(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002' 。对于 datetime 的实例对象 d,在本地C语言的ctime() (调用time.ctime()而不是datetime.ctime())函数符合C标准的平台上,d.ctime()等价于如下表达式的值:

    time.ctime(time.mktime(d.timetuple()))

    >>> dt = datetime.now()
    >>> dt.ctime()
    'Sun Mar  3 04:30:52 2019'
    
  • datetimte.__format__()

    datetime.strftime() 方法功能相同。同时,这也使得在使用 str.format() 时,可以使用带格式的字符串文本为 datetime 对象实例指定格式字符串。完整的格式化指令,请参考 strftime() and strptime() Behavior 。

    >>> dt = datetime.now()
    >>> 'The {1} is {0:%d}, the {2} is {0:%B}, the {3} is {0:%I:%M%p}.'.format(dt, "day", "month", "time")
    'The day is 03, the month is March, the time is 04:43AM.'
    
  • datetime.strftime()

    返回一个表示 datetime 实例的日期和时间的字符串,其格式由显式的格式化字符串指定。完整的格式化指令,请参考 strftime() and strptime() Behavior 。

    >>> dt = datetime.now()
    >>> dt.strftime('%A, %d. %B %Y %I:%M%p')
    'Sunday, 03. March 2019 04:43AM'
    >>> dt.strftime('%Y-%m-%d')
    '2019-03-03'
    

2. time模块

2.1 time模块简介

尽管这个模块总是可用的,但是不是所有的这个模块内的方法(函数)在所有平台上都是可用的。这个模块内定义的大多数方法都会调用平台的C库的同名方法。由于这些函数的语义在不同的平台之间是不同的,因此,在使用时应该参考对应平台上的使用文档。

2.2 time模块详解

2.2.1 术语和约定

如下是对一些要使用到的术语和约定的解释:

  • 纪元(epoch)

    表示时间开始的点,与平台无关。对于Unix系统来说,纪元是UTC时间 “1970-01-01 00:00:00”。对于给定平台上的纪元,可以使用 gmtime(0) 方法获取。

    >>> import time
    >>> time.gmtime(0)
    time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)
    
  • 自纪元以来的秒(seconds since the epoch)

    该术语指自纪元以来经过的秒的总数,通常不包括闰秒。在所有兼容posix的平台上,闰秒都不包括在这个总数中。

  • 此模块中的函数可能无法处理纪元之前或很远的将来的日期和时间。未来的分界点由C库确定,对于32位系统,通常是在2038年。

  • 2000年问题

    Python依赖于平台的C库,该库通常没有2000年问题,因为所有日期和时间都在内部表示为自纪元之后的总的秒数。函数 strptime() 可以接受格式为 %y 的格式化代码并正确解析两位数年份。当解析两位数年份时,它们将根据POSIX和ISO C标准进行如下转换:

    值69—99映射到1969—1999,值0—68映射到2000—2068。

  • UTC是 协调世界时(Coordinated Universal Time)(以前称为 格林威治标准时间(Greenwich Mean Time),或 GMT)。首字母缩略词 UTC 不是一个错误,而是英语和法语的一种折中方案。

  • DST是 夏令时(Daylight Saving Time),是指在一年中的某一段时间内时区(通常)调整一小时。DST规则由当地法律决定,并且每年都可能发生变化。C库有一个包含本地规则的表(通常是从系统文件中读取以获得以便具有灵活性)。

  • 各种实时(real-time)函数的精度可能低于表示其值或参数的单位所建议的精度。例如,在大多数Unix系统上,时钟每秒只滴答(ticks)50或100次。

  • 另一方面,times()sleep() 能够获得比Unix上同名方法更好的精度:时间用浮点数表示,times() 方法返回可用的最准确的时间(在可用的情况下使用Unix的gettimeofday()方法),sleep() 方法接受非零小数的时间作为参数(在可用的情况下使用Unix的select()方法实现)。

  • gmtime() 方法、localtime() 方法和 strptime() 方法返回的时间,以及 asctime() 方法、mktime() 方法和 strftime() 方法接受的时间,是9个整数组成的序列。 asctime() 方法、mktime() 方法和 strftime() 方法的返回值还为每个独立的项提供了属性名。

    >>> import time
    >>> lt = time.localtime()
    >>> lt
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=5, tm_hour=15, tm_min=5, tm_sec=49, tm_wday=1, tm_yday=64, tm_isdst=0)
    >>> lt.tm_year
    2019
    >>> lt.tm_yday
    64
    
  • 使用如下的几个方法进行时间的表示形式之间的转换:

2.2.2 time模块中的函数

time模块中包含如下一些常用方法:

  • time.asctime([t])

    将表示 gmtime()localtime()返回值的 tuple 对象实例或 struct_time 对象转换为以下形式的字符串:

    “Sun Jun 20 23:21:05 1993”

    如果不提供参数 t,则使用 localtime() 返回的当前时间。该方法不使用区域信息。

    >>> lt = time.localtime()
    >>> time.asctime(lt)
    'Tue Mar  5 16:11:45 2019'
    >>> t = (2010, 2, 14, 10, 10, 30, 2, 66, 1)
    >>> time.asctime(t)
    'Wed Feb 14 10:10:30 2010'
    >>> st = time.struct_time(t)
    >>> st
    time.struct_time(tm_year=2010, tm_mon=2, tm_mday=14, tm_hour=10, tm_min=10, tm_sec=30, tm_wday=2, tm_yday=66, tm_isdst=1)
    >>> time.asctime(st)
    'Wed Feb 14 10:10:30 2010'
    
  • time.clock()

    在Unix上,返回表示当前处理器时间的以秒为单位的浮点数。“处理器时间”的精度和定义,实际上取决于同名C函数。

    在Windows上,该函数基于Win32函数 QueryPerformanceCounter() 返回以浮点数的形式表示的自第一次调用该函数以来的挂钟秒数。误差通常小于1微秒。

    注意:该函数从3.3版本开始已被弃用,如果调用该函数,虽然可以得到返回值,但同时也将引发 DeprecationWarning 异常,并且从3.8版本以后,这个函数将被移除。建议使用 time.perf_countertime.process_time 进行替换。

  • time.pthread_getcpuclockid(thread_id)

    为指定的 thread_id 返回特定于线程的cpu时间时钟的 clk_id

    使用 thread .get_ident() 或线程的 ident 属性为线程对象获取适合 thread_id 的值。

    警告:传递一个无效或过期thread_id可能导致未定义行为,如段错误(segmentation fault)。

    可用性:仅Unix平台可用

  • time.clock_getres(clk_id)

    返回指定的时钟 clk_id 的resolution(精度)。有关 clk_id 的可接受值列表,请参阅时钟ID常量。

    可用性:仅Unix平台可用

  • time.clock_gettime(clk_id) -> float

    返回指定时钟 clk_id 的时间。有关 clk_id 的可接受值列表,请参阅时钟ID常量。

    可用性:仅Unix平台可用

  • time.clock_gettime_ns(clk_id) -> int

    类似 clock_gettime(),但返回的时间为纳秒。

    可用性:仅Unix平台可用

  • time.clock_settime(clk_id, time: float)

    设置指定时钟 clk_id 的时间。目前,CLOCK_REALTIMEclk_id 唯一可接受的值。

    可用性:仅Unix平台可用

  • time.clock_settime_ns(clk_id, time: int)

    类似 clock_settime(),但使用纳秒设置时间。

    可用性:仅Unix平台可用

  • time.ctime([secs])

    将纪元后以秒为单位表示的时间转换为表示本地时间的字符串。如果未提供 secs 参数或该参数值为 None,则使用 time() 方法返回的当前时间。ctime(secs) 相当于 asctime(localtime(secs))ctime() 不使用区域设置信息。

    >>> time.ctime()
    'Tue Mar  5 17:01:49 2019'
    >>> time.ctime(5201314)
    'Mon Mar  2 12:48:34 1970'
    >>> time.ctime(5201314) == time.asctime(time.localtime(5201314))
    True
    
  • time.get_clock_info(name)

    以命名空间对象的形式获取关于指定时钟的信息。支持的时钟名称和读取其值的对应函数如下:

    • clock“:time.clock()
    • monotonic:time.monotonic()
    • perf_counter:time.perf_counter()
    • process_time:time.process_time()
    • thread_time:time.thread_time()
    • time:time.time()

    该方法的返回值有如下属性:

    • adjustable:如果时钟能够被自动更改(例如,被NTP守护进程)或被系统管理员手动更改,那么这个值将为 True,否则则为 False
    • implementation:获取时钟值的底层C函数。可能的值,请参阅 时钟ID常量
    • monotonic:如果时钟不能倒退,则返回True,否则返回 False
    • resolution:用浮点数表示的以秒为单位的时钟误差(resolution)。
    >>> r = time.get_clock_info('time')
    >>> r
    namespace(adjustable=True, implementation='clock_gettime(CLOCK_REALTIME)', monotonic=False, resolution=1.0000000000000002e-06)
    >>> r.__dict__
    {'implementation': 'clock_gettime(CLOCK_REALTIME)', 'monotonic': False, 'adjustable': True, 'resolution': 1.0000000000000002e-06}
    
  • time.gmtime([secs])

    将以秒表示的纪元后时间转换为以 struct_time 实例表示的UTC时间,其中 dst 标志始终为零。如果没有提供 secs 参数或参数值为 None,则使用 time() 方法返回的当前时间。小数秒将被忽略。详情请参见struct_time 对象的描述。有关此函数的逆函数,请参见 calendar.timegm() 函数。

    >>> time.gmtime(5201314)
    time.struct_time(tm_year=1970, tm_mon=3, tm_mday=2, tm_hour=4, tm_min=48, tm_sec=34, tm_wday=0, tm_yday=61, tm_isdst=0)
    >>> time.gmtime()
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=5, tm_hour=9, tm_min=43, tm_sec=52, tm_wday=1, tm_yday=64, tm_isdst=0)
    >>> time.gmtime(None)
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=5, tm_hour=9, tm_min=43, tm_sec=59, tm_wday=1, tm_yday=64, tm_isdst=0)
    >>> time.gmtime(4.6)
    time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=4, tm_wday=3, tm_yday=1, tm_isdst=0)
    
  • time.localtime([secs])

    类似于 gmtime(),但返回值将被转换为本地时间。如果没有提供 secs 参数或参数值为 None,则使用time() 方法返回的当前时间。当 DST 适用于给定的时间时,dst 标志将被设置为1。

    >>> time.localtime()
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=5, tm_hour=17, tm_min=45, tm_sec=11, tm_wday=1, tm_yday=64, tm_isdst=0)
    >>> time.localtime(None)
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=5, tm_hour=17, tm_min=45, tm_sec=13, tm_wday=1, tm_yday=64, tm_isdst=0)
    >>> time.gmtime(5201314) # 转化为UTC
    time.struct_time(tm_year=1970, tm_mon=3, tm_mday=2, tm_hour=4, tm_min=48, tm_sec=34, tm_wday=0, tm_yday=61, tm_isdst=0)
    >>> time.localtime(5201314) # 转换为本地时间,可以看到结果中的小时数已经加了8小时,即东八区时间
    time.struct_time(tm_year=1970, tm_mon=3, tm_mday=2, tm_hour=12, tm_min=48, tm_sec=34, tm_wday=0, tm_yday=61, tm_isdst=0)
    
  • time.mktime(t)

    这是 localtime() 函数的逆函数。该方法的参数 t 必须是 struct_time 实例或一个9元组(因为需要 dst 标志;如果dst 是未知的,则使用-1作为 dst 标志),返回值为表示本地时间而不是UTC的以秒为单位的浮点数。之所以返回值类行为浮点型主要是为了与 time()兼容。如果输入值不能表示为有效时间,则会引发 OverflowError 异常或 ValueError 异常(这取决于Python或底层C库是否捕捉到无效值)。该方法能够生成的最早的时间依赖于平台。

    >>> time.mktime((1970, 3, 2, 12, 48, 34, 0, 61, 0))
    5201314.0
    st = time.struct_time((1970, 3, 2, 12, 48, 34, 0, 61, 0))
    >>> st
    time.struct_time(tm_year=1970, tm_mon=3, tm_mday=2, tm_hour=12, tm_min=48, tm_sec=34, tm_wday=0, tm_yday=61, tm_isdst=0)
    >>> time.mktime(st)
    5201314.0
    >>> time.mktime(454)
    Traceback (most recent call last):
      File "", line 1, in <module>
    TypeError: Tuple or struct_time argument required
    
  • time.monotonic() -> float

    返回一个单调时钟的值(以小数秒为单位)。单调时钟不受系统时钟更新的影响。由于返回值的参考点没有定义,因此只有连续调用的结果之间的差异才是有效的。

  • time.monotonic_ns() -> int

    monotonic() 函数类似,但返回值的单位纳秒,类型为整形。

  • time.perf_counter() -> float

    返回性能计数器的值(以小数秒为单位),例如,一个以最高的可用分辨率测量短地持续时间的时钟。它确实包括系统范围内睡眠期间经过的时间。由于返回值的参考点没有定义,因此只有连续调用的结果之间的差异是有效的。

  • time.perf_counter_ns() -> int

    perf_counter() 函数类似,但是返回值是以纳秒为单位,且类型为整形。

  • time.process_time() -> float

    返回当前进程的系统和用户CPU时间之和的值(以分数秒为单位)。它不包括在睡眠期间经过的时间,而是在进程范围内定义的。由于返回值的参考点未定义,因此只有连续调用结果之间的差异有效。

  • time.process_time_ns() -> int

    process_time() 函数类似,但范围值是以纳秒为单位,且类型为整形。

  • time.sleep(secs)

    在给定的秒数内暂停调用线程的执行。参数可以是一个浮点数,用以表示更精确的睡眠时间。实际的暂停时间可能小于请求的时间,因为任何捕获到的信号都会在执行该信号的捕获例程之后终止 sleep() 。此外,由于系统中其他活动的调度,实际的暂停时间可能比请求的暂停时间长任意地数量。

  • time.strftime(format[, t])

    将由 gmtime() 函数或 localtime() 函数返回的表示时间的元组或 struct_time 对象实例转换为字符串,其中,字符串的格式由字符串类型的参数format 指定。如果没有给参数 t 提供值,则使用 localtime() 函数返回的当前时间。如果 t 中的任何字段超出了允许的范围,则会引发 ValueError

    0 是时间元组中任何位置上的合法参数。如果 0 通常是非法的,那么它会被强制为一个正确的值。

    以下指令可以嵌入到 format 参数中。它们没有可选的字段宽度和精度规范,而是由 strftime() 结果中指定的字符替换:

    指令 含义 注释
    %a 当前区域设置下工作日名称的缩写
    %A 当前区域设置下工作日名称的全称
    %b 当前区域设置下月份名称的缩写
    %B 当前区域设置下月份名称的全称
    %c 当前区域设置下日期和时间的适当表示
    %d 使用十进制数字表示的当前日期中的天在当前月份的序数,范围为[01, 31]
    %H 使用十进制数字表示的当前时间中小时的序数(24小时制),范围为[00, 23]
    %I 使用十进制数字表示的当前时间中小时的序数(12小时制),范围为[01, 12]
    %j 使用十进制数字表示的当前日期中的天在当前年的序数,范围为[001, 366]
    %m 使用十进制数字表示的当前日期中的月份的序数,范围为[01, 12]
    %M 使用十进制数字表示的当前时间中的分钟在一小时内的序数,范围为[00, 59]
    %p 当前区域设置下的上午(AM)或下午(PM) (1)
    %S 使用十进制数字表示的当前时间中的秒在一分钟内的序数,范围为[00, 61] (2)
    %U 使用十进制数字表示当前日期处于当年中的第几个星期,范围为[00, 53]。周日被看作每周的第一天。新年第一个星期日之前的所有日子都被认为是在第0周。 (3)
    %w 使用十进制数字表示当前日期中的天在当前周的序号,范围为[0, 6]。其中,0表示周日,6表示周六
    %W 使用十进制数字表示当前日期处于当年中的第几个星期,范围为[00, 53]。周一被看作每周的第一天。新年第一个星期日之前的所有日子都被认为是在第0周。 (3)
    %x 当前区域设置下日期的适当表示
    %X 当前区域设置下时间的适当表示
    %y 使用两位十进制数字表示当前日期中的年(不包括世纪),范围为[00, 99]
    %Y 使用十进制数字表示当前日期中的年(包含世纪)
    %z 表示与UTC/GMT的正或负时差的时区偏移量,其形式为 +HHMM-HHMM。其中 H 表示十进制小时数,M 表示十进制分钟数
    %Z 时区名称(如果没有时区信息则为空)
    %% 表示一个 % 符号

    注释

    (1). 当与 strptime() 函数一起使用时,如果 %I指令用于解析小时,则%p指令只影响输出中的小时字段。

    (2). 范围实际上是0到61。60在表示闰秒的时间戳中有效,而由于历史原因,需要支持61。

    (3). 当与 strptime() 函数一起使用时,如果指定了星期几和年份,则 %U%W 只用于计算。

    下面是一个示例,其中日期格式与RFC 2822 Internet电子邮件标准中指定的格式兼容:

    >>> from time import gmtime, strftime
    >>> strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
    'Thu, 28 Jun 2001 14:17:15 +0000'
    

    在某些平台上,该方法可能支持其他指令,但是这里仅列出被ANSI C标准化了指令的含义。

    在某些平台上,可选的字段宽度和精度可以紧挨着 % 给出。但是这些特性是不可移植的。除 %j 的字段宽度为3外,其他的字段宽度通常为2。

  • time.strptime(string[, format])

    将表示时间的字符串根据其格式进行解析。返回值是类似于 gmtime()localtime() 方法返回值的struct_time 对象。

    format 参数使用的指令与 strftime() 函数使用的指令相同,默认值的格式与ctime() 函数返回的格式相匹配,其值为 %a %b %d %H:%M:%S %Y,。如果字符串不能按照 format 参数指定的格式进行解析,或者解析后有多余的数据,则会引发 ValueError 异常。当无法推断出更精确的值时,将使用(1900、1、1、0、0、0、0、0、1、-1)中的值填充对应位置缺失的数据。stringformat 参数都必须是字符串。

    >>> import time
    >>> time.strptime("30 Nov 00", "%d %b %y")   # doctest: +NORMALIZE_WHITESPACE
    time.struct_time(tm_year=2000, tm_mon=11, tm_mday=30, tm_hour=0, tm_min=0,
                     tm_sec=0, tm_wday=3, tm_yday=335, tm_isdst=-1)
    

    %Z 指令的支持是基于time.tzname 中包含的值以及 time.daylight 是否为真。正因为如此,%Z 指令是特定于平台的,除了识别总是已知的UTC和GMT(并且被认为是非夏令时时区)。

    该函数仅支持文档中列出的格式化指令。因为 strftime()是在每个平台上实现的,所以strftime()有时可以支持比列出的指令更多的指令。但是 strptime() 独立于任何平台,因此并不一定支持所有被strftime() 函数支持但并未被文档化的格式化指令。

  • time.time() -> float

    返回用浮点数表示的以秒为单位的表示自纪元以来的时间。纪元的具体日期和闰秒的处理取决于平台。在Windows和大多数Unix系统上,纪元是UTC时间 “1970-01-01 00:00:00”,并且不包括闰秒。这通常称为Unix时间。要了解给定平台上的纪元是多少,请通过 gmtime(0) 查看。

    请注意,尽管时间总是作为浮点数返回,但并不是所有的系统提供的时间精度都高于1秒。虽然该函数通常返回非递减值,但如果系统时钟在两次调用之间被设置回调,那么它可能返回比前一次调用更低的值。

    可以将该方法的返回值传递给 gmtime() 函数,用以转换为常见格式(即年、月、日、小时等)的UTC时间,也可以传递给 localtime() 函数用以转换为本地时间。在这两种情况下,都会返回一个可以使用日历日期属性进行访问的 struct_time 对象。

    >>> time.time()
    1551880865.881496
    >>> time.gmtime(time.time())
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=6, tm_hour=14, tm_min=1, tm_sec=17, tm_wday=2, tm_yday=65, tm_isdst=0)
    >>> time.localtime(time.time())
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=6, tm_hour=22, tm_min=1, tm_sec=27, tm_wday=2, tm_yday=65, tm_isdst=0)
    
  • time.time_ns() -> int

    time(0 函数类似,但是返回值为整形,且单位为纳秒。

  • time.thread_time() -> float

    返回当前线程的系统和用户CPU时间之和的值(以小数秒为单位)。该方法的返回值不包括睡眠时间。根据定义,这个时间是特定于线程的。由于返回值的参考点是未定义的,因此只有同一线程中连续调用的结果之间的差异才是有效的。

  • time.thread_time_ns() -> int

    thread_time() 函数类似,但是返回值的单位是纳秒,并且是整形。

  • time.tzset()

    根据环境变量 TZ 的值重置库例程使用的时间转换规则。这个方法还会设置变量 tzname (根据环境变量 TZ)、timezone (UTC以西非夏令时时区偏移量),altzone (UTC以西夏令时时区偏移量) 和 daylight (如果这个时区没有夏令时规则,则设置为0,如果在过去、现在或者将来的某些时间,会应用到夏令时规则,则设置为非零值)的值。

    可用性:仅Unix平台可用

    注意:尽管在许多情况下,更改 TZ 环境变量但是不调用 tzset() 函数可能会影响 localtime() 等函数的输出,但是不应该依赖于这种行为。

    TZ 环境变量的标准格式为(为清晰起见添加了空格,实际的 TZ 环境变量不能包含空格):

    std offset [dst [offset [,start[/time], end[/time]]]]

    其中,各个组件的含义如下:

    • stddst

      使用三个或三个以上的字母数字表示的时区的缩写,这些值会传递给 time.tzname 属性。

    • offset

      这个值的格式为:± hh[:mm[:ss]]。如果前面是 -,则表示时区在本初子午线以东,如果前面是 +,则表示时区在本初子午线以西。如果 dst 后面没有跟偏移量,则假定夏季时间比标准时间早一个小时。

    • start[/time], end[/time]

      指示切换到 DST 和从 DST 返回的日期。开始日期和结束日期的格式如下:

      • Jn

        儒略日 n (1 <= n <= 365)。由于闰日不包括在内,因此,每年2月28日是第59天,3月1日是第60天。

      • n

        从零开始的儒略日n (0 <= n <= 365)。闰日是计算在内的,因此可以表示2月29日。

      • Mm.n.d

        一年中的第 m 个月的第 n 个星期的第 d 天 (1 <= n <= 5,1<= m <=12,当 n 等于5时,表示第 m月的最后 d 天,这种情况可能出现在第四个星期或者第五个星期)。出现第 d 天的第一个周视为第一周。第0天表示星期日。

      • time

        offset 的格式相同,但是不允许使用前导符号( +-)。如果这个参数未赋值,则取默认值 02:00:00

    >>> os.environ['TZ'] = 'EST+05EDT,M4.1.0,M10.5.0'
    >>> time.tzset()
    >>> time.strftime('%X %x %Z')
    >>> '02:07:36 05/08/03 EDT'
    >>> os.environ['TZ'] = 'AEST-10AEDT-11,M10.5.0,M3.5.0'
    >>> time.tzset()
    >>> time.strftime('%X %x %Z')
    >>> '16:08:12 05/08/03 AEST'
    

在许多Unix系统(包括*BSD、Linux、Solaris和Darwin)上,使用系统的zoneinfo (tzfile(5))数据库指定时区规则更为方便。具体的操作方法为,将 TZ 环境变量设置为所需时区数据文件相对于系统的 zoneinfo时区数据库的根目录(通常位于/usr/share/zoneinfo)的相对路径。

例如,“US/Eastern”、“Australia/Melbourne”、“Egypt” 或 “Europe/Amsterdam”。

>>> os.environ['TZ'] = 'US/Eastern' # 先设置环境变量TZ的值
>>> time.tzset() # 再调用tzset方法重置时间转换规则
>>> time.tzname
('EST', 'EDT')
>>> os.environ['TZ'] = 'Egypt'
>>> time.tzset()
>>> time.tzname
('EET', 'EEST')

2.2.3 time模块中的常量

该模块包含如下几个常用的常量:

  • time.altzone

    定义了本地DST时区的偏移量,以UTC以西秒为单位。如果当地的DST时区位于UTC以东(如西欧,包括英国),则为负。只有在 daylight 不为零时才使用这个。请参阅下面的注意事项。

  • time.daylight

    如果定义了DST时区,则为非零值。请参阅下面的注意事项。

  • time.timezone

    本地(非夏令时)时区的偏移量,以UTC以西的秒为单位(西欧大部分地区为负,美国为正,英国为零)。请参阅下面的注意事项。

  • time.tzname

    由两个字符串组成的元组:第一个是本地非夏令时时区的名称,第二个是本地DST时区的名称。如果没有定义DST时区,则不应使用第二个字符串。请参阅下面的注意事项。

注意:

对于上述时区常量(altzonedaylighttimezonetzname),该值由模块加载时有效的时区规则或最后一次调用tzset()的时间决定,并且对于过去的时间,这个值可能是不正确的。建议使用localtime() 函数的返回值的的tm_zone属性和 tm_gmtoff 属性来获取时区信息。

>>> time.timezone
-28800
>>> time.tzname
('CST', 'CST')
>>> time.altzone
-28800
>>> time.daylight
0
>>> time.localtime().tm_zone
'CST'
>>> time.localtime().tm_gmtoff
28800

你可能感兴趣的:(Python学习)