datetime
—- 基本日期和时间类型
源代码: Lib/datetime.py [https://github.com/python/cpython/tree/3.13/Lib/datetime.py]
datetime
模块提供了用于操作日期和时间的类。
在支持日期时间数学运算的同时,实现的关注点更着重于如何能够更有效地解析其属性用于格式化输出和数据操作。
小技巧
跳到 格式代码。
参见
- 模块
calendar
通用日历相关函数
模块
time
时间的访问和转换
zoneinfo
模块代表 IANA 时区数据库的具体时区。
具有扩展时区和解析支持的第三方库。
- 引入了几种独特的静态类型的第三方库,例如允许 静态类型检查器 区分简单型和感知型日期时间。
感知型对象和简单型对象
日期和时间对象可以根据它们是否包含时区信息而分为“感知型”和“简单型”两类。
充分掌握应用性算法和政治性时间调整信息例如时区和夏令时的情况下,一个 感知型 对象就能相对于其他感知型对象来精确定位自身时间点。 感知型对象是用来表示一个没有解释空间的固定时间点。 [1]
简单型 对象没有包含足够多的信息来无歧义地相对于其他 date/time 对象来定位自身时间点。 不论一个简单型对象所代表的是世界标准时间(UTC)、当地时间还是某个其他时区的时间完全取决于具体程序,就像一个特定数字所代表的是米、英里还是质量完全取决于具体程序一样。 简单型对象更易于理解和使用,代价则是忽略了某些现实性考量。
对于要求感知型对象的应用,datetime
和 time
对象具有一个可选的时区信息属性 tzinfo
,它可被设为抽象类 tzinfo
的子类的一个实例。 这些 tzinfo
对象会捕获与 UTC 时间的差值、时区名称以及夏令时是否生效等信息。
datetime
模块只提供了一个具体的 tzinfo
类,即 timezone
类。 timezone
类可以表示具有相对于 UTC 的固定时差的简单时区,例如 UTC 本身或北美 EST 和 EDT 时区等。 支持时区的详细程度取决于具体的应用。 世界各地的时间调整规则往往是政治性多于合理性,经常会发生变化,除了 UTC 之外并没有一个能适合所有应用的标准。
常量
datetime
模块导出了以下常量:
- datetime.UTC
- UTC 时区单例
datetime.timezone.utc
的别名。
Added in version 3.11.
有效的类型
- class datetime.time
- 一个独立于任何特定日期的理想化时间,它假设每一天都恰好等于 246060 秒。 (这里没有“闰秒”的概念。) 包含属性:
hour
,minute
,second
,microsecond
和tzinfo
。
- class datetime.datetime
- 日期和时间的结合。属性:
year
,month
,day
,hour
,minute
,second
,microsecond
, andtzinfo
.
- class datetime.timezone
- 一个实现了
tzinfo
抽象基类的子类,用于表示相对于 世界标准时间(UTC)的偏移量。
Added in version 3.2.
这些类型的对象都是不可变的。
子类关系
- object
- timedelta
- tzinfo
- timezone
- time
- date
- datetime
通用的特征属性
date
, datetime
, time
和 timezone
类型共享这些通用特性:
确定一个对象是感知型还是简单型
date
类型的对象都是简单型的。
time
或 datetime
类型的对象可以是感知型或者简单型。
一个 datetime
对象 d
在以下条件同时成立时将是感知型的:
d.tzinfo
不为None
d.tzinfo.utcoffset(d)
不返回None
在其他情况下,d
将是简单型的。
一个 time
对象 t
在以下条件同时成立时将是感知型的:
t.tzinfo
不为None
t.tzinfo.utcoffset(None)
不返回None
。
在其他情况下,t
将是简单型的。
感知型和简单型之间的区别不适用于 timedelta
对象。
timedelta
类对象
timedelta
对象表示一段持续的时间,即两个 datetime
或 date
实例之间的差值。
- class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
- 所有参数都是可选的并且默认为 0。 这些参数可以是整数或者浮点数,并可以为正值或者负值。
只有 days, seconds 和 microseconds 会存储在内部。 参数单位的换算规则如下:
1毫秒会转换成1000微秒。
1分钟会转换成60秒。
1小时会转换成3600秒。
1星期会转换成7天。
日期、秒、微秒都是标准化的,所以它们的表达方式也是唯一的,例:
0 <= microseconds < 1000000
0 <= seconds < 3600*24
(一天的秒数)-999999999 <= days <= 999999999
下面的例子演示了如何对 days, seconds 和 microseconds 以外的任意参数执行“合并”操作并标准化为以上三个结果属性:
- >>> from datetime import timedelta
- >>> delta = timedelta(
- ... days=50,
- ... seconds=27,
- ... microseconds=10,
- ... milliseconds=29000,
- ... minutes=5,
- ... hours=8,
- ... weeks=2
- ... )
- >>> # 只保留日期、秒和微秒
- >>> delta
- datetime.timedelta(days=64, seconds=29156, microseconds=10)
在有任何参数为浮点型并且 microseconds 值为小数的情况下,从所有参数中余下的微秒数将被合并,并使用四舍五入偶不入奇的规则将总计值舍入到最接近的整数微秒值。 如果没有任何参数为浮点型的情况下,则转换和标准化过程将是完全精确的(不会丢失信息)。
如果标准化后的 days 数值超过了指定范围,将会抛出 OverflowError
异常。
请注意对负数值进行标准化的结果可能会令人感到惊讶。 例如:
- >>> from datetime import timedelta
- >>> d = timedelta(microseconds=-1)
- >>> (d.days, d.seconds, d.microseconds)
- (-1, 86399, 999999)
类属性:
- timedelta.min
- The most negative
timedelta
object,timedelta(-999999999)
.
- timedelta.max
- The most positive
timedelta
object,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
|
t2 和 t3 之和。 运算后 t1 - t2 == t3 且 t1 - t3 == t2 为真值。 (1)
|
t1 = t2 - t3
|
t2 和 t3 之差。 运算后 t1 == t2 - t3 且 t2 == t1 + t3 为真值。 (1)(6)
|
t1 = t2 * i or t1 = i * t2
|
时差乘以一个整数。 运算后如果 i != 0 则 t1 // i == t2 为真值。
|
通常情况下,t1 * i == t1 * (i-1) + t1 为真值。 (1)
| |
t1 = t2 * f or t1 = f * t2
| 乘以一个浮点数,结果会被舍入到 timedelta 最接近的整数倍。 精度使用四舍五偶入奇不入规则。 |
f = t2 / t3
|
总时长 t2 除以间隔单位 t3 (3)。 返回一个 float 对象。
|
t1 = t2 / f or t1 = t2 / i
| 除以一个浮点数或整数。 结果会被舍入到 timedelta 最接近的整数倍。 精度使用四舍五偶入奇不入规则。 |
t1 = t2 // i or t1 = 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 对象。
|
-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)
|
返回一个 timedelta 对象的字符串表示形式,作为附带正规属性值的构造器调用。
|
注释:
结果正确,但可能会溢出。
结果正确,不会溢出。
除以零将会引发
ZeroDivisionError
。-timedelta.max
不可以表示为一个timedelta
对象。timedelta
对象的字符串表示形式类似于其内部表示形式被规范化。对于负时间增量,这会导致一些不寻常的结果。例如:
- >>> timedelta(hours=-5)
- datetime.timedelta(days=-1, seconds=68400)
- >>> print(_)
- -1 day, 19:00:00
- 表达式
t2 - t3
通常与t2 + (-t3)
是等价的,除非 t3 等于timedelta.max
; 在这种情况下前者会返回结果,而后者则会溢出。
除了上面列举的操作以外,timedelta
对象还支持与 date
和 datetime
对象进行特定的相加和相减运算(见下文)。
在 3.2 版本发生变更: 现在已支持 timedelta
对象与另一个 timedelta
对象相整除或相除,包括求余运算和 divmod()
函数。 现在也支持 timedelta
对象加上或乘以一个 float
对象。
timedelta
对象支持相等性和顺序比较。
在布尔运算中,timedelta
对象当且仅当其不等于 timedelta(0)
时则会被视为真值。
实例方法:
- timedelta.total_seconds()
- 返回期间占用了多少秒。等价于
td / timedelta(seconds=1)
。对于秒以外的间隔单位,直接使用除法形式 (例如td / timedelta(microseconds=1)
)。
需要注意的是,时间间隔较大时,这个方法的结果中的微秒将会失真(大多数平台上大于270年视为一个较大的时间间隔)。
Added in version 3.2.
timedelta
用法示例
一个标准化的附加示例:
- >>> # another_year 的部分增加恰好 365 天
- >>> 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 <= 日期 <= 给定年月对应的天数
如果参数不在这些范围内,则抛出 ValueError
异常。
其它构造器,所有的类方法:
- classmethod date.today()
- 返回当前的本地日期。
这等价于 date.fromtimestamp(time.time())
。
- classmethod date.fromtimestamp(timestamp)
- 返回对应于 POSIX 时间戳的当地时间,例如
time.time()
返回的就是时间戳。
这可能引发 OverflowError
,如果时间戳数值超出所在平台 C localtime()
函数的支持范围的话,并且会在 localtime()
出错时引发 OSError
。 通常该数值会被限制在 1970 年至 2038 年之间。 请注意在时间戳概念包含闰秒的非 POSIX 系统上,闰秒会被 fromtimestamp()
所忽略。
在 3.3 版本发生变更: 引发 OverflowError
而不是 ValueError
,如果时间戳数值超出所在平台 C localtime()
函数的支持范围的话,并会在 localtime()
出错时引发 OSError
而不是 ValueError
。
- classmethod date.fromordinal(ordinal)
- 返回对应于预期格列高利历序号的日期,其中公元 1 年 1 月 1 日的序号为 1。
除非 1 <= ordinal <= date.max.toordinal()
否则会引发 ValueError
。 对于任意的日期 d
,均有 date.fromordinal(d.toordinal()) == d
。
- classmethod date.fromisoformat(date_string)
- 返回一个对应于以任何有效 ISO 8601 格式给出的 date_string 的
date
,下列格式除外:
目前不支持降低精度的日期 (
YYYY-MM
,YYYY
)。目前不支持扩展日期表示形式 (
±YYYYYY-MM-DD
)。目前不支持序数日期 (
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)
Added in version 3.7.
在 3.11 版本发生变更: 在之前版本中,此方法仅支持一种格式 YYYY-MM-DD
。
- classmethod date.fromisocalendar(year, week, day)
- 返回指定 year, week 和 day 所对应 ISO 历法日期的
date
。 这是函数date.isocalendar()
的逆操作。
Added in version 3.8.
类属性:
- date.min
- 最小的日期
date(MINYEAR, 1, 1)
。
- date.max
- 最大的日期 ,
date(MAXYEAR, 12, 31)
。
- date.resolution
- 两个日期对象的最小间隔,
timedelta(days=1)
。
实例属性(只读):
- 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) |
注释:
如果
timedelta.days > 0
则 date2 将在时间线上前进,如果timedelta.days < 0
则将后退。 操作完成后date2 - date1 == timedelta.days
。timedelta.seconds
和timedelta.microseconds
会被忽略。 如果date2.year
将小于MINYEAR
或大于MAXYEAR
则会引发OverflowError
。timedelta.seconds
和timedelta.microseconds
会被忽略。该值是精确的,且不会溢出。 运算后
timedelta.seconds
和timedelta.microseconds
均为 0,且date2 + timedelta == date1
。date
对象在表示相同的日期时相等。
不属于 datetime
实例的 date
对象永远不会与 datetime
对象相等,即使它们表示相同的日期。
- 当 date1 的时间在 date2 之前则认为 date1 小于 date2。 换句话说,当且仅当
date1.toordinal() < date2.toordinal()
时date1 < date2
。
不同时为 datetime
实例的 date
实例和 datetime
对象之间的顺序比较将会引发 TypeError
。
在 3.13 版本发生变更: 在 datetime
对象和不属于 datetime
子类的 date
子类的实例之间进行比较时不会再将后者转换为 date
,并忽略时间部分和时区信息。 此默认行为可以通过在子类中重写特殊比较方法来更改。
在布尔运算中,所有 date
对象都会被视为真值。
实例方法:
- 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)
date
对象也被泛型函数 copy.replace()
所支持。
- date.timetuple()
- 返回一个
time.struct_time
,即time.localtime()
所返回的类型。
hours, minutes 和 seconds 值均为 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
对象d
,均有date.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()
- 返回一个由三部分组成的 named tuple 对象:
year
,week
和weekday
。
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 版本发生变更: 结果由元组改为 named tuple。
- date.isoformat()
- 返回一个以 ISO 8601 格式
YYYY-MM-DD
来表示日期的字符串:
- >>> from datetime import date
- >>> date(2002, 12, 4).isoformat()
- '2002-12-04'
- date.str()
- 对于日期
d
,str(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()
函数遵循 C 标准的平台上 (time.ctime()
会发起对该函数的调用,但 date.ctime()
并不会) 。
- date.strftime(format)
- 返回一个由显式格式字符串所控制的,代表日期的字符串。 表示时、分或秒的格式代码值将为 0。 另请参阅 strftime() 和 strptime() 的行为 和
date.isoformat()
。
- date.format(format)
- 与
date.strftime()
相同。 此方法使得在 格式化字符串字面值 中以及使用str.format()
时为date
对象指定格式字符串成为可能。 另请参阅 strftime() 和 strptime() 的行为 和date.isoformat()
。