datetime — 基本日期和时间类型

源代码: Lib/datetime.py


datetime 模块提供了用于操作日期和时间的类。

虽然支持日期和时间算术,但实现重点在于为输出格式化和操作提供高效的属性提取。

提示

跳到格式代码

另请参阅

模块calendar

通用的日历相关函数。

模块time

时间访问和转换。

模块zoneinfo

表示 IANA 时区数据库的具体时区。

dateutil

具有扩展时区和解析支持的第三方库。

DateType

引入不同的静态类型的第三方库,例如,允许静态类型检查器区分简单型和感知型日期时间。

感知型和简单型对象

日期和时间对象可以根据是否包含时区信息分为“感知型”或“简单型”。

凭借对适用的算法和政治时间调整(例如时区和夏令时信息)的充分了解,一个感知型对象可以相对于其他感知型对象定位自身。一个感知型对象表示一个特定的时间点,不容解释。[1]

一个简单型对象不包含足够的信息来明确地相对于其他日期/时间对象定位自身。一个简单型对象表示协调世界时 (UTC)、本地时间还是其他时区的时间,完全取决于程序,就像一个特定的数字表示米、英里还是质量取决于程序一样。简单型对象易于理解和使用,但代价是忽略了现实的某些方面。

对于需要感知型对象的应用程序,datetimetime 对象有一个可选的时区信息属性 tzinfo,可以将其设置为抽象 tzinfo 类的子类的实例。这些 tzinfo 对象捕获有关与 UTC 时间的偏移量、时区名称以及夏令时是否生效的信息。

datetime 模块只提供一个具体的 tzinfo 类,即 timezone 类。timezone 类可以表示与 UTC 具有固定偏移量的简单时区,例如 UTC 本身或北美 EST 和 EDT 时区。支持更深层次的详细时区取决于应用程序。世界各地的时间调整规则更多是政治性的而非理性的,并且经常变化,除了 UTC 之外,没有适合每个应用程序的标准。

常量

datetime 模块导出以下常量

datetime.MINYEAR

datedatetime 对象中允许的最小年份数字。MINYEAR 为 1。

datetime.MAXYEAR

datedatetime 对象中允许的最大年份数字。MAXYEAR 为 9999。

datetime.UTC

UTC 时区单例 datetime.timezone.utc 的别名。

在 3.11 版本中添加。

可用类型

class datetime.date

一个理想化的简单日期,假设当前的公历始终有效。属性:yearmonthday

class datetime.time

一个理想化的时间,独立于任何特定的日期,假设每天正好有 24*60*60 秒。(这里没有“闰秒”的概念。)属性:hour, minute, second, microsecond, 和 tzinfo

class datetime.datetime

日期和时间的组合。 属性:year, month, day, hour, minute, second, microsecond, 和 tzinfo

class datetime.timedelta

一个表示两个 datetimedate 实例之间的时间差,精确到微秒的分辨率。

class datetime.tzinfo

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

class datetime.timezone

一个实现了 tzinfo 抽象基类,作为与 UTC 的固定偏移量的类。

在版本 3.2 中添加。

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

子类关系

object
    timedelta
    tzinfo
        timezone
    time
    date
        datetime

常用属性

date, datetime, time, 和 timezone 类型共享这些共同的特性

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

  • 这些类型的对象是 可哈希的,这意味着它们可以被用作字典的键。

  • 这些类型的对象通过 pickle 模块支持高效的序列化。

确定对象是否为感知型或简单型

date 类型的对象始终是简单型的。

类型为 timedatetime 的对象可以是感知型或简单型的。

如果满足以下两个条件,则 datetime 对象 d 是感知型的

  1. d.tzinfo 不是 None

  2. d.tzinfo.utcoffset(d) 不返回 None

否则,d 是简单型的。

如果满足以下两个条件,则 time 对象 t 是感知型的

  1. t.tzinfo 不是 None

  2. t.tzinfo.utcoffset(None) 不返回 None

否则,t 是简单型的。

感知型和简单型之间的区别不适用于 timedelta 对象。

timedelta 对象

timedelta 对象表示一个时间段,即两个 datetimedate 实例之间的差值。

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

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

内部只存储天数秒数微秒数。参数会被转换为这些单位

  • 一毫秒转换为 1000 微秒。

  • 一分钟转换为 60 秒。

  • 一小时转换为 3600 秒。

  • 一周转换为 7 天。

然后对天数、秒数和微秒数进行标准化,以使表示是唯一的,其中

  • 0 <= microseconds < 1000000

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

  • -999999999 <= days <= 999999999

以下示例说明了除天数秒数微秒数之外的任何参数如何“合并”并标准化为这三个结果属性

>>> from datetime import timedelta
>>> delta = timedelta(
...     days=50,
...     seconds=27,
...     microseconds=10,
...     milliseconds=29000,
...     minutes=5,
...     hours=8,
...     weeks=2
... )
>>> # Only days, seconds, and microseconds remain
>>> delta
datetime.timedelta(days=64, seconds=29156, microseconds=10)

如果任何参数是浮点数并且存在小数微秒,则所有参数中剩余的小数微秒会合并,并且它们的总和会使用四舍五入到偶数的舍入方式舍入到最接近的微秒。如果没有参数是浮点数,则转换和标准化过程是精确的(不会丢失信息)。

如果天数的标准化值超出指示的范围,则会引发 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 对象。

实例属性(只读)

timedelta.days

介于 -999,999,999 和 999,999,999 之间(包括这两个值)。

timedelta.seconds

介于 0 和 86,399 之间,包含边界值。

注意

代码无意中使用此属性,而实际上是想获取 total_seconds() 值,这是一个很常见的错误。

>>> from datetime import timedelta
>>> duration = timedelta(seconds=11235813)
>>> duration.days, duration.seconds
(130, 3813)
>>> duration.total_seconds()
11235813.0
timedelta.microseconds

介于 0 和 999,999 之间,包含边界值。

支持的操作

操作

结果

t1 = t2 + t3

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

t1 = t2 - t3

t2t3 的差。之后 t1 == t2 - t3t2 == t1 + t3 为真。(1)(6)

t1 = t2 * i t1 = i * t2

Delta 乘以一个整数。之后,如果 i != 0,则 t1 // i == t2 为真。

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

t1 = t2 * f t1 = f * t2

Delta 乘以一个浮点数。结果使用四舍五入到偶数的规则舍入到 timedelta.resolution 的最接近倍数。

f = t2 / t3

用间隔单元 t3 除以总持续时间 t2 的除法 (3)。返回一个 float 对象。

t1 = t2 / f t1 = t2 / i

Delta 除以一个浮点数或整数。结果使用四舍五入到偶数的规则舍入到 timedelta.resolution 的最接近倍数。

t1 = t2 // it1 = t2 // t3

