Skip to main content

8.1. datetime —基本日期和时间类型

源代码: Lib/datetime.py


datetime 模块以简单和复杂的方式提供操作日期和时间的类。虽然支持日期和时间算法,但实现的重点是对输出格式化和操作的高效属性提取。有关相关功能,另请参阅 timecalendar 模块。

有两种日期和时间对象:“naive”和“aware”。

感知对象具有足够的可应用的算法和政治时间调整的知识,例如时区和夏令时信息,以相对于其他感知对象来定位自身。感知对象用于表示不能解释 [1] 的特定时刻。

初始对象不包含足够的信息以相对于其他日期/时间对象明确地定位它自己。一个简单的对象是否表示协调世界时(UTC),本地时间或某些其他时区的时间完全取决于程序,就像某个特定数字代表米,英里或大众的程序一样。天真的对象很容易理解和使用,以忽视现实的一些方面为代价。

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

datetime 模块导出以下常量:

datetime.MINYEAR

datedatetime 对象中允许的最小年份数。 MINYEAR1

datetime.MAXYEAR

datedatetime 对象中允许的最大年份数。 MAXYEAR9999

参见

模块 calendar

一般日历相关功能。

模块 time

时间访问和转化。

8.1.1. 可用类型

class datetime.date

一个理想化的幼稚日期,假设当前的公历日历总是,并将永远是有效的。属性:yearmonthday

class datetime.time

一个理想的时间,独立于任何特定的日子,假设每天都有24*60*60秒(这里没有“闰秒”的概念)。属性:hourminutesecondmicrosecondtzinfo

class datetime.datetime

日期和时间的组合。属性:yearmonthdayhourminutesecondmicrosecondtzinfo

class datetime.timedelta

表示两个 datetimedatetime 实例与微秒分辨率之间的差异的持续时间。

class datetime.tzinfo

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

class datetime.timezone

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

3.2 新版功能.

这些类型的对象是不可变的。

date 类型的对象总是天真的。

timedatetime 类型的对象可以是幼稚的或意识的。 datetime 对象 d 知道 d.tzinfo 是否不是 None,并且 d.tzinfo.utcoffset(d) 不返回 None。如果 d.tzinfoNone,或者如果 d.tzinfo 不是 None,但是 d.tzinfo.utcoffset(d) 返回 None,则 d 是天真的。 time 对象 t 知道 t.tzinfo 是否不是 None,并且 t.tzinfo.utcoffset(None) 不返回 None。否则,t 是天真的。

天真和意识之间的区别不适用于 timedelta 对象。

子类关系:

object
    timedelta
    tzinfo
        timezone
    time
    date
        datetime

8.1.2. timedelta 对象

timedelta 对象表示持续时间,两个日期或时间之间的差异。

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

所有参数都是可选的,默认为 0。参数可以是整数或浮点数,可以是正数或负数。

只有 dayssecondsmicroseconds 在内部存储。参数将转换为这些单位:

  • A毫秒转换为1000微秒。

  • 分钟转换为60秒。

  • 一小时转换为3600秒。

  • 一周被转换为7天。

然后将天,秒和微秒标准化,使得表示是唯一的

  • 0 <= microseconds < 1000000

  • 0 <= seconds < 3600*24 (一天中的秒数)

  • -999999999 <= days <= 999999999

如果任何参数是浮点数并且有微秒分数,则将所有参数剩余的小数微秒进行组合,并使用round-half-to-even tiebreaker将它们的和舍入到最接近的微秒。如果没有参数是浮点数,转换和规范化过程是准确的(没有信息丢失)。

如果天的归一化值在所指示的范围之外,则提高 OverflowError

注意,负值的归一化可能首先是令人惊讶的。例如,

>>> from datetime import timedelta
>>> d = timedelta(microseconds=-1)
>>> (d.days, d.seconds, d.microseconds)
(-1, 86399, 999999)

类属性包括:

timedelta.min

最负的 timedelta 对象,timedelta(-999999999)

timedelta.max

最积极的 timedelta 对象,timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999)

timedelta.resolution

非等量 timedelta 对象(timedelta(microseconds=1))之间的最小可能差异。

注意,由于归一化,timedelta.max> -timedelta.min-timedelta.max 不能表示为 timedelta 对象。

实例属性(只读):

属性

days

介于-999999999和999999999之间

seconds

介于0和86399之间(包括0和86399)

microseconds

介于0和999999之间(含)

支持的操作:

操作

结果

t1 = t2 + t3

t2t3 的总和。之后 t1-t2 == t3t1-t3 == t2 为真。 (1)

t1 = t2 - t3

t2t3 的区别。之后 t1 == t2 - t3t2 == t1 + t3 是真的。 (1)

t1 = t2 * i or t1 = i * t2

Delta乘以一个整数。之后 t1 // i == t2 为true,提供 i != 0

 

一般来说,t1 * i == t1 * (i-1) + t1 为真。 (1)

t1 = t2 * f or t1 = f * t2

Delta乘以浮点数。结果舍入到使用round-half-to-even的timedelta.resolution的最近的倍数。

f = t2 / t3

t2 部门(3)由 t3。返回 float 对象。

t1 = t2 / f or t1 = t2 / i

Delta除以浮点数或整数。结果舍入到使用round-half-to-even的timedelta.resolution的最近的倍数。

t1 = t2 // it1 = t2 // t3

计算下限,剩余部分(如果有的话)被丢弃。在第二种情况下,返回一个整数。 (3)

t1 = t2 % t3

余数被计算为 timedelta 对象。 (3)

q, r = divmod(t1, t2)

计算商和余数:q = t1 // t2 (3)和 r = t1 % t2。 q是整数,r是 timedelta 对象。

+t1

返回具有相同值的 timedelta 对象。 (2)

-t1

相当于 timedelta (-t1.days,-t1.seconds,-t1.microseconds)和 t1 * -1。 (1)(4)

abs(t)

t.days >= 0 时相当于+ t,当 t.days < 0 时相当于-t。 (2)

str(t)

返回 [D day[s], ][H]H:MM:SS[.UUUUUU] 形式的字符串,其中对于否定 t,D为负数。 (5)

repr(t)

返回 datetime.timedelta(D[, S[, U]]) 形式的字符串,其中对于否定 t,D为负数。 (5)

笔记:

  1. 这是确切的,但可能会溢出。

  2. 这是确切的,不能溢出。

  3. 除以0提高 ZeroDivisionError

  4. -timedelta.max 不能表示为 timedelta 对象。

  5. timedelta 对象的字符串表示与其内部表示法类似地进行标准化。这导致负时间的一些不寻常的结果。例如:

    >>> timedelta(hours=-5)
    datetime.timedelta(-1, 68400)
    >>> print(_)
    -1 day, 19:00:00
    

除了上面列出的操作之外,timedelta 对象还支持使用 datedatetime 对象进行某些加法和减法(见下文)。

在 3.2 版更改: 现在支持由另一 timedelta 对象进行的 timedelta 对象的分区和真分区,以及余数操作和 divmod() 函数。现在支持通过 float 对象进行 timedelta 对象的真正除法和乘法。

timedelta 对象的比较由表示较小持续时间的 timedelta 对象支持,该持续时间被认为是较小的timedelta。为了阻止混合类型比较从对象地址回退到默认比较,当 timedelta 对象与不同类型的对象比较时,TypeError 被提升,除非比较是 ==!=。后一种情况分别返回 FalseTrue

timedelta 对象是 hashable (可用作字典键),支持高效的pickling,在布尔上下文中,当且仅当 timedelta 对象不等于 timedelta(0) 时,timedelta 对象才被认为是true。

实例方法:

timedelta.total_seconds()

返回持续时间中包含的总秒数。相当于 td / timedelta(seconds=1)

请注意,对于非常大的时间间隔(在大多数平台上大于270年),此方法将失去微秒精度。

3.2 新版功能.

用法示例:

>>> from datetime import timedelta
>>> year = timedelta(days=365)
>>> another_year = timedelta(weeks=40, days=84, hours=23,
...                          minutes=50, seconds=600)  # adds up to 365 days
>>> year.total_seconds()
31536000.0
>>> year == another_year
True
>>> ten_years = 10 * year
>>> ten_years, ten_years.days // 365
(datetime.timedelta(3650), 10)
>>> nine_years = ten_years - year
>>> nine_years, nine_years.days // 365
(datetime.timedelta(3285), 9)
>>> three_years = nine_years // 3;
>>> three_years, three_years.days // 365
(datetime.timedelta(1095), 3)
>>> abs(three_years - ten_years) == 2 * three_years + year
True

8.1.3. date 对象

date 对象表示理想化日历中的日期(年,月和日),当前格雷戈里日历在两个方向上无限延伸。第1年的1月1日被称为第1号,第1年的1月2日被称为第2号,等等。这符合Dershowitz和Reingold的“Calendrical Calculations”书中的“proleptic Gregorian”日历的定义,其中它是所有计算的基本日历。请参阅这本书,用于在简单格雷戈里语序数和许多其他日历系统之间进行转换的算法。

class datetime.date(year, month, day)

所有参数都是必需的。参数可以是以下范围内的整数:

  • MINYEAR <= year <= MAXYEAR

  • 1 <= month <= 12

  • 1 <= day <= number of days in the given month and year

如果给出了这些范围之外的参数,则提出 ValueError

其他构造函数,所有类方法:

classmethod date.today()

返回当前本地日期。这相当于 date.fromtimestamp(time.time())

classmethod date.fromtimestamp(timestamp)

返回与POSIX时间戳对应的本地日期,例如 time.time() 返回的日期。如果时间戳超出平台C localtime() 函数支持的值的范围,并且 OSErrorlocaltime() 失败,则这可能提高 OverflowError。它通常被限制为从1970年到2038年的几年。请注意,在包括闰秒在其时间戳的概念的非POSIX系统,闰秒被 fromtimestamp() 忽略。

在 3.3 版更改: 如果时间戳超出平台C localtime() 功能支持的值的范围,请提高 OverflowError,而不是 ValueError。在 localtime() 失败时提高 OSError 而不是 ValueError

classmethod date.fromordinal(ordinal)

返回对应于地方格雷戈里亚序数的日期,其中第1年的1月1日有序数1.除非 1 <= ordinal <= date.max.toordinal(),否则提出 ValueError。任何日期 ddate.fromordinal(d.toordinal()) == d

类属性:

date.min

最早可表示日期,date(MINYEAR, 1, 1)

date.max

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

date.resolution

非等数日期对象 timedelta(days=1) 之间的最小可能差异。

实例属性(只读):

date.year

MINYEARMAXYEAR 之间。

date.month

介于1和12之间。

date.day

在1和给定年份的给定月份中的天数之间。

支持的操作:

操作

结果

date2 = date1 + timedelta

date2date1 移除 timedelta.days 天。 (1)

date2 = date1 - timedelta

计算 date2 使得 date2 + timedelta == date1。 (2)

timedelta = date1 - date2

(3)

date1 < date2

date1 在时间上先于 date2 时,认为 date1 小于 date2。 (4)

笔记:

  1. 如果 timedelta.days > 0date2 在时间上向前移动,或者如果 timedelta.days < 0,则向后移动。后来 date2 - date1 == timedelta.days。忽略 timedelta.secondstimedelta.microseconds。如果 date2.year 小于 MINYEAR 或大于 MAXYEAR,则产生 OverflowError

  2. 这不完全等价于date1 +(-timedelta),因为-timedelta在隔离的情况下可能会溢出,如果date1 - timedelta没有。 timedelta.secondstimedelta.microseconds 被忽略。

  3. 这是确切的,不能溢出。 timedelta.seconds和timedelta.microseconds是0,并且date2 + timedelta == date1之后。

  4. 换句话说,date1 < date2 当且仅当 date1.toordinal() < date2.toordinal()。为了停止比较,回退到比较对象地址的默认方案,如果另一个比较数据不是 date 对象,日期比较通常会提高 TypeError。但是,如果另一个比较数据具有 timetuple() 属性,则返回 NotImplemented。这个钩子给其他种类的日期对象一个机会实现混合型比较。如果不是,当将 date 对象与不同类型的对象进行比较时,TypeError 升高,除非比较是 ==!=。后一种情况分别返回 FalseTrue

日期可以用作字典键。在布尔上下文中,所有 date 对象都被视为true。

实例方法:

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

返回具有相同值的日期,但通过指定的任何关键字参数为给定新值的参数除外。例如,如果 d == date(2002, 12, 31),则 d.replace(day=26) == date(2002, 12, 26)

date.timetuple()

返回由 time.localtime() 返回的 time.struct_time。小时,分钟和秒为0,DST标志为-1。 d.timetuple() 等价于 time.struct_time((d.year, d.month, d.day, 0, 0, 0, d.weekday(), yday, -1)),其中 yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1 是从1月1日的 1 开始的当前年份中的天数。

date.toordinal()

返回日期的普通格雷戈里的序数,其中第1年的1月1日有序数1.对于任何 date 对象 ddate.fromordinal(d.toordinal()) == d

date.weekday()

将星期几作为整数返回,其中星期一为0,星期六为6.例如,date(2002, 12, 4).weekday() == 2,星期三。参见 isoweekday()

date.isoweekday()

将星期几作为整数返回,其中星期一为1,星期日为7.例如,date(2002, 12, 4).isoweekday() == 3,星期三。参见 weekday()isocalendar()

date.isocalendar()

返回3元组(ISO年,ISO周数,ISO工作日)。

ISO日历是公历日历的广泛使用的变体。见 https://www.staff.science.uu.nl/~gent0113/calendar/isocalendar.htm 的好的解释。

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.isoformat()

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

date.__str__()

对于日期 dstr(d) 等同于 d.isoformat()

date.ctime()

返回表示日期的字符串,例如 date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'd.ctime() 在平台上等效于 time.ctime(time.mktime(d.timetuple())),其中本机C ctime() 功能(time.ctime() 调用,但 date.ctime() 未调用)符合C标准。

date.strftime(format)