计算向下取整的值,并丢弃余数(如果有)。在第二种情况下,返回一个整数。(3)

t1 = t2 % t3

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

q, r = divmod(t1, t2)

计算商和余数:q = t1 // t2 (3) 和 r = t1 % t2q 是一个整数,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] 的字符串,其中 D 对于负数 t 为负数。(5)

repr(t)

返回 timedelta 对象的字符串表示形式,作为带有规范属性值的构造函数调用。

备注

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

  2. 这是精确的,不会溢出。

  3. 除以零会引发 ZeroDivisionError

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

  5. timedelta 对象的字符串表示形式与其内部表示形式类似地进行了规范化。这导致了负时间间隔的一些不寻常的结果。例如

    >>> timedelta(hours=-5)
    datetime.timedelta(days=-1, seconds=68400)
    >>> print(_)
    -1 day, 19:00:00
    
  6. 表达式 t2 - t3 将始终等于表达式 t2 + (-t3),除非 t3 等于 timedelta.max;在这种情况下,前者将产生结果,而后者将溢出。

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

在 3.2 版本中更改: 现在支持 timedelta 对象与另一个 timedelta 对象的向下取整除法和真除法,以及余数运算和 divmod() 函数。 现在支持 timedelta 对象与 float 对象的真除法和乘法。

timedelta 对象支持相等和顺序比较。

在布尔上下文中,当且仅当 timedelta 对象不等于 timedelta(0) 时,才将其视为 true。

实例方法

timedelta.total_seconds()

返回持续时间包含的总秒数。 等价于 td / timedelta(seconds=1)。 对于秒以外的间隔单位,请直接使用除法形式(例如,td / timedelta(microseconds=1))。

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

在版本 3.2 中添加。

用法示例: timedelta

规范化的其他示例

>>> # Components of another_year add up to exactly 365 days
>>> from datetime import timedelta
>>> year = timedelta(days=365)
>>> another_year = timedelta(weeks=40, days=84, hours=23,
...                          minutes=50, seconds=600)
>>> year == another_year
True
>>> year.total_seconds()
31536000.0

timedelta 算术示例

>>> from datetime import timedelta
>>> year = timedelta(days=365)
>>> ten_years = 10 * year
>>> ten_years
datetime.timedelta(days=3650)
>>> ten_years.days // 365
10
>>> nine_years = ten_years - year
>>> nine_years
datetime.timedelta(days=3285)
>>> three_years = nine_years // 3
>>> three_years, three_years.days // 365
(datetime.timedelta(days=1095), 3)

date 对象

date 对象表示理想日历中的日期(年、月和日),当前公历在两个方向上无限延伸。

1 年 1 月 1 日称为第 1 天,1 年 1 月 2 日称为第 2 天,依此类推。 [2]

class datetime.date(year, month, day)

所有参数都是必需的。参数必须是整数,并且在以下范围内

  • MINYEAR <= year <= MAXYEAR

  • 1 <= month <= 12

  • 1 <= day <= 给定月份和年份的天数

如果给定的参数超出这些范围,则会引发 ValueError 异常。

其他构造函数,均为类方法

classmethod date.today()

返回当前本地日期。

这等价于 date.fromtimestamp(time.time())

classmethod date.fromtimestamp(timestamp)

返回与 POSIX 时间戳对应的本地日期,例如 time.time() 返回的时间戳。

如果时间戳超出平台 C localtime() 函数支持的值范围,则可能引发 OverflowError 异常;在 localtime() 失败时,会引发 OSError 异常。 这通常限制在 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

classmethod date.fromisoformat(date_string)

返回与任何有效的 ISO 8601 格式给定的 date_string 对应的 date,但以下情况例外

  1. 目前不支持降低精度的日期 (YYYY-MM, YYYY)。

  2. 目前不支持扩展日期表示形式 (±YYYYYY-MM-DD)。

  3. 目前不支持序数日期 (YYYY-OOO)。

示例

>>> from datetime import date
>>> date.fromisoformat('2019-12-04')
datetime.date(2019, 12, 4)
>>> date.fromisoformat('20191204')
datetime.date(2019, 12, 4)
>>> date.fromisoformat('2021-W01-1')
datetime.date(2021, 1, 4)

3.7 版本中新增。

在 3.11 版本中更改: 以前,此方法仅支持 YYYY-MM-DD 格式。

classmethod date.fromisocalendar(year, week, day)

返回与 year、week 和 day 指定的 ISO 日历日期对应的 date。 这是函数 date.isocalendar() 的逆函数。

3.8 版本中新增。

类属性

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

date2 将是 date1 之后 timedelta.days 天的日期。(1)

date2 = date1 - timedelta

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

timedelta = date1 - date2

(3)

date1 == date2
date1 != date2

相等性比较。(4)

date1 < date2
date1 > date2
date1 <= date2
date1 >= date2

顺序比较。(5)

备注

  1. 如果 timedelta.days > 0,则 date2 在时间上向前移动;如果 timedelta.days < 0,则向后移动。之后,date2 - date1 == timedelta.days。 将忽略 timedelta.secondstimedelta.microseconds。 如果 date2.year 小于 MINYEAR 或大于 MAXYEAR,则会引发 OverflowError 异常。

  2. timedelta.secondstimedelta.microseconds 会被忽略。

  3. 这是精确的,不会溢出。timedelta.secondstimedelta.microseconds 为 0,之后 date2 + timedelta == date1

  4. 如果 date 对象表示同一日期,则它们相等。

    不是 datetime 实例的 date 对象永远不会与 datetime 对象相等,即使它们表示同一日期。

  5. date1 在时间上早于 date2 时,认为 date1 小于 date2。换句话说,当且仅当 date1.toordinal() < date2.toordinal() 时,date1 < date2

    将不是 datetime 实例的 date 对象与 datetime 对象进行顺序比较会引发 TypeError

3.13 版本更改: datetime 对象与不是 datetime 子类的 date 子类的实例之间的比较不再将后者转换为 date,从而忽略时间部分和时区。可以通过覆盖子类中的特殊比较方法来更改默认行为。

在布尔上下文中,所有 date 对象都被认为是 true。

实例方法

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

返回一个具有相同值的日期,但通过指定的关键字参数赋予新值的参数除外。

示例

>>> from datetime import date
>>> d = date(2002, 12, 31)
>>> d.replace(day=26)
datetime.date(2002, 12, 26)

通用函数 copy.replace() 也支持 date 对象。

date.timetuple()

返回一个 time.struct_time,如 time.localtime() 返回的那样。

小时、分钟和秒为 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()

返回一个具有三个组件的 命名元组 对象:yearweekweekday

ISO 日历是格里高利历的广泛使用的变体。[3]