返回一个表示日期的字符串,由显式格式字符串控制。格式代码小时,分钟或秒的代码将看到0个值。有关格式化伪指令的完整列表,请参阅 strftime() 和 strptime() 行为

date.__format__(format)

date.strftime() 相同。这使得可以在 格式化的字符串文字 中和当使用 str.format() 时指定 date 对象的格式字符串。有关格式化伪指令的完整列表,请参见 strftime() 和 strptime() 行为

计数事件的天数示例:

>>> import time
>>> from datetime import date
>>> today = date.today()
>>> today
datetime.date(2007, 12, 5)
>>> today == date.fromtimestamp(time.time())
True
>>> my_birthday = date(today.year, 6, 24)
>>> if my_birthday < today:
...     my_birthday = my_birthday.replace(year=today.year + 1)
>>> my_birthday
datetime.date(2008, 6, 24)
>>> time_to_birthday = abs(my_birthday - today)
>>> time_to_birthday.days
202

使用 date 的示例:

>>> from datetime import date
>>> d = date.fromordinal(730920) # 730920th day after 1. 1. 0001
>>> d
datetime.date(2002, 3, 11)
>>> t = d.timetuple()
>>> for i in t:     
...     print(i)
2002                # year
3                   # month
11                  # day
0
0
0
0                   # weekday (0 = Monday)
70                  # 70th day in the year
-1
>>> ic = d.isocalendar()
>>> for i in ic:    
...     print(i)
2002                # ISO year
11                  # ISO week number
1                   # ISO day number ( 1 = Monday )
>>> d.isoformat()
'2002-03-11'
>>> d.strftime("%d/%m/%y")
'11/03/02'
>>> d.strftime("%A %d. %B %Y")
'Monday 11. March 2002'
>>> 'The {1} is {0:%d}, the {2} is {0:%B}.'.format(d, "day", "month")
'The day is 11, the month is March.'

8.1.4. datetime 对象

datetime 对象是包含来自 date 对象和 time 对象的所有信息的单个对象。像 date 对象一样,datetime 假定当前的公历在两个方向上延伸;像时间对象,datetime 假设每天有3600 * 24秒。

构造函数:

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

年,月和日参数是必需的。 tzinfo 可以是 None,或 tzinfo 子类的实例。其余参数可以是以下范围内的整数:

  • MINYEAR <= year <= MAXYEAR

  • 1 <= month <= 12

  • 1 <= day <= number of days in the given month and year

  • 0 <= hour < 24

  • 0 <= minute < 60

  • 0 <= second < 60

  • 0 <= microsecond < 1000000

  • fold in [0, 1]

如果给出了这些范围之外的参数,则提出 ValueError

3.6 新版功能: 添加了 fold 参数。

其他构造函数,所有类方法:

classmethod datetime.today()

返回当前本地日期时间,使用 tzinfo None。这相当于 datetime.fromtimestamp(time.time())。参见 now()fromtimestamp()

classmethod datetime.now(tz=None)

返回当前本地日期和时间。如果可选参数 tzNone 或未指定,这就像 today(),但如果可能,提供比通过 time.time() 时间戳获得的精度更高的精度(例如,这可能在提供C gettimeofday() 函数的平台上)。

如果 tz 不是 None,它必须是 tzinfo 子类的实例,并且当前日期和时间将转换为 tz 的时区。在这种情况下,结果等同于 tz.fromutc(datetime.utcnow().replace(tzinfo=tz))。参见 today()utcnow()

classmethod datetime.utcnow()

返回当前UTC日期和时间,使用 tzinfo None。这就像 now(),但返回当前UTC日期和时间,作为一个幼稚的 datetime 对象。通过调用 datetime.now(timezone.utc) 可以获得感知当前UTC日期时间。参见 now()

classmethod datetime.fromtimestamp(timestamp, tz=None)

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

如果 tz 不是 None,它必须是 tzinfo 子类的实例,并且时间戳转换为 tz 的时区。在这种情况下,结果等同于 tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))

如果时间戳超出平台C localtime()gmtime() 功能支持的值的范围,以及 localtime()gmtime() 故障时的 OSError,则 fromtimestamp() 可以产生 OverflowError。它通常被限制为1970年到2038年的多年。请注意,在包含闰秒的时间戳的概念中的非POSIX系统,闰秒被 fromtimestamp() 忽略,然后可能有两个时间戳相差一个第二,产生相同的 datetime 对象。参见 utcfromtimestamp()

在 3.3 版更改: 如果时间戳超出平台C localtime()gmtime() 函数支持的值的范围,请提高 OverflowError 而不是 ValueError。在 localtime()gmtime() 故障时提高 OSError 而不是 ValueError

在 3.6 版更改: fromtimestamp() 可返回 fold 设置为1的实例。

classmethod datetime.utcfromtimestamp(timestamp)

返回对应于POSIX时间戳的UTC datetime,使用 tzinfo None。如果时间戳在平台C gmtime() 函数支持的值的范围之外,并且 OSErrorgmtime() 失败时,这可以提高 OverflowError。它通常被限制为1970年到2038年的年。

要获得感知的 datetime 对象,请调用 fromtimestamp():

datetime.fromtimestamp(timestamp, timezone.utc)

在POSIX兼容平台上,它等价于以下表达式:

datetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=timestamp)

除非后者公式总是支持全年范围:在 MINYEARMAXYEAR 之间。

在 3.3 版更改: 如果时间戳超出平台C gmtime() 功能支持的值的范围,请提高 OverflowError,而不是 ValueError。在 gmtime() 失败时提高 OSError 而不是 ValueError

classmethod datetime.fromordinal(ordinal)

返回对应于普通公历序列的 datetime,其中第1年的1月1号具有序数1.除非 1 <= ordinal <= datetime.max.toordinal(),否则 ValueError 被提升。结果的小时,分,秒和微秒都是0,tzinfoNone

classmethod datetime.combine(date, time, tzinfo=self.tzinfo)

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

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

在 3.6 版更改: 添加了 tzinfo 参数。

classmethod datetime.strptime(date_string, format)

返回对应于 date_stringdatetime,根据 format 解析。这相当于 datetime(*(time.strptime(date_string, format)[0:6]))。如果date_string和格式不能由 time.strptime() 解析或如果返回的值不是时间元组,则会引发 ValueError。有关格式化伪指令的完整列表,请参见 strftime() 和 strptime() 行为

类属性:

datetime.min

最早代表的 datetimedatetime(MINYEAR, 1, 1, tzinfo=None)

datetime.max

最新的可代表性的 datetimedatetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, tzinfo=None)

datetime.resolution

非等量 datetime 对象(timedelta(microseconds=1))之间的最小可能差异。

实例属性(只读):

datetime.year

MINYEARMAXYEAR 之间。

datetime.month

介于1和12之间。

datetime.day

在1和给定年份的给定月份中的天数之间。

datetime.hour

range(24)

datetime.minute

range(60)

datetime.second

range(60)

datetime.microsecond

range(1000000)

datetime.tzinfo

该对象作为 tzinfo 参数传递给 datetime 构造函数,如果没有传递,则为 None

datetime.fold

[0, 1]。用于在重复间隔期间消除壁时间。 (当夏令时结束时或当当前区域的UTC偏移由于政治原因而减少时,时钟被回滚时,会发生重复间隔。)值0(1)表示两个时刻的较早(较晚)相同的墙时间表示。

3.6 新版功能.

支持的操作:

操作

结果

datetime2 = datetime1 + timedelta

(1)

datetime2 = datetime1 - timedelta

(2)

timedelta = datetime1 - datetime2

(3)

datetime1 < datetime2

datetimedatetime 进行比较。 (4)

  1. datetime2是从datetime1中删除timedelta的持续时间,如果 timedelta.days> 0则向前移动,或者如果 timedelta.days <0则向后移动。结果具有与输入datetime相同的 tzinfo 属性,datetime2 - datetime1 == timedelta之后。如果datetime2.year小于 MINYEAR 或大于 MAXYEAR,则引发 OverflowError。注意,即使输入是感知对象,也不执行时区调整。

  2. 计算datetime2,使datetime2 + timedelta == datetime1。至于添加,结果具有与输入日期时间相同的 tzinfo 属性,并且即使输入已知,也不执行时区调整。这不完全等同于datetime1 +(-timedelta),因为-timedelta隔离可能会溢出在datetime1 - timedelta没有。

  3. 仅当两个操作数都是初始的或者两者都知道时,才定义从 datetime 中减去 datetime。如果一个人知道,另一个是天真的,TypeError 被提出。

    如果两者都是幼稚的,或者两者都知道并且具有相同的 tzinfo 属性,则 tzinfo 属性被忽略,并且结果是 timedelta 对象 t,使得 datetime2 + t == datetime1。在这种情况下不进行时区调整。

    如果两者都知道并具有不同的 tzinfo 属性,a-b 就好像首先将 ab 转换为初始UTC数据时。结果是 (a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset()),但实现永远不会溢出。

  4. datetime1 在时间上先于 datetime2 时,认为 datetime1 小于 datetime2

    如果一个比较对象是幼稚的,另一个是意识到的,则如果试图进行顺序比较,则产生 TypeError。对于等式比较,初始实例永远不等于感知实例。

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

    在 3.3 版更改: 天真和感知 datetime 实例之间的平等比较不会提高 TypeError

    注解

    为了停止比较,回退到比较对象地址的默认方案,如果另一比较数据不是 datetime 对象,则datetime比较通常提高 TypeError。但是,如果另一个compareand具有 timetuple() 属性,则返回 NotImplemented。这个钩子给其他种类的日期对象一个机会实现混合型比较。如果不是,当将 datetime 对象与不同类型的对象进行比较时,TypeError 被提升,除非比较是 ==!=。后一种情况分别返回 FalseTrue

datetime 对象可以用作字典键。在布尔上下文中,所有 datetime 对象都被视为true。

实例方法:

datetime.date()

返回具有相同年,月和日的 date 对象。

datetime.time()

以相同的小时,分钟,秒,微秒和折叠返回 time 对象。 tzinfoNone。也参见方法 timetz()

在 3.6 版更改: 折叠值将复制到返回的 time 对象。

datetime.timetz()

返回具有相同hour,minute,second,microsecond,fold和tzinfo属性的 time 对象。参见方法 time()

在 3.6 版更改: 折叠值将复制到返回的 time 对象。

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,除了通过指定的任何关键字参数赋予新值的那些属性。请注意,可以指定 tzinfo=None 从无意义日期时间的日期和时间数据转换创建一个天真的datetime。

3.6 新版功能: 添加了 fold 参数。

datetime.astimezone(tz=None)

返回具有新 tzinfo 属性 tzdatetime 对象,调整日期和时间数据,使得结果与 self 相同,但是在 tz 的本地时间。

如果提供,tz 必须是 tzinfo 子类的实例,并且其 utcoffset()dst() 方法不得返回 None。如果 self 是幼稚的(self.tzinfo is None),则假定在系统时区中表示时间。

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

如果 self.tzinfotz,则 self.astimezone(tz) 等于 self:不执行日期或时间数据的调整。否则结果是时区 tz 中的本地时间,表示与 self 相同的UTC时间:在 astz = dt.astimezone(tz) 之后,astz - astz.utcoffset() 将具有与 dt - dt.utcoffset() 相同的日期和时间数据。

如果您只想将时区对象 tz 附加到日期时间 dt 而不调整日期和时间数据,请使用 dt.replace(tzinfo=tz)。如果您只想从意识到的日期时间 dt 中删除时区对象,而不转换日期和时间数据,请使用 dt.replace(tzinfo=None)

注意,默认的 tzinfo.fromutc() 方法可以在 tzinfo 子类中被覆盖,以影响 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)

在 3.3 版更改: tz 现在可以省略。

在 3.6 版更改: 现在可以在被假定为表示系统本地时间的初始实例上调用 astimezone() 方法。

datetime.utcoffset()

如果 tzinfoNone,则返回 None,否则返回 self.tzinfo.utcoffset(self),并且如果后者不返回 None 或者表示小于一天的整数分钟的 timedelta 对象,则引发异常。

datetime.dst()

如果 tzinfoNone,则返回 None,否则返回 self.tzinfo.dst(self),并且如果后者不返回 None 或者表示小于一天的整数分钟的 timedelta 对象,则引发异常。

datetime.tzname()

如果 tzinfoNone,返回 None,否则返回 self.tzinfo.tzname(self),如果后者不返回 None 或字符串对象则引发异常,

datetime.timetuple()

返回由 time.localtime() 返回的 time.struct_timed.timetuple() 等价于 time.struct_time((d.year, d.month, d.day, d.hour, d.minute, d.second, d.weekday(), yday, dst)),其中 yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1 是从1月1日的 1 开始的当前年份中的天数。结果的 tm_isdst 标志根据 dst() 方法设置:tzinfoNonedst() 返回 Nonetm_isdst 被设置为 -1;否则如果 dst() 返回非零值,tm_isdst 设置为 1;否则 tm_isdst 设置为 0

datetime.utctimetuple()

如果 datetime 实例 d 是天真的,这与 d.timetuple() 相同,除了 tm_isdst 被强制为0,而不管 d.dst() 返回什么。 DST从未在UTC时间生效。

如果 d 知道,d 通过减去 d.utcoffset() 被归一化到UTC时间,并且返回归一化时间的 time.struct_timetm_isdst 被迫为0.注意,如果 d .year是 MINYEARMAXYEAR 和UTC调整超过一年的边界,则可能会产生 OverflowError

datetime.toordinal()

返回日期的proleptic Gregorian ordinal。与 self.date().toordinal() 相同。

datetime.timestamp()

返回与 datetime 实例对应的POSIX时间戳。返回值是与 time.time() 返回的类似的 float

原始 datetime 实例被假定为表示本地时间,并且该方法依赖于平台C mktime() 功能来执行转换。由于 datetime 在许多平台上支持比 mktime() 更广泛的值,所以该方法可以在过去或远远的时间内提高 OverflowError 的时间。

对于感知 datetime 实例,返回值计算为:

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