ISO 年由 52 或 53 个整周组成,其中一周从星期一开始,到星期日结束。ISO 年的第一周是包含星期四的年份的第一个(格里高利)日历周。这被称为第 1 周,该星期四的 ISO 年份与其格里高利年份相同。

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

>>> from datetime import date
>>> date(2003, 12, 29).isocalendar()
datetime.IsoCalendarDate(year=2004, week=1, weekday=1)
>>> date(2004, 1, 4).isocalendar()
datetime.IsoCalendarDate(year=2004, week=1, weekday=7)

3.9 版本更改: 结果从元组更改为 命名元组

date.isoformat()

返回一个表示 ISO 8601 格式的日期的字符串,YYYY-MM-DD

>>> from datetime import date
>>> date(2002, 12, 4).isoformat()
'2002-12-04'
date.__str__()

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

date.ctime()

返回一个表示日期的字符串

>>> from datetime import date
>>> 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.isoformat()

date.__format__(format)

date.strftime() 相同。 这使得在 格式化字符串字面值 中以及使用 str.format() 时可以为 date 对象指定格式字符串。 另请参阅 strftime() 和 strptime() 的行为date.isoformat()

用法示例:date

计算事件天数的示例

>>> 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)

>>> # Methods related to formatting string output
>>> d.isoformat()
'2002-03-11'
>>> d.strftime("%d/%m/%y")
'11/03/02'
>>> d.strftime("%A %d. %B %Y")
'Monday 11. March 2002'
>>> d.ctime()
'Mon Mar 11 00:00:00 2002'
>>> 'The {1} is {0:%d}, the {2} is {0:%B}.'.format(d, "day", "month")
'The day is 11, the month is March.'

>>> # Methods for to extracting 'components' under different calendars
>>> 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 )

>>> # A date object is immutable; all operations produce a new object
>>> d.replace(year=2005)
datetime.date(2005, 3, 11)

datetime 对象

datetime 对象是一个包含来自 date 对象和 time 对象的所有信息的单一对象。

date 对象一样,datetime 假设当前公历在两个方向上都进行了扩展;与 time 对象一样,datetime 假设每天正好有 3600*24 秒。

构造函数

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

yearmonthday 参数是必需的。tzinfo 可以是 None,也可以是 tzinfo 子类的实例。 其余参数必须是以下范围内的整数

  • MINYEAR <= year <= MAXYEAR,

  • 1 <= month <= 12,

  • 1 <= day <= 给定月份和年份的天数,

  • 0 <= hour < 24,

  • 0 <= minute < 60,

  • 0 <= second < 60,

  • 0 <= microsecond < 1000000,

  • fold in [0, 1].

如果给定的参数超出这些范围,则会引发 ValueError 异常。

在 3.6 版本中更改: 添加了 fold 参数。

其他构造函数,均为类方法

classmethod datetime.today()

返回当前的本地日期和时间,其中 tzinfoNone

等效于

datetime.fromtimestamp(time.time())

另请参阅 now()fromtimestamp()

此方法在功能上等效于 now(),但没有 tz 参数。

classmethod datetime.now(tz=None)

返回当前的本地日期和时间。

如果可选参数 tzNone 或未指定,则此方法与 today() 类似,但如果可能,它会提供比从 time.time() 时间戳获得的更高的精度(例如,这在提供 C gettimeofday() 函数的平台上可能是可能的)。

如果 tz 不为 None,则它必须是 tzinfo 子类的实例,并且当前日期和时间将转换为 tz 的时区。

此函数优于 today()utcnow()

注意

根据底层时钟的精度,后续对 datetime.now() 的调用可能会返回相同的时刻。

classmethod datetime.utcnow()

返回当前的 UTC 日期和时间,其中 tzinfoNone

这与 now() 类似,但会返回当前的 UTC 日期和时间,作为朴素的 datetime 对象。 通过调用 datetime.now(timezone.utc) 可以获得感知当前 UTC datetime。 另请参阅 now()

警告

由于许多 datetime 方法将朴素的 datetime 对象视为本地时间,因此最好使用感知 datetime 来表示 UTC 中的时间。因此,创建表示当前 UTC 时间的对象的建议方法是调用 datetime.now(timezone.utc)

自 3.12 版本起已弃用: 请改用带 UTCdatetime.now()

classmethod datetime.fromtimestamp(timestamp, tz=None)

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

如果 tz 不为 None,则它必须是 tzinfo 子类的实例,并且时间戳将转换为 tz 的时区。

fromtimestamp() 方法可能会引发 OverflowError 异常,如果时间戳超出了平台 C localtime()gmtime() 函数支持的值范围;并且在 localtime()gmtime() 函数调用失败时会引发 OSError 异常。通常,这会被限制在 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() 函数支持的值范围,则此方法可能会引发 OverflowError 异常;并且在 gmtime() 函数调用失败时会引发 OSError 异常。通常,这会被限制在 1970 年到 2038 年之间的年份。

要获取感知时区的 datetime 对象,请调用 fromtimestamp() 方法。

datetime.fromtimestamp(timestamp, timezone.utc)

在符合 POSIX 标准的平台上,它等效于以下表达式:

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

但后一种公式始终支持完整的年份范围:包括 MINYEARMAXYEAR

警告

由于许多 datetime 方法将朴素的 datetime 对象视为本地时间,因此建议使用感知时区的 datetime 对象来表示 UTC 时间。 因此,创建表示 UTC 中特定时间戳的对象的推荐方法是调用 datetime.fromtimestamp(timestamp, tz=timezone.utc)

在 3.3 版本中变更: 如果时间戳超出了平台 C gmtime() 函数支持的值范围,则引发 OverflowError 异常,而不是 ValueError 异常。 在 gmtime() 函数调用失败时,则引发 OSError 异常,而不是 ValueError 异常。

自 3.12 版本起弃用: 请改用带有 UTCdatetime.fromtimestamp() 方法。

classmethod datetime.fromordinal(ordinal)

返回与前格里高利序数对应的 datetime 对象,其中 1 年 1 月 1 日的序数为 1。 除非 1 <= ordinal <= datetime.max.toordinal(),否则会引发 ValueError 异常。结果的小时、分钟、秒和微秒均为 0,并且 tzinfoNone

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

返回一个新的 datetime 对象,其日期部分等于给定的 date 对象的日期部分,其时间部分等于给定的 time 对象的时间部分。如果提供了 *tzinfo* 参数,则使用其值设置结果的 tzinfo 属性,否则使用 *time* 参数的 tzinfo 属性。如果 *date* 参数是一个 datetime 对象,则会忽略其时间部分和 tzinfo 属性。

对于任何 datetime 对象 dd == datetime.combine(d.date(), d.time(), d.tzinfo)

在 3.6 版本中变更: 添加了 *tzinfo* 参数。

classmethod datetime.fromisoformat(date_string)