3.3 新版功能.

在 3.6 版更改: timestamp() 方法使用 fold 属性来消除重复间隔期间的时间。

注解

没有方法直接从表示UTC时间的朴素 datetime 实例获取POSIX时间戳。如果您的应用程序使用此约定,并且您的系统时区未设置为UTC,您可以通过提供 tzinfo=timezone.utc 来获取POSIX时间戳:

timestamp = dt.replace(tzinfo=timezone.utc).timestamp()

或直接计算时间戳:

timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)
datetime.weekday()

将星期几作为整数返回,其中星期一为0,星期六为6.与 self.date().weekday() 相同。参见 isoweekday()

datetime.isoweekday()

将星期几作为整数返回,其中星期一为1,星期日为7.与 self.date().isoweekday() 相同。参见 weekday()isocalendar()

datetime.isocalendar()

返回3元组(ISO年,ISO周数,ISO工作日)。与 self.date().isocalendar() 相同。

datetime.isoformat(sep='T', timespec='auto')

以ISO 8601格式,-MM-DDTHH:MM:SS.mmmmmm返回一个表示日期和时间的字符串,如果 microsecond 为0,则返回 -MM-DDTHH:MM:SS

如果 utcoffset() 不返回 None,则附加一个6个字符的字符串,以(签名)小时和分钟为单位给出UTC偏移量:-MM-DDTHH:MM:SS.mmmmmm + HH:MM或者如果 microsecond 为0 - MM-DDTHH:MM:SS + HH:MM

可选参数 sep (默认 'T')是一个单字符分隔符,位于结果的日期和时间部分之间。例如,

>>> from datetime import tzinfo, timedelta, datetime
>>> class TZ(tzinfo):
...     def utcoffset(self, dt): return timedelta(minutes=-399)
...
>>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ')
'2002-12-25 00:00:00-06:39'

可选参数 timespec 指定要包含的时间的附加组件数(默认值为 'auto')。它可以是以下之一:

  • 'auto':如果 microsecond 为0,与 'seconds' 相同,否则与 'microseconds' 相同。

  • 'hours':以两位数HH格式包含 hour

  • 'minutes':在HH:MM格式中包括 hourminute

  • 'seconds':在HH:MM:SS格式中包括 hourminutesecond

  • 'milliseconds':包括全部时间,但截断小数秒部分到毫秒。 HH:MM:SS.sss格式。

  • 'microseconds':包括全时格式在HH:MM:SS.mmmmmm格式。

注解

排除的时间组件被截断,不舍入。

ValueError 将对无效的 timespec 参数引发。

>>> from datetime import datetime
>>> datetime.now().isoformat(timespec='minutes')
'2002-12-25T00:00'
>>> dt = datetime(2015, 1, 1, 12, 30, 59, 0)
>>> dt.isoformat(timespec='microseconds')
'2015-01-01T12:30:59.000000'

3.6 新版功能: 添加了 timespec 参数。

datetime.__str__()

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

datetime.ctime()

返回表示日期和时间的字符串,例如 datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec  4 20:30:40 2002'd.ctime() 在平台上等效于 time.ctime(time.mktime(d.timetuple())),其中本机C ctime() 功能(time.ctime() 调用,但 datetime.ctime() 未调用)符合C标准。

datetime.strftime(format)

返回一个表示日期和时间的字符串,由显式格式字符串控制。有关格式化伪指令的完整列表,请参阅 strftime() 和 strptime() 行为

datetime.__format__(format)

datetime.strftime() 相同。这使得可以在 格式化的字符串文字 中和当使用 str.format() 时指定 datetime 对象的格式字符串。有关格式化伪指令的完整列表,请参见 strftime() 和 strptime() 行为

使用datetime对象的示例:

>>> from datetime import datetime, date, time
>>> # Using datetime.combine()
>>> d = date(2005, 7, 14)
>>> t = time(12, 30)
>>> datetime.combine(d, t)
datetime.datetime(2005, 7, 14, 12, 30)
>>> # Using datetime.now() or datetime.utcnow()
>>> datetime.now()   
datetime.datetime(2007, 12, 6, 16, 29, 43, 79043)   # GMT +1
>>> datetime.utcnow()   
datetime.datetime(2007, 12, 6, 15, 29, 43, 79060)
>>> # Using datetime.strptime()
>>> dt = datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M")
>>> dt
datetime.datetime(2006, 11, 21, 16, 30)
>>> # Using datetime.timetuple() to get tuple of all attributes
>>> tt = dt.timetuple()
>>> for it in tt:   
...     print(it)
...
2006    # year
11      # month
21      # day
16      # hour
30      # minute
0       # second
1       # weekday (0 = Monday)
325     # number of days since 1st January
-1      # dst - method tzinfo.dst() returned None
>>> # Date in ISO format
>>> ic = dt.isocalendar()
>>> for it in ic:   
...     print(it)
...
2006    # ISO year
47      # ISO week
2       # ISO weekday
>>> # Formatting datetime
>>> dt.strftime("%A, %d. %B %Y %I:%M%p")
'Tuesday, 21. November 2006 04:30PM'
>>> '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 21, the month is November, the time is 04:30PM.'

对tzinfo使用datetime:

>>> from datetime import timedelta, datetime, tzinfo
>>> class GMT1(tzinfo):
...     def utcoffset(self, dt):
...         return timedelta(hours=1) + self.dst(dt)
...     def dst(self, dt):
...         # DST starts last Sunday in March
...         d = datetime(dt.year, 4, 1)   # ends last Sunday in October
...         self.dston = d - timedelta(days=d.weekday() + 1)
...         d = datetime(dt.year, 11, 1)
...         self.dstoff = d - timedelta(days=d.weekday() + 1)
...         if self.dston <=  dt.replace(tzinfo=None) < self.dstoff:
...             return timedelta(hours=1)
...         else:
...             return timedelta(0)
...     def tzname(self,dt):
...          return "GMT +1"
...
>>> class GMT2(tzinfo):
...     def utcoffset(self, dt):
...         return timedelta(hours=2) + self.dst(dt)
...     def dst(self, dt):
...         d = datetime(dt.year, 4, 1)
...         self.dston = d - timedelta(days=d.weekday() + 1)
...         d = datetime(dt.year, 11, 1)
...         self.dstoff = d - timedelta(days=d.weekday() + 1)
...         if self.dston <=  dt.replace(tzinfo=None) < self.dstoff:
...             return timedelta(hours=1)
...         else:
...             return timedelta(0)
...     def tzname(self,dt):
...         return "GMT +2"
...
>>> gmt1 = GMT1()
>>> # Daylight Saving Time
>>> dt1 = datetime(2006, 11, 21, 16, 30, tzinfo=gmt1)
>>> dt1.dst()
datetime.timedelta(0)
>>> dt1.utcoffset()
datetime.timedelta(0, 3600)
>>> dt2 = datetime(2006, 6, 14, 13, 0, tzinfo=gmt1)
>>> dt2.dst()
datetime.timedelta(0, 3600)
>>> dt2.utcoffset()
datetime.timedelta(0, 7200)
>>> # Convert datetime to another time zone
>>> dt3 = dt2.astimezone(GMT2())
>>> dt3     
datetime.datetime(2006, 6, 14, 14, 0, tzinfo=<GMT2 object at 0x...>)
>>> dt2     
datetime.datetime(2006, 6, 14, 13, 0, tzinfo=<GMT1 object at 0x...>)
>>> dt2.utctimetuple() == dt3.utctimetuple()
True