返回与任何有效的 ISO 8601 格式的 *date_string* 对应的 datetime 对象,但以下情况除外:

  1. 时区偏移量可能包含小数秒。

  2. T 分隔符可以替换为任何单个 Unicode 字符。

  3. 不支持小数小时和分钟。

  4. 目前不支持降低精度的日期 (YYYY-MM, YYYY)。

  5. 目前不支持扩展日期表示形式 (±YYYYYY-MM-DD)。

  6. 目前不支持序数日期 (YYYY-OOO)。

示例

>>> from datetime import datetime
>>> datetime.fromisoformat('2011-11-04')
datetime.datetime(2011, 11, 4, 0, 0)
>>> datetime.fromisoformat('20111104')
datetime.datetime(2011, 11, 4, 0, 0)
>>> datetime.fromisoformat('2011-11-04T00:05:23')
datetime.datetime(2011, 11, 4, 0, 5, 23)
>>> datetime.fromisoformat('2011-11-04T00:05:23Z')
datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone.utc)
>>> datetime.fromisoformat('20111104T000523')
datetime.datetime(2011, 11, 4, 0, 5, 23)
>>> datetime.fromisoformat('2011-W01-2T00:05:23.283')
datetime.datetime(2011, 1, 4, 0, 5, 23, 283000)
>>> datetime.fromisoformat('2011-11-04 00:05:23.283')
datetime.datetime(2011, 11, 4, 0, 5, 23, 283000)
>>> datetime.fromisoformat('2011-11-04 00:05:23.283+00:00')
datetime.datetime(2011, 11, 4, 0, 5, 23, 283000, tzinfo=datetime.timezone.utc)
>>> datetime.fromisoformat('2011-11-04T00:05:23+04:00')   
datetime.datetime(2011, 11, 4, 0, 5, 23,
    tzinfo=datetime.timezone(datetime.timedelta(seconds=14400)))

3.7 版本中新增。

3.11 版本更改: 之前,此方法仅支持 date.isoformat()datetime.isoformat() 可以发出的格式。

classmethod datetime.fromisocalendar(year, week, day)

返回一个 datetime 对象,该对象对应于由 year、week 和 day 指定的 ISO 日历日期。datetime 的非日期组件将使用其正常的默认值填充。 这是函数 datetime.isocalendar() 的逆运算。

3.8 版本中新增。

classmethod datetime.strptime(date_string, format)

返回一个 datetime 对象,该对象对应于根据 *format* 解析的 *date_string*。

如果 *format* 不包含微秒或时区信息,则这等效于

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

如果 time.strptime() 无法解析 *date_string* 和 *format*,或者它返回的值不是时间元组,则会引发 ValueError。另请参阅 strftime() 和 strptime() 的行为 以及 datetime.fromisoformat()

3.13 版本更改: 如果 *format* 指定了没有年份的月份日期,现在会发出 DeprecationWarning。这是为了避免代码中寻求仅解析月份和日期时出现四年一次的闰年错误,因为格式中缺少年份时使用的默认年份不是闰年。 从 Python 3.15 开始,此类 *format* 值可能会引发错误。解决方法是在你的 *format* 中始终包含年份。如果解析没有年份的 *date_string* 值,请在解析之前显式添加一个闰年年份

>>> from datetime import datetime
>>> date_string = "02/29"
>>> when = datetime.strptime(f"{date_string};1984", "%m/%d;%Y")  # Avoids leap year bug.
>>> when.strftime("%B %d")  
'February 29'

类属性

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
datetime1 != datetime2

相等性比较。(4)

datetime1 < datetime2
datetime1 > datetime2
datetime1 <= datetime2
datetime1 >= datetime2

顺序比较。(5)

  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。与加法一样,结果具有与输入 datetime 相同的 tzinfo 属性,并且即使输入是感知的,也不会进行时区调整。

  3. 只有当两个操作数都是朴素的,或者都是感知的时,才定义从 datetime 中减去 datetime。如果一个是感知的而另一个是朴素的,则会引发 TypeError

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

    如果两者都是 aware 且具有不同的 tzinfo 属性,则 a-b 的行为就像 ab 首先被转换为 naive UTC datetime 一样。结果是 (a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset()),但实现永远不会溢出。

  4. 如果 datetime 对象表示相同的日期和时间(考虑到时区),则它们是相等的。

    Naive 和 aware 的 datetime 对象永远不相等。

    如果两个比较对象都是 aware,并且具有相同的 tzinfo 属性,则会忽略 tzinfofold 属性,并比较基本 datetime。如果两个比较对象都是 aware 且具有不同的 tzinfo 属性,则比较行为就像比较对象首先被转换为 UTC datetime 一样,但实现永远不会溢出。重复间隔中的 datetime 实例永远不等于其他时区中的 datetime 实例。

  5. datetime1 在时间上早于 datetime2 时(考虑到时区),则认为 datetime1 小于 datetime2

    Naive 和 aware 的 datetime 对象之间的顺序比较会引发 TypeError

    如果两个比较对象都是 aware,并且具有相同的 tzinfo 属性,则会忽略 tzinfofold 属性,并比较基本 datetime。如果两个比较对象都是 aware 且具有不同的 tzinfo 属性,则比较行为就像比较对象首先被转换为 UTC datetime 一样,但实现永远不会溢出。

在 3.3 版本中更改: aware 和 naive 的 datetime 实例之间的相等性比较不会引发 TypeError

3.13 版本更改: datetime 对象与不是 datetime 子类的 date 子类的实例之间的比较不再将后者转换为 date,从而忽略时间部分和时区。可以通过覆盖子类中的特殊比较方法来更改默认行为。

实例方法

datetime.date()

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

datetime.time()

返回具有相同的小时、分钟、秒、微秒和 fold 的 time 对象。tzinfoNone。另请参阅方法 timetz()

在 3.6 版本中更改: fold 值被复制到返回的 time 对象中。

datetime.timetz()

返回具有相同的小时、分钟、秒、微秒、fold 和 tzinfo 属性的 time 对象。另请参阅方法 time()

在 3.6 版本中更改: fold 值被复制到返回的 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 以从 aware datetime 创建 naive datetime,而无需转换日期和时间数据。

datetime 对象也受通用函数 copy.replace() 支持。

在 3.6 版本中更改: 添加了 fold 参数。

datetime.astimezone(tz=None)

返回一个新的 datetime 对象,其具有新的 tzinfo 属性 tz,并调整日期和时间数据,以使结果与 self 具有相同的 UTC 时间,但采用 tz 的本地时间。

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

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

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

如果只想将 timezone 对象 tz 附加到 datetime dt,而无需调整日期和时间数据,请使用 dt.replace(tzinfo=tz)。如果只想从 aware datetime dt 中删除 timezone 对象,而无需转换日期和时间数据,请使用 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 timezone 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 对象,则引发异常。

在 3.7 版本中变更:UTC 偏移量不再限制为整数分钟。

datetime.dst()

如果 tzinfoNone,则返回 None,否则返回 self.tzinfo.dst(self),如果后者没有返回 None 或一个幅度小于一天的 timedelta 对象,则引发异常。

在 3.7 版本中变更:DST 偏移量不再限制为整数分钟。

datetime.tzname()

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

datetime.timetuple()

返回一个 time.struct_time,如 time.localtime() 返回的那样。

d.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.yearMINYEARMAXYEAR 且 UTC 调整溢出年份边界,则可能会引发 OverflowError

警告

由于许多 datetime 方法将朴素的 datetime 对象视为本地时间,因此最好使用感知的日期时间来表示 UTC 时间;因此,使用 datetime.utctimetuple() 可能会给出误导性的结果。如果您有一个表示 UTC 的朴素 datetime,请使用 datetime.replace(tzinfo=timezone.utc) 使其感知,此时您可以使用 datetime.timetuple()

datetime.toordinal()

返回日期的普罗勒普提格里高利序号。与 self.date().toordinal() 相同。

datetime.timestamp()

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

假定朴素的 datetime 实例代表本地时间,并且此方法依赖于平台 C mktime() 函数来执行转换。由于 datetime 支持比许多平台上的 mktime() 更广泛的值范围,因此对于过去或将来很远的时间,此方法可能会引发 OverflowErrorOSError

对于感知的 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()

返回一个包含三个组件的命名元组year, weekweekday。与 self.date().isocalendar() 相同。

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

返回一个以 ISO 8601 格式表示日期和时间的字符串

如果 utcoffset() 不返回 None,则会附加一个字符串,给出 UTC 偏移量

  • YYYY-MM-DDTHH:MM:SS.ffffff+HH:MM[:SS[.ffffff]], 如果 microsecond 不为 0

  • YYYY-MM-DDTHH:MM:SS+HH:MM[:SS[.ffffff]], 如果 microsecond 为 0

示例

>>> from datetime import datetime, timezone
>>> datetime(2019, 5, 18, 15, 17, 8, 132263).isoformat()
'2019-05-18T15:17:08.132263'
>>> datetime(2019, 5, 18, 15, 17, tzinfo=timezone.utc).isoformat()
'2019-05-18T15:17:00+00:00'

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

>>> from datetime import tzinfo, timedelta, datetime
>>> class TZ(tzinfo):
...     """A time zone with an arbitrary, constant -06:39 offset."""
...     def utcoffset(self, dt):
...         return timedelta(hours=-6, minutes=-39)
...
>>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ')
'2002-12-25 00:00:00-06:39'
>>> datetime(2009, 11, 27, microsecond=100, tzinfo=TZ()).isoformat()
'2009-11-27T00:00:00.000100-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.ffffff 格式包括完整时间。

注意

排除的时间组成部分被截断,而不是四舍五入。

如果 timespec 参数无效,则会引发 ValueError

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

返回表示日期和时间的字符串

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

datetime.__format__(format)

datetime.strftime() 相同。这使得可以在格式化字符串字面值中和使用 str.format() 时为 datetime 对象指定格式字符串。另请参阅 strftime() 和 strptime() 行为 以及 datetime.isoformat()

用法示例:datetime

使用 datetime 对象的示例

>>> from datetime import datetime, date, time, timezone

>>> # 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()
>>> datetime.now()   
datetime.datetime(2007, 12, 6, 16, 29, 43, 79043)   # GMT +1
>>> datetime.now(timezone.utc)   
datetime.datetime(2007, 12, 6, 15, 29, 43, 79060, tzinfo=datetime.timezone.utc)

>>> # 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 a 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 子类,用于捕获阿富汗喀布尔的时区信息,该子类在 1945 年之前使用 +4 UTC,之后使用 +4:30 UTC

from datetime import timedelta, datetime, tzinfo, timezone

class KabulTz(tzinfo):
    # Kabul used +4 until 1945, when they moved to +4:30
    UTC_MOVE_DATE = datetime(1944, 12, 31, 20, tzinfo=timezone.utc)

    def utcoffset(self, dt):
        if dt.year < 1945:
            return timedelta(hours=4)
        elif (1945, 1, 1, 0, 0) <= dt.timetuple()[:5] < (1945, 1, 1, 0, 30):
            # An ambiguous ("imaginary") half-hour range representing
            # a 'fold' in time due to the shift from +4 to +4:30.
            # If dt falls in the imaginary range, use fold to decide how
            # to resolve. See PEP495.
            return timedelta(hours=4, minutes=(30 if dt.fold else 0))
        else:
            return timedelta(hours=4, minutes=30)

    def fromutc(self, dt):
        # Follow same validations as in datetime.tzinfo
        if not isinstance(dt, datetime):
            raise TypeError("fromutc() requires a datetime argument")
        if dt.tzinfo is not self:
            raise ValueError("dt.tzinfo is not self")

        # A custom implementation is required for fromutc as
        # the input to this function is a datetime with utc values
        # but with a tzinfo set to self.
        # See datetime.astimezone or fromtimestamp.
        if dt.replace(tzinfo=timezone.utc) >= self.UTC_MOVE_DATE:
            return dt + timedelta(hours=4, minutes=30)
        else:
            return dt + timedelta(hours=4)

    def dst(self, dt):
        # Kabul does not observe daylight saving time.
        return timedelta(0)

    def tzname(self, dt):
        if dt >= self.UTC_MOVE_DATE:
            return "+04:30"
        return "+04"

上面 KabulTz 的用法

>>> tz1 = KabulTz()

>>> # Datetime before the change
>>> dt1 = datetime(1900, 11, 21, 16, 30, tzinfo=tz1)
>>> print(dt1.utcoffset())
4:00:00

>>> # Datetime after the change
>>> dt2 = datetime(2006, 6, 14, 13, 0, tzinfo=tz1)
>>> print(dt2.utcoffset())
4:30:00

>>> # Convert datetime to another time zone
>>> dt3 = dt2.astimezone(timezone.utc)
>>> dt3
datetime.datetime(2006, 6, 14, 8, 30, tzinfo=datetime.timezone.utc)
>>> dt2
datetime.datetime(2006, 6, 14, 13, 0, tzinfo=KabulTz())
>>> dt2 == dt3
True

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

如果给出的参数超出这些范围,则会引发 ValueError。所有参数的默认值都为 0,除了 tzinfo,其默认值为 None

类属性

time.min

最早可表示的 timetime(0, 0, 0, 0)

time.max

最新的可表示的 time,即 time(23, 59, 59, 999999)

time.resolution

不相等的 time 对象之间最小的可能差异,即 timedelta(microseconds=1),但请注意,不支持对 time 对象进行算术运算。