8.1.5. 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 in [0, 1]

如果给出了这些范围之外的参数,则提出 ValueError。所有默认为 0,除了 tzinfo,默认为 None

类属性:

time.min

最早代表的 timetime(0, 0, 0, 0)

time.max

最新的可代表性的 timetime(23, 59, 59, 999999)

time.resolution

尽管注意到不支持对 time 对象的算术,但不等于 time 对象 timedelta(microseconds=1) 之间的最小可能差异。

实例属性(只读):

time.hour

range(24)

time.minute

range(60)

time.second

range(60)

time.microsecond

range(1000000)

time.tzinfo

对象作为tzinfo参数传递给 time 构造函数,或者 None (如果没有传递)。

time.fold

[0, 1]。用于在重复间隔期间消除壁时间。 (当夏令时结束时或当当前区域的UTC偏移由于政治原因而减少时,时钟被回滚时,会发生重复间隔。)值0(1)表示两个时刻的较早(较晚)相同的墙时间表示。

3.6 新版功能.

支持的操作:

  • timetime 的比较,其中当 a 在时间上先于 b 时,认为 a 小于 b。如果一个比较对象是幼稚的,而另一个是意识到的,则如果尝试了顺序比较,则产生 TypeError。对于等式比较,初始实例永远不等于感知实例。

    如果两个比较值都知道,并且具有相同的 tzinfo 属性,则忽略公共 tzinfo 属性,并比较基本时间。如果两个比较值都知道并具有不同的 tzinfo 属性,则首先通过减去它们的UTC偏移量(从 self.utcoffset() 获得)来调整比较值。为了停止混合类型比较从对象地址回退到默认比较,当将 time 对象与不同类型的对象进行比较时,TypeError 被提升,除非比较是 ==!=。后一种情况分别返回 FalseTrue

    在 3.3 版更改: 天真和感知 time 实例之间的平等比较不会提高 TypeError

  • 哈希,用作dict键

  • 高效酸洗

在布尔上下文中,time 对象总是被认为是真的。

在 3.5 版更改: 在Python 3.5之前,如果 time 对象表示UTC的午夜,则认为它是false。这个行为被认为是晦涩和容易出错,已在Python 3.5中删除。有关详细信息,请参阅 issue 13936

实例方法:

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

返回具有相同值的 time,除了通过指定的任何关键字参数给出新值的那些属性。注意,可以指定 tzinfo=None 以从感知 time 创建原始 time,而不转换时间数据。

3.6 新版功能: 添加了 fold 参数。

time.isoformat(timespec='auto')

返回一个表示ISO 8601格式时间的字符串,HH:MM:SS.mmmmmm,或者,如果 microsecond 为0,HH:MM:SS如果 utcoffset() 不返回 None,将附加一个6个字符的字符串, (有符号)小时和分钟:HH:MM:SS.mmmmmm + HH:MM,如果self.microsecond为0,则HH:MM:SS + HH:MM

可选参数 timespec 指定要包含的时间的附加组件数(默认值为 'auto')。它可以是以下之一:

  • 'auto':如果 microsecond 为0,与 'seconds' 相同,否则与 'microseconds' 相同。

  • 'hours':以两位数HH格式包含 hour

  • 'minutes':在HH:MM格式中包括 hourminute

  • 'seconds':在HH:MM:SS格式中包括 hourminutesecond

  • 'milliseconds':包括全部时间,但截断小数秒部分到毫秒。 HH:MM:SS.sss格式。

  • 'microseconds':包括全时格式在HH:MM:SS.mmmmmm格式。

注解

排除的时间组件被截断,不舍入。

ValueError 将对无效的 timespec 参数引发。

>>> from datetime import time
>>> time(hour=12, minute=34, second=56, microsecond=123456).isoformat(timespec='minutes')
'12:34'
>>> dt = time(hour=12, minute=34, second=56, microsecond=0)
>>> dt.isoformat(timespec='microseconds')
'12:34:56.000000'
>>> dt.isoformat(timespec='auto')
'12:34:56'

3.6 新版功能: 添加了 timespec 参数。

time.__str__()

对于 t 时间,str(t) 等效于 t.isoformat()

time.strftime(format)

返回一个表示时间的字符串,由显式格式字符串控制。有关格式化伪指令的完整列表,请参阅 strftime() 和 strptime() 行为

time.__format__(format)

time.strftime() 相同。这使得可以在 格式化的字符串文字 中和当使用 str.format() 时指定 time 对象的格式字符串。有关格式化伪指令的完整列表,请参见 strftime() 和 strptime() 行为

time.utcoffset()

如果 tzinfoNone,则返回 None,否则返回 self.tzinfo.utcoffset(None),并且如果后者不返回 None 或表示大小小于一天的整分钟数的 timedelta 对象,则引发异常。

time.dst()

如果 tzinfoNone,则返回 None,否则返回 self.tzinfo.dst(None),并且如果后者不返回 None 或者表示小于一天的整数分钟的 timedelta 对象,则引发异常。

time.tzname()

如果 tzinfoNone,则返回 None,否则返回 self.tzinfo.tzname(None),或者如果后者不返回 None 或字符串对象则引发异常。

例:

>>> from datetime import time, tzinfo
>>> 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=<GMT1 object at 0x...>)
>>> gmt = GMT1()
>>> t.isoformat()
'12:10:30+01:00'
>>> t.dst()
datetime.timedelta(0)
>>> t.tzname()
'Europe/Prague'
>>> t.strftime("%H:%M:%S %Z")
'12:10:30 Europe/Prague'
>>> 'The {} is {:%H:%M}.'.format("time", t)
'The time is 12:10.'

8.1.6. tzinfo 对象

class datetime.tzinfo

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

tzinfo 的一个实例(一个具体子类)可以传递给 datetimetime 对象的构造函数。后面的对象将它们的属性视为在本地时间,并且 tzinfo 对象支持显示本地时间与UTC,时区的名称和DST偏移量的偏移,所有这些都相对于传递给它们的日期或时间对象。

酸洗的特殊要求:tzinfo 子类必须有一个 __init__() 方法,可以调用没有参数,否则它可以酸洗,但可能不再取消。这是一个在未来可能放松的技术要求。

tzinfo 的具体子类可能需要实现以下方法。需要哪些方法取决于使用感知 datetime 对象。如果有疑问,只需实施所有这些。

tzinfo.utcoffset(dt)

返回本地时间与UTC的偏移量,以UTC为单位的分钟数。如果本地时间在UTC的西边,这应该是负的。请注意,这是UTC的总偏移量;例如,如果 tzinfo 对象表示时区和DST调整,则 utcoffset() 应返回其和。如果UTC偏移量未知,请返回 None。否则返回的值必须是 timedelta 对象,指定-1439到1439范围内的整数分钟(1440 = 24 * 60;偏移量必须小于一天)。大多数 utcoffset() 的实现可能看起来像这两个:

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