实例属性(只读)

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 版本新增。

time 对象支持相等和顺序比较,其中当 a 在时间上早于 b 时,则认为 a 小于 b

朴素(Naive)和感知(Aware)的 time 对象永远不相等。 朴素和感知的 time 对象之间的顺序比较会引发 TypeError

如果两个比较对象都是感知的,并且具有相同的 tzinfo 属性,则忽略 tzinfofold 属性,并比较基本时间。如果两个比较对象都是感知的,并且具有不同的 tzinfo 属性,则首先通过减去它们的 UTC 偏移量(从 self.utcoffset() 获取)来调整比较对象。

在 3.3 版本中更改: 感知和朴素 time 实例之间的相等比较不会引发 TypeError

在布尔上下文中,time 对象始终被视为 true。

在 3.5 版本中更改: 在 Python 3.5 之前,如果 time 对象表示 UTC 午夜,则会被视为 false。此行为被认为是晦涩难懂且容易出错的,已在 Python 3.5 中删除。有关完整详细信息,请参阅 bpo-13936

其他构造函数

classmethod time.fromisoformat(time_string)

返回与任何有效的 ISO 8601 格式的 time_string 对应的 time,但有以下例外:

  1. 时区偏移量可能包含小数秒。

  2. 在日期和时间之间可能存在歧义的情况下,通常需要的开头 T 是不需要的。

  3. 小数秒可以有任意位数(超过 6 位的任何位数都将被截断)。

  4. 不支持小数小时和分钟。

示例

>>> from datetime import time
>>> time.fromisoformat('04:23:01')
datetime.time(4, 23, 1)
>>> time.fromisoformat('T04:23:01')
datetime.time(4, 23, 1)
>>> time.fromisoformat('T042301')
datetime.time(4, 23, 1)
>>> time.fromisoformat('04:23:01.000384')
datetime.time(4, 23, 1, 384)
>>> time.fromisoformat('04:23:01,000384')
datetime.time(4, 23, 1, 384)
>>> time.fromisoformat('04:23:01+04:00')
datetime.time(4, 23, 1, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400)))
>>> time.fromisoformat('04:23:01Z')
datetime.time(4, 23, 1, tzinfo=datetime.timezone.utc)
>>> time.fromisoformat('04:23:01+00:00')
datetime.time(4, 23, 1, tzinfo=datetime.timezone.utc)

3.7 版本中新增。

在 3.11 版本中更改: 以前,此方法仅支持可以由 time.isoformat() 发出的格式。

实例方法

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

返回一个具有相同值的 time,但由指定的任何关键字参数赋予新值的属性除外。请注意,可以指定 tzinfo=None 从一个感知的 time 创建一个朴素的 time,而无需转换时间数据。

time 对象也受通用函数 copy.replace() 支持。

在 3.6 版本中更改: 添加了 fold 参数。

time.isoformat(timespec='auto')

返回一个以 ISO 8601 格式表示时间的字符串,以下之一:

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

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

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

  • 'minutes':以 HH:MM 格式包含 hourminute

  • 'seconds':包括 hourminutesecond,格式为 HH:MM:SS

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

  • 'microseconds': 以 HH:MM:SS.ffffff 格式包括完整时间。

注意

排除的时间组成部分被截断,而不是四舍五入。

如果 timespec 参数无效,将引发 ValueError 异常。

示例

>>> 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__()

对于时间 tstr(t) 等同于 t.isoformat()

time.strftime(format)

返回一个字符串,表示由显式格式字符串控制的时间。另请参阅 strftime() 和 strptime() 的行为time.isoformat()

time.__format__(format)

time.strftime() 相同。 这使得可以在 格式化字符串字面值 中以及使用 str.format() 时为 time 对象指定格式字符串。另请参阅 strftime() 和 strptime() 的行为time.isoformat()

time.utcoffset()

如果 tzinfoNone,则返回 None,否则返回 self.tzinfo.utcoffset(None),如果后者没有返回 None 或一个大小小于一天的 timedelta 对象,则会引发异常。

在 3.7 版本中变更:UTC 偏移量不再限制为整数分钟。

time.dst()

如果 tzinfoNone,则返回 None,否则返回 self.tzinfo.dst(None),如果后者没有返回 None,或者返回一个大小小于一天的 timedelta 对象,则会引发异常。

在 3.7 版本中变更:DST 偏移量不再限制为整数分钟。

time.tzname()

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

用法示例:time

使用 time 对象的示例

>>> from datetime import time, tzinfo, timedelta
>>> class TZ1(tzinfo):
...     def utcoffset(self, dt):
...         return timedelta(hours=1)
...     def dst(self, dt):
...         return timedelta(0)
...     def tzname(self,dt):
...         return "+01:00"
...     def  __repr__(self):
...         return f"{self.__class__.__name__}()"
...
>>> t = time(12, 10, 30, tzinfo=TZ1())
>>> t
datetime.time(12, 10, 30, tzinfo=TZ1())
>>> t.isoformat()
'12:10:30+01:00'
>>> t.dst()
datetime.timedelta(0)
>>> t.tzname()
'+01:00'
>>> t.strftime("%H:%M:%S %Z")
'12:10:30 +01:00'
>>> 'The {} is {:%H:%M}.'.format("time", t)
'The time is 12:10.'

tzinfo 对象

class datetime.tzinfo

这是一个抽象基类,这意味着不应直接实例化此类。定义 tzinfo 的子类,以捕获有关特定时区的信息。

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

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

pickling 的特殊要求: tzinfo 子类必须有一个可以使用无参数调用的 __init__() 方法,否则可以对其进行 pickled 处理,但可能无法再次 unpickled。这是一项技术要求,将来可能会放宽。

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

tzinfo.utcoffset(dt)

返回本地时间与 UTC 的偏移量,以 timedelta 对象的形式返回,该对象在 UTC 东边为正值。如果本地时间位于 UTC 西边,则该值应为负值。

这表示与 UTC 的偏移量; 例如,如果 tzinfo 对象表示时区和 DST 调整,则 utcoffset() 应该返回它们的总和。如果 UTC 偏移量未知,则返回 None。 否则,返回的值必须是一个 timedelta 对象,其值严格介于 -timedelta(hours=24)timedelta(hours=24) 之间(偏移量的大小必须小于一天)。 大多数 utcoffset() 的实现可能类似于以下两种之一

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

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

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

在 3.7 版本中变更:UTC 偏移量不再限制为整数分钟。

tzinfo.dst(dt)

返回夏令时 (DST) 调整,以 timedelta 对象的形式返回,如果 DST 信息未知,则返回 None

如果夏令时未生效,则返回 timedelta(0)。如果夏令时生效,则返回偏移量,类型为 timedelta 对象(详见 utcoffset())。请注意,夏令时偏移量(如果适用)已添加到 utcoffset() 返回的 UTC 偏移量中,因此无需查询 dst(),除非您想单独获取夏令时信息。例如,datetime.timetuple() 会调用其 tzinfo 属性的 dst() 方法,以确定应如何设置 tm_isdst 标志,并且 tzinfo.fromutc() 会调用 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.

    if dston <= dt.replace(tzinfo=None) < dstoff:
        return timedelta(hours=1)
    else:
        return timedelta(0)

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

在 3.7 版本中变更:DST 偏移量不再限制为整数分钟。

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 子类的方法应准备好接受 dt 参数为 Nonedatetime 类。

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

当为了响应 datetime 方法而传递 datetime 对象时,dt.tzinfoself 是同一个对象。tzinfo 方法可以依赖于此,除非用户代码直接调用 tzinfo 方法。其目的是 tzinfo 方法将 dt 解释为本地时间,而无需担心其他时区的对象。

还有一个 tzinfo 方法,子类可能希望重写:

tzinfo.fromutc(dt)

这是从默认的 datetime.astimezone() 实现中调用的。当从该方法调用时,dt.tzinfoself,并且 dt 的日期和时间数据应视为表达 UTC 时间。fromutc() 的目的是调整日期和时间数据,返回 self 本地时间中等效的 datetime。

大多数 tzinfo 子类应该能够毫无问题地继承默认的 fromutc() 实现。它足够强大,可以处理固定偏移时区,以及同时考虑标准时间和夏令时的时区,即使不同年份的夏令时转换时间不同也是如此。默认的 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_examples.py 文件中,有一些关于 tzinfo 类的示例。

from datetime import tzinfo, timedelta, datetime

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
# https://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")

请注意,在考虑标准时间和夏令时的 tzinfo 子类中,每年在夏令时转换点会不可避免地出现两次细微差别。为了具体起见,考虑美国东部时间(UTC-0500),其中夏令时在三月第二个星期日的 1:59 (EST) 之后开始,并在十一月第一个星期日的 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

当夏令时开始(“开始”行)时,本地时间会从 1:59 跳到 3:00。形式为 2:MM 的本地时间在那一天实际上没有意义,因此 astimezone(Eastern) 不会在夏令时开始的当天产生 hour == 2 的结果。例如,在 2016 年的春季前进转换时,我们得到:

>>> from datetime import datetime, timezone
>>> from tzinfo_examples import HOUR, Eastern
>>> 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

当夏令时结束(“结束”行)时,可能会出现更严重的问题:在本地时间中,有一个小时无法明确表达,即夏令时的最后一个小时。在东部时间,这是夏令时结束当天的形式为 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

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

无法忍受本地时间歧义的应用程序应显式检查 fold 属性的值,或避免使用混合的 tzinfo 子类;当使用 timezone 或任何其他固定偏移量的 tzinfo 子类时(例如,仅表示 EST(固定偏移 -5 小时)或仅表示 EDT(固定偏移 -4 小时)的类),不会出现歧义。

另请参阅

zoneinfo

datetime 模块具有基本的 timezone 类(用于处理来自 UTC 的任意固定偏移量)及其 timezone.utc 属性(一个 UTC timezone 实例)。

zoneinfoIANA 时区数据库(也称为 Olson 数据库)引入 Python,建议使用它。

IANA 时区数据库

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

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 中添加。

在 3.7 版本中变更:UTC 偏移量不再限制为整数分钟。

timezone.utcoffset(dt)

返回构造 timezone 实例时指定的固定值。

dt 参数被忽略。返回值是 timedelta 实例,等于本地时间与 UTC 之间的差异。

在 3.7 版本中变更:UTC 偏移量不再限制为整数分钟。

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 参数必须是具有 tzinfo 设置为 self 的感知 datetime 实例。

类属性

timezone.utc

UTC 时区,timezone(timedelta(0))

strftime()strptime() 行为

datedatetimetime 对象都支持 strftime(format) 方法,以创建在显式格式字符串控制下表示时间的字符串。

相反, datetime.strptime() 类方法根据表示日期和时间的字符串和相应的格式字符串创建一个 datetime 对象。

下表提供了 strftime()strptime() 的高级比较

strftime

strptime

用法

根据给定的格式将对象转换为字符串

根据相应的格式将字符串解析为 datetime 对象。

方法类型

实例方法

类方法

所属方法

date; datetime; time

datetime

签名

strftime(format)

strptime(date_string, format)

strftime()strptime() 格式代码

这些方法接受格式代码,可用于解析和格式化日期。

>>> datetime.strptime('31/01/22 23:59:59.999999',
...                   '%d/%m/%y %H:%M:%S.%f')
datetime.datetime(2022, 1, 31, 23, 59, 59, 999999)
>>> _.strftime('%a %d %b %Y, %I:%M%p')
'Mon 31 Jan 2022, 11:59PM'

以下是 1989 C 标准要求的所有格式代码的列表,这些代码在所有具有标准 C 实现的平台上都能工作。

指令

含义

示例

备注

%a

以区域设置的缩写形式表示星期几。

Sun, Mon, …, Sat (en_US);
So, Mo, …, Sa (de_DE)

(1)

%A

以区域设置的全名表示星期几。

Sunday, Monday, …, Saturday (en_US);
Sonntag, Montag, …, Samstag (de_DE)

(1)

%w

以十进制数字表示星期几,其中 0 表示星期日,6 表示星期六。

0, 1, …, 6

%d

以零填充的十进制数字表示月份中的第几天。

01, 02, …, 31

(9)

%b

以区域设置的缩写形式表示月份。

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

(1)

%B

以区域设置的全名表示月份。

January, February, …, December (en_US);
Januar, Februar, …, Dezember (de_DE)

(1)

%m

以零填充的十进制数字表示月份。

01, 02, …, 12

(9)

%y

以零填充的十进制数字表示不带世纪的年份。

00, 01, …, 99

(9)

%Y

以十进制数字表示带世纪的年份。

0001, 0002, …, 2013, 2014, …, 9998, 9999

(2)

%H

以零填充的十进制数字表示小时(24 小时制)。

00, 01, …, 23

(9)

%I

以零填充的十进制数字表示小时(12 小时制)。

01, 02, …, 12

(9)

%p

区域设置中与 AM 或 PM 等效的表示。

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

(1), (3)

%M

以零填充的十进制数字表示分钟。

00, 01, …, 59

(9)

%S

以零填充的十进制数字表示秒。

00, 01, …, 59

(4), (9)

%f

以十进制数字表示微秒,零填充至 6 位。

000000, 000001, …, 999999

(5)

%z

±HHMM[SS[.ffffff]] 格式表示 UTC 偏移量(如果对象是 naive,则为空字符串)。