如果 utcoffset() 不返回 Nonedst() 也不应返回 None

utcoffset() 的默认实现提高 NotImplementedError

tzinfo.dst(dt)

返回夏令时(DST)调整(UTC以前的分钟数),如果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)

必须对每个具有 dt.tzinfo == tzdatetime dt 返回相同的结果对于正常的 tzinfo 子类,此表达式产生时区的“标准偏移”,其不应取决于日期或时间,而仅取决于地理位置。 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.  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”,“America/New York”都是有效回复。如果字符串名称未知,返回 None。注意,这是一个方法而不是一个固定的字符串,主要是因为一些 tzinfo 子类希望根据传递的 dt 的具体值返回不同的名称,特别是如果 tzinfo 类占了白天时间。

tzname() 的默认实现提高 NotImplementedError

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

None 通过时,由类设计者决定最佳响应。例如,如果该类希望说时间对象不参与 tzinfo 协议,则返回 None 是适当的。对于 utcoffset(None),返回标准UTC偏移可能更有用,因为没有发现标准偏移的其他约定。

当响应于 datetime 方法传递 datetime 对象时,dt.tzinfo 是与 self 相同的对象。 tzinfo 方法可以依赖于此,除非用户代码直接调用 tzinfo 方法。意图是 tzinfo 方法将 dt 解释为在本地时间,并且不需要担心其他时区中的对象。

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

tzinfo.fromutc(dt)

这是从默认的 datetime.astimezone() 实现中调用的。当从中调用时,dt.tzinfoselfdt 的日期和时间数据被视为表示UTC时间。 fromutc() 的目的是调整日期和时间数据,在 self 的本地时间返回等效的datetime。

大多数 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, timezone

ZERO = timedelta(0)
HOUR = timedelta(hours=1)
SECOND = timedelta(seconds=1)

# A class capturing the platform's idea of local time.
# (May result in wrong values on historical times in
#  timezones where UTC offset and/or the DST rules had
#  changed in the past.)
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")

注意,在DST转换点处,在 tzinfo 子类中存在每年两次不可避免的微小差异,其占据标准时间和日光时间。为了具体性,考虑美国东部(UTC-0500),其中EDT在3月的第二个星期日1:59(EST)之后的分钟开始,并且在11月的第一个星期日1:59(EDT):

  UTC   3:MM  4:MM  5:MM  6:MM  7:MM  8:MM
  EST  22:MM 23:MM  0:MM  1:MM  2:MM  3:MM
  EDT  23:MM  0:MM  1:MM  2:MM  3:MM  4:MM

start  22:MM 23:MM  0:MM  1:MM  3:MM  4:MM

  end  23:MM  0:MM  1:MM  1:MM  2:MM  3:MM

当DST开始(“开始”行),本地墙钟从1:59飞跃到3:00。格式2:MM的挂钟时间在当天没有任何意义,因此 astimezone(Eastern) 将不会在DST开始当天提供 hour == 2 的结果。例如,在2016年春天的过渡,我们得到

>>> u0 = datetime(2016, 3, 13, 5, tzinfo=timezone.utc)
>>> for i in range(4):
...     u = u0 + i*HOUR
...     t = u.astimezone(Eastern)
...     print(u.time(), 'UTC =', t.time(), t.tzname())
...
05:00:00 UTC = 00:00:00 EST
06:00:00 UTC = 01:00:00 EST
07:00:00 UTC = 03:00:00 EDT
08:00:00 UTC = 04:00:00 EDT

当DST结束(“结束”行)时,有一个可能更糟糕的问题:有一个小时不能在本地墙上时间明确拼写:白天的最后一个小时。在东部,这是时间的形式5:MM UTC在日间时间结束。本地墙钟从1:59(夏令时)回到1:00(标准时间)。形式1:MM的本地时间不明确。 astimezone() 通过将两个相邻的UTC小时映射到相同的当地时间来模拟本地时钟的行为。在东方示例中,形式为5:MM和6:MM的UTC时间转换为东方时映射为1:MM,但较早时间的 fold 属性设置为0,后面的时间设置为1。 ,在2016年的回落过渡,我们得到

>>> u0 = datetime(2016, 11, 6, 4, tzinfo=timezone.utc)
>>> for i in range(4):
...     u = u0 + i*HOUR
...     t = u.astimezone(Eastern)
...     print(u.time(), 'UTC =', t.time(), t.tzname(), t.fold)
...
04:00:00 UTC = 00:00:00 EDT 0
05:00:00 UTC = 01:00:00 EDT 0
06:00:00 UTC = 01:00:00 EST 1
07:00:00 UTC = 02:00:00 EST 0

注意,仅在 fold 属性的值方面不同的 datetime 实例在比较中被认为是相等的。

不能承载墙时间模糊的应用程序应该显式地检查 fold 属性的值或避免使用混合 tzinfo 子类;当使用 timezone 或任何其他固定偏移 tzinfo 子类(例如仅表示EST(固定偏移-5小时)或仅表示EDT(固定偏移-4小时)的类)时没有歧义。

参见

datetuil.tz

标准库具有 timezone 类,用于处理来自UTC和 timezone.utc 的任意固定偏移作为UTC时区实例。

datetuil.tz 库将 IANA时区数据库 (也称为Olson数据库)带到Python,建议使用它。

IANA时区数据库

时区数据库(通常称为tz,tzdata或zoneinfo)包含代表世界各地许多代表性位置的本地时间历史的代码和数据。它定期更新,以反映政治团体对时区边界,UTC偏移和夏令时规则所做的更改。

8.1.7. timezone 对象

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

class datetime.timezone(offset, name=None)

offset 参数必须指定为表示本地时间和UTC之间差异的 timedelta 对象。它必须严格地在 -timedelta(hours=24)timedelta(hours=24) 之间,并且表示整数分钟,否则产生 ValueError

name 参数是可选的。如果指定,它必须是将被用作 datetime.tzname() 方法返回的值的字符串。

3.2 新版功能.

timezone.utcoffset(dt)

返回构建 timezone 实例时指定的固定值。忽略 dt 参数。返回值是等于本地时间和UTC之间的差的 timedelta 实例。

timezone.tzname(dt)

返回构建 timezone 实例时指定的固定值。如果构造函数中没有提供 name,则 tzname(dt) 返回的名称从 offset 的值生成如下。如果 offsettimedelta(0),则名称是“UTC”,否则是字符串“UTC±HH:MM”,其中±是 offset 的符号,HH和MM分别是 offset.hoursoffset.minutes 的两个数字。

在 3.6 版更改: offset=timedelta(0) 生成的名称现在是简单的“UTC”,而不是“UTC + 00:00”。

timezone.dst(dt)

始终返回 None

timezone.fromutc(dt)

返回 dt + offsetdt 参数必须是知道的 datetime 实例,tzinfo 设置为 self

类属性:

timezone.utc

UTC时区,timezone(timedelta(0))