(empty), +0000, -0400, +1030, +063415, -030712.345216

(6)

%Z

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

(empty), UTC, GMT

(6)

%j

以零填充的十进制数字表示一年中的第几天。

001, 002, …, 366

(9)

%U

以零填充的十进制数字表示一年中的周数(星期日为一周的第一天)。 新年中第一个星期日之前的所有天数都视为第 0 周。

00, 01, …, 53

(7), (9)

%W

以零填充的十进制数字表示一年中的周数(星期一为一周的第一天)。 新年中第一个星期一之前的所有天数都视为第 0 周。

00, 01, …, 53

(7), (9)

%c

区域设置的适当日期和时间表示。

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

(1)

%x

区域设置的适当日期表示。

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

(1)

%X

区域设置的适当时间表示。

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

(1)

%%

文字字符 '%'

%

为了方便起见,还包括了 C89 标准未要求的其他几个指令。 这些参数都对应于 ISO 8601 日期值。

指令

含义

示例

备注

%G

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

0001, 0002, …, 2013, 2014, …, 9998, 9999

(8)

%u

以十进制数字表示 ISO 8601 星期几,其中 1 表示星期一。

1, 2, …, 7

%V

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

01, 02, …, 53

(8), (9)

%:z

±HH:MM[:SS[.ffffff]] 格式表示 UTC 偏移量(如果对象是 naive,则为空字符串)。

(empty), +00:00, -04:00, +10:30, +06:34:15, -03:07:12.345216

(6)

strftime() 方法一起使用时,这些方法可能并非在所有平台上都可用。 ISO 8601 年份和 ISO 8601 周指令与上面的年份和周数指令不可互换。 调用带有不完整或不明确的 ISO 8601 指令的 strptime() 会引发 ValueError

支持的完整格式代码集因平台而异,因为 Python 调用平台 C 库的 strftime() 函数,并且平台差异很常见。 要查看平台上支持的完整格式代码集,请查阅 strftime(3) 文档。 在处理不受支持的格式说明符时,平台之间也存在差异。

3.6 版本中新增: 添加了 %G%u%V

3.12 版本中新增: 添加了 %:z

技术细节

广义而言,d.strftime(fmt) 的行为类似于 time 模块的 time.strftime(fmt, d.timetuple()),尽管并非所有对象都支持 timetuple() 方法。

对于 datetime.strptime() 类方法,默认值为 1900-01-01T00:00:00.000:格式字符串中未指定的任何组件都将从默认值中提取。 [4]

使用 datetime.strptime(date_string, format) 等效于

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

除非格式包含亚秒级组件或时区偏移量信息,这些信息在 datetime.strptime 中受支持,但在 time.strptime 中会被丢弃。

对于 time 对象,不应使用年、月和日的格式代码,因为 time 对象没有这些值。 如果仍然使用,则年份将替换为 1900,月份和日期将替换为 1。

对于 date 对象,不应使用小时、分钟、秒和微秒的格式代码,因为 date 对象没有这些值。 如果仍然使用,则将它们替换为 0。

出于同样的原因,处理包含当前区域设置字符集中无法表示的 Unicode 代码点的格式字符串也取决于平台。 在某些平台上,此类代码点在输出中完整保留,而在其他平台上,strftime 可能会引发 UnicodeError 或返回空字符串。

备注

  1. 由于格式取决于当前区域设置,因此在对输出值进行假设时应格外小心。 字段顺序会有所不同(例如,“月/日/年”与“日/月/年”),并且输出可能包含非 ASCII 字符。

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

    在 3.2 版本中更改: 在以前的版本中,strftime() 方法仅限于 >= 1900 的年份。

    在 3.3 版本中更改: 在 3.2 版本中,strftime() 方法仅限于 >= 1000 的年份。

  3. 当与 strptime() 方法一起使用时,%p 指令仅在使用 %I 指令解析小时时才会影响输出的小时字段。

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

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

  6. 对于朴素对象,%z%:z%Z 格式代码将替换为空字符串。

    对于感知对象

    %z

    utcoffset() 被转换为 ±HHMM[SS[.ffffff]] 形式的字符串,其中 HH 是一个 2 位字符串,表示 UTC 偏移小时数,MM 是一个 2 位字符串,表示 UTC 偏移分钟数,SS 是一个 2 位字符串,表示 UTC 偏移秒数,ffffff 是一个 6 位字符串,表示 UTC 偏移微秒数。当偏移量为整数秒时,将省略 ffffff 部分;当偏移量为整数分钟时,将省略 ffffffSS 部分。例如,如果 utcoffset() 返回 timedelta(hours=-3, minutes=-30),则 %z 将被替换为字符串 '-0330'

    在 3.7 版本中变更:UTC 偏移量不再限制为整数分钟。

    在 3.7 版本中更改: 当向 strptime() 方法提供 %z 指令时,UTC 偏移量的小时、分钟和秒之间可以使用冒号作为分隔符。例如,'+01:00:00' 将被解析为一小时的偏移量。此外,提供 'Z''+00:00' 相同。

    %:z

    行为与 %z 完全相同,但小时、分钟和秒之间添加了冒号分隔符。

    %Z

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

    strptime() 仅接受 %Z 的某些值

    1. 您的机器区域设置中 time.tzname 中的任何值

    2. 硬编码的值 UTCGMT

    因此,住在日本的人可能会将 JSTUTCGMT 作为有效值,但可能不包括 EST。对于无效值,它将引发 ValueError

    在 3.2 版本中更改: 当向 strptime() 方法提供 %z 指令时,将生成一个感知 datetime 对象。结果的 tzinfo 将被设置为 timezone 实例。

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

  8. %U%W 类似,%V 仅在 strptime() 格式字符串中指定星期几和 ISO 年份 (%G) 时才在计算中使用。另请注意,%G%Y 不可互换。

  9. 当与 strptime() 方法一起使用时,对于格式 %d%m%H%I%M%S%j%U%W%V,前导零是可选的。格式 %y 需要前导零。

  10. 当使用 strptime() 解析月份和日期时,请始终在格式中包含年份。如果您需要解析的值缺少年份,请附加一个显式的虚拟闰年。否则,您的代码在遇到闰日时会引发异常,因为解析器使用的默认年份不是闰年。用户每四年都会遇到此错误……

    >>> month_day = "02/29"
    >>> datetime.strptime(f"{month_day};1984", "%m/%d;%Y")  # No leap year bug.
    datetime.datetime(1984, 2, 29, 0, 0)
    

    在 3.13 版本中已弃用,将在 3.15 版本中移除: 使用包含没有年份的月份日期格式字符串调用 strptime() 现在会发出 DeprecationWarning。在 3.15 或更高版本中,我们可能会将其更改为错误,或者将默认年份更改为闰年。请参阅 gh-70647

脚注