8.1.8. strftime()strptime() 行为

datedatetimetime 对象都支持 strftime(format) 方法,以创建一个表示在显式格式字符串控制下的时间的字符串。一般来说,d.strftime(fmt) 的行为就像 time 模块的 time.strftime(fmt, d.timetuple()),虽然并不是所有的对象都支持 timetuple() 方法。

相反,datetime.strptime() 类方法从表示日期和时间的字符串以及相应的格式字符串创建 datetime 对象。 datetime.strptime(date_string, format) 等同于 datetime(*(time.strptime(date_string, format)[0:6]))

对于 time 对象,不应使用年,月和日的格式代码,因为时间对象没有此类值。如果它们被使用,1900 替代年份,1 替代月份和日期。

对于 date 对象,不应使用小时,分钟,秒和微秒的格式代码,因为 date 对象没有此类值。如果它们被使用,0 替代它们。

支持的全套格式代码因平台而异,因为Python调用平台C库的 strftime() 函数,平台变体是常见的。要查看平台支持的全套格式代码,请参阅 strftime(3) 文档。

以下是C标准(1989年版本)要求的所有格式代码的列表,这些代码可在所有平台上使用标准C实现。注意,1999年版本的C标准添加了附加格式代码。

指示

含义

笔记

%a

工作日作为区域设置的缩写名称。

Sun,Mon,...,Sat(en_US);
所以,Mo,...,Sa(de_DE)

(1)

%A

工作日作为区域设置的全名。

星期日,星期一,...,星期六(en_US);
Sonntag,Montag,...,Samstag(de_DE)

(1)

%w

工作日为十进制数,其中0为星期日,6为星期六。

0, 1, ..., 6

 

%d

以月为单位的十进制数字。

01, 02, ..., 31

 

%b

月作为区域设置的缩写名称。

Jan,Feb,...,Dec(en_US);
Jan,Feb,...,Dez(de_DE)

(1)

%B

月作为区域设置的全名。

1月,2月,...,12月(en_US);
Januar,Februar,...,Dezember(de_DE)

(1)

%m

月作为零填充十进制数。

01, 02, ..., 12

 

%y

年,无世纪作为零填充十进制数。

00, 01, ..., 99

 

%Y

年份以世纪为十进制数。

0001, 0002, ..., 2013, 2014, ..., 9998, 9999

(2)

%H

小时(24小时制)作为零填充十进制数。

00, 01, ..., 23

 

%I

小时(12小时制)作为零填充十进制数。

01, 02, ..., 12

 

%p

Locale相当于AM或PM。

AM,PM(en_US);
am,pm(de_DE)

(1), (3)

%M

分钟为零填充十进制数。

00, 01, ..., 59

 

%S

第二个为零填充十进制数。

00, 01, ..., 59

(4)

%f

微秒作为十进制数,零填充在左边。

000000, 000001, ..., 999999

(5)

%z

UTC偏移形式为+ 或- (如果对象是幼稚的,则为空字符串)。

(空),+0000,-0400,+1030

(6)

%Z

时区名称(如果对象是幼稚的,则为空字符串)。

(空),UTC,EST,CST

 

%j

一年中的一天为零填充十进制数。

001, 002, ..., 366

 

%U

年的星期数(星期日作为星期的第一天)作为零填充十进制数。在第一个星期日之前的新的一年中的所有天被认为是在第0周。

00, 01, ..., 53

(7)

%W

年的星期(星期一作为星期的第一天)作为十进制数。在第一个星期一之前的新的一年中的所有天被认为是在第0周。

00, 01, ..., 53

(7)

%c

语言环境的适当日期和时间表示。

Tue Aug 16 21:30:00 1988(en_US);
Di 16 Aug 21:30:00 1988(de_DE)

(1)

%x

语言环境的适当日期表示。

08/16/88(无);
08/16/1988(en_US);
16.08.1988(de_DE)

(1)

%X

语言环境的适当时间表示。

21:30:00(zh_US);
21:30:00(de_DE)

(1)

%%

一个文字 '%' 字符。

%

 

为方便起见,包括C89标准不需要的一些附加指令。这些参数都对应于ISO 8601日期值。当与 strftime() 方法一起使用时,这些可能不在所有平台上可用。 ISO 8601年和ISO 8601周指令不能与上面的年份和周数指令互换。调用具有不完全或模糊的ISO 8601指令的 strptime() 将产生 ValueError

指示

含义

笔记

%G

ISO 8601年,世纪代表包含ISO周(%V)大部分的年份。

0001, 0002, ..., 2013, 2014, ..., 9998, 9999

(8)

%u

ISO 8601工作日为十进制数,其中1为星期一。

1, 2, ..., 7

 

%V

ISO 8601周为十进制数字,星期一为一周的第一天。第01周是包含1月4日的星期。

01, 02, ..., 53

(8)

3.6 新版功能: %G%u%V

笔记:

  1. 因为格式取决于当前的区域设置,在做出关于输出值的假设时应该小心。字段排序将有所不同(例如,“月/日/年”对“日/月/年”),输出可能包含使用语言环境的默认编码进行编码的Unicode字符(例如,如果当前语言环境是 ja_JP,默认编码可以是 eucJPSJISutf-8 中的任何一个;使用 locale.getlocale() 来确定当前语言环境的编码)。

  2. strptime() 方法可以在完整[1,9999]范围内解析年份,但年<1000必须填零到4位宽度。

    在 3.2 版更改: 在以前的版本中,strftime() 方法被限制为年> = 1900年。

    在 3.3 版更改: 在版本3.2中,strftime() 方法被限制为年> = 1000。

  3. 当与 strptime() 方法一起使用时,如果使用 %I 指令来解析小时,则 %p 指令仅影响输出小时字段。

  4. time 模块不同,datetime 模块不支持闰秒。

  5. 当与 strptime() 方法一起使用时,%f 指令接受右边的一至六个数字和零点。 %f 是C标准中的一组格式字符的扩展(但是在datetime对象中单独实现,因此始终可用)。

  6. 对于幼稚的对象,%z%Z 格式代码被空字符串替换。

    对于感知对象:

    %z

    utcoffset() 转换为+ 或- 格式的5字符字符串,其中HH是给出UTC偏移小时数的2位字符串,MM是给出UTC偏移分钟数的2位字符串。例如,如果 utcoffset() 返回 timedelta(hours=-3, minutes=-30),则 %z 被替换为字符串 '-0330'

    %Z

    如果 tzname() 返回 None,则 %Z 将替换为空字符串。否则 %Z 被替换为返回值,它必须是字符串。

    在 3.2 版更改: %z 指令被提供给 strptime() 方法时,将产生一个有意识的 datetime 对象。结果的 tzinfo 将设置为 timezone 实例。

  7. 当与 strptime() 方法一起使用时,%U%W 仅在指定星期几和日历年(%Y)的计算中使用。

  8. %U%W 类似,只有在 strptime() 格式字符串中指定星期和ISO年(%G)时,%V 才会用于计算。还要注意,%G%Y 不可互换。

脚注

[1]

如果,也就是说,我们忽略相对论的影响