如何使用 Python datetime 模块对日期时间进行运算?timedelta 类介绍

我被代码海扁署名-非商业-禁演绎
阅读 19:28·字数 5844·发布 
Bilibili 空间
关注 960

Python datetime 模块的 date,time,datetime 对象之间的运算

对于 Pythondatetime模块的datetime以及datetime对象,可使用减法运算符和比较运算符进行运算,参与运算的对象需要是相同的类型,比如date对象不能与timedatetime对象进行运算。

使用减法运算符-可以计算两个日期(date对象)或日期时间(datetime对象)之间的差值,这将返回 Pythondatetime模块的timedelta对象。

date1 - date2
datetime1 - datetime2

无法计算 Python datetime 模块的 time 对象之间的时间差值

你可以使用减法运算符-计算日期或日期时间之间的差值,但对于 Pythondatetime模块的time对象,无法通过减法运算符-计算他们之间的差值,这将导致异常TypeError: unsupported operand type(s) for -: 'datetime.time' and 'datetime.time'

from datetime import date, datetime
# 计算两个日期之间差值
date(2024, 10, 10) - date(2024, 10, 1)
datetime.timedelta(days=9)
# 计算两个日期时间之间差值
datetime(2024, 10, 1, 0, 0, 0, 1234) - datetime(2024, 10, 10, 0, 0, 1, 123)
datetime.timedelta(days=-10, seconds=86399, microseconds=1111)

使用比较运算符==!=可以计算两个日期(date对象),两个时间(time对象)或日期时间(datetime对象)是否相等或是否不相等。

date1 == date2
date1 != date2
time1 == time2
time1 != time2
datetime1 == datetime2
datetime1 != datetime2

表示相同日期的 Python datetime 模块的 date 与 datetime 对象不相等

即便表示了相同的日期,Pythondatetime模块的datedatetime对象不会相等,比如,date(2024,1,1)datetime(2024,1,1)不相等。

from datetime import date, time, datetime
# 两个日期相等
date(2024, 10, 3) == date(2024, 10, 3)
True
# 两个时间相等
time(1, 1) == time(1, 1, 0, 0)
True
# 两个日期时间相等
datetime(2024, 10, 3, 1) != datetime(2024, 10, 3, 1, 0)
False
# date 和 datetime 不相等
date(2024, 10, 3) == datetime(2024, 10, 3)
False

使用比较运算符<<=可以计算一个日期(date对象)是否小于或小于等于另一个日期,计算一个时间(time对象)是否小于或小于等于另一个时间,计算一个日期时间(datetime对象)是否小于或小于等于另一个日期时间。

使用比较运算符>>=可以计算一个日期(date对象)是否大于或大于等于另一个日期,计算一个时间(time对象)是否大于或大于等于另一个时间,计算一个日期时间(datetime对象)是否大于或大于等于另一个日期时间。

date1 < date2
date1 <= date2
time1 < time2
time1 <= time2
datetime1 < datetime2
datetime1 <= datetime2
date1 > date2
date1 >= date2
time1 > time2
time1 >= time2
datetime1 > datetime2
datetime1 >= datetime2

from datetime import date, time, datetime
# 日期 2024-10-3 更大
date(2024, 10, 3) < date(2024, 10, 1)
False
# 时间 23:59:59 更大
time(23, 59, 59) > time(23, 59)
True
# 日期时间 2024-10-3 23:59:59.123456 更大
datetime(2024, 10, 3, 23, 59, 59) <= datetime(2024, 10, 3, 23, 59, 59, 123456)
True

时区

如果你想了解时区信息对timedatetime对象运算的影响,那么可以查看Python datetime 模块的时区对象 tzinfo 对日期时间运算的影响一段。

Python datetime 模块的 timedelta 类

Pythondatetime模块的timedelta类,用于表示两个日期或两个日期时间之间的差值,该类的实例通常由包含减法运算符-的表达式计算得到,也可以使用构造器创建,传递给构造器的参数将被换算累计为timedelta对象的dayssecondsmicroseconds的属性,这意味着转递的任意参数都将成为日期时间差值的一部分。

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

days 参数

days参数表示日期时间差值持续的天数。

seconds 参数

seconds参数表示日期时间差值持续的秒数。

microseconds 参数

microseconds参数表示日期时间差值持续的微秒。

milliseconds 参数

milliseconds参数表示毫秒数(1秒等于1000毫秒),他将被累计为微秒(1毫秒等于1000微秒)。

minutes 参数

minutes参数表示分钟数,他将被累计为秒(1分钟等于60秒)。

hours 参数

hours参数表示小时数,他将被累计为秒(1小时等于3600秒)。

weeks 参数

weeks参数表示星期数,他将被累计为天(1星期等于7天),秒(如果有秒的部分)和微秒(如果有微秒的部分)。

Python datetime 模块的 timedelta 类的构造器参数可以是负数和小数

在 Pythondatetime模块的timedelta类的构造器中,构造器的参数可以是负数和小数,除了表示微秒的microseconds,该参数可以是负数但不能是小数。此外,在参数milliseconds所表示的毫秒被转换为微秒时,仅前三位小数有效(其余部分会被舍入),比如,毫秒11.2345会被转换为微秒11235,毫秒11.2344会被转换为微秒11234

对于构造器参数daysweekshoursminutesseconds,如果拥有小数部分,则相当于将其计算为对应秒数,其微秒部分为六位(其余部分会被舍入)。比如,表达式timedelta(days=0.5555555555),其微秒部分的计算结果为9999952,舍入后为999995datetime.timedelta(seconds=47999,microseconds=999995)),表达式timedelta(days=0.55555555555),其微秒部分的计算结果为99999952,舍入后为1秒(datetime.timedelta(seconds=48000))。

from datetime import timedelta
# 创建 timedelta 对象
timedelta(days=1, hours=-24, minutes=60.5)
datetime.timedelta(seconds=3630)
timedelta(minutes=1, milliseconds=123, microseconds=111567)
datetime.timedelta(seconds=60, microseconds=234567)
timedelta(days=0.5, weeks=0.5, hours=0.5, minutes=0.5)
datetime.timedelta(days=4, seconds=1830)
timedelta(seconds=0.5, milliseconds=0.5)
datetime.timedelta(microseconds=500500)

获取 Python datetime 模块的 timedelta 对象所对应的日期时间差值信息

Pythondatetime模块的timedelta对象拥有以下只读属性,可用于获取日期时间差值的相关信息,其中days属性表示日期时间差值所持续的天数(大于等于-999999999,小于等于999999999),seconds属性表示日期时间差值所持续的秒数(大于等于0,小于86400),microseconds属性表示日期时间差值所持续的微秒(大于等于0,小于1000000)。

timedelta.days
timedelta.seconds
timedelta.microseconds

Pythondatetime模块的timedelta对象的total_seconds方法,可用于获取日期时间差值对应的总秒数(不同于seconds属性),微秒部分将被表示为小数,因此,该方法的返回值是一个浮点数。

timedelta.total_seconds()

Python datetime 模块的 timedelta 对象的 seconds 属性和 total_seconds 方法的区别

Pythondatetime模块的timedelta对象的total_seconds方法所返回的秒数可以表示完整的日期时间差值,而seconds属性需要和daysmicroseconds属性一起才能表示完整的日期时间差值。

from datetime import timedelta
# 获取日期时间差值信息
td = timedelta(days=1, weeks=1, hours=0.5, milliseconds=1.234)
td.days
8
td.seconds
1800
td.microseconds
1234
# 总秒数
td.total_seconds()
693000.001234

Python datetime 模块的 timedelta 对象的 total_seconds 方法可能失真

这里需要指出,对于 Pythondatetime模块的timedelta对象的total_seconds方法,如果日期时间的差值过大,那么其返回值的小数(微秒)部分可能会失真。

from datetime import timedelta
# 差值过大,微秒部分失真
timedelta(days=365 * 3000, microseconds=123456).total_seconds()
94608000000.12346

Python datetime 模块的 timedelta 对象所允许的最小和最大日期时间差值

Pythondatetime模块的timedelta类的类变量minmax,分别表示所允许的最小日期时间差值和最大日期时间差值,其中min等价于表达式timedelta(days=-999999999)运算得到的timedelta对象,max等价于表达式timedelta(days=999999999,hours=23,minutes=59,seconds=59,microseconds=999999)timedelta(days=999999999,seconds=86399,microseconds=999999)运算得到的timedelta对象。

timedelta.min
timedelta.max

from datetime import timedelta
# 最小日期时间差值
timedelta.min
datetime.timedelta(days=-999999999)
# 最大日期时间差值
timedelta.max
datetime.timedelta(days=999999999, seconds=86399, microseconds=999999)

Python datetime 模块的 timedelta 对象之间的运算

你可以使用某些运算符对 Pythondatetime模块的timedelta对象进行运算,如果运算的结果是一个新的timedelta对象,并且日期时间差值超出了timedelta对象的表达范围(比如-timedelta.max),那么可能会引发异常OverflowError,如果涉及除法运算(比如,取余或整除)的除数为0或等价于timedelta()timedelta对象,那么可能会引发异常ZeroDivisionError

使用加法运算符+和减法运算符-,可以在 Pythondatetime模块的timedelta对象之间进行加法或减法运算,这相当于将日期时间的差值相加或相减,其运算结果是一个新的timedelta对象。

timedelta1 + timedelta2
timedelta1 - timedelta2

from datetime import timedelta
# 将两个日期时间差值相加
timedelta(days=1, hours=324) + timedelta(weeks=3)
datetime.timedelta(days=35, seconds=43200)
# 将两个日期时间差值相减
timedelta(hours=3, minutes=20) - timedelta(minutes=45)
datetime.timedelta(seconds=9300)

使用除法运算符/,可以在 Pythondatetime模块的timedelta对象之间进行除法运算,这相当于将日期时间的差值相除,其运算结果是一个表示倍数关系的浮点数。

使用整除运算符//,可以在 Pythondatetime模块的timedelta对象之间进行整除运算,这相当于将日期时间的差值整除(运算结果为整数,丢弃结果中的小数部分)。

timedelta1 / timedelta2
timedelta1 // timedelta2

from datetime import timedelta
# 将两个日期时间差值相除
timedelta(5) / timedelta(2)
2.5
timedelta(1) / timedelta(hours=48)
0.5
# 将两个日期时间差值整除
timedelta(5) // timedelta(2)
2
timedelta(1) // timedelta(hours=48)
0

使用取余运算符%,可以在 Pythondatetime模块的timedelta对象之间进行取余运算,这相当于将日期时间的差值相除然后获取余数,其运算结果是一个新的timedelta对象(两个timedelta对象的dayssecondsmicroseconds属性相除,并通过余数来创建新的timedelta对象)。

timedelta1 % timedelta2

from datetime import timedelta
# 对两个日期时间差值取余
timedelta(days=5, hours=5, microseconds=5) % timedelta(days=2, minutes=120, milliseconds=0.002)
datetime.timedelta(days=1, seconds=3600, microseconds=1)

通过 Python 的divmod函数,可同时完成对两个datetime模块的timedelta对象的整除和取余运算,运算的结果是一个 Python 元组,元组的第一个元素是整除的结果(与整除运算符//的结果相同),第二个元素是取余的结果(与取余运算符%的结果相同)。

divmod(timedelta1, timedelta2)

from datetime import timedelta
# 同时整除和取余
divmod(timedelta(5), timedelta(2))
(2, datetime.timedelta(days=1))

使用一元运算符+,可以获得一个新的 Pythondatetime模块的timedelta对象,新对象所表示的日期时间差值与原有timedelta对象相同。使用一元运算符-,可以获得一个新的 Pythondatetime模块的timedelta对象,新对象将根据原有timedelta对象的daysseconds以及microseconds属性的相反数创建。

+timedelta
-timedelta

from datetime import timedelta
# 一元运算符
+timedelta(hours=23, minutes=59, seconds=59)
datetime.timedelta(seconds=86399)
-timedelta(hours=23, minutes=59, seconds=59)
datetime.timedelta(days=-1, seconds=1)

使用比较运算符==!=可以计算两个日期时间差值(timedelta对象)是否相等或是否不相等。

timedelta1 == timedelta2
timedelta1 != timedelta2

from datetime import date, timedelta
# 1 分钟等于 60 秒
timedelta(minutes=1) == timedelta(seconds=60)
True
# 两边表达式相等
timedelta(days=1) != date(2024, 10, 1) - date(2024, 9, 30)
False

使用比较运算符<<=可以计算一个日期时间差值(timedelta对象)是否小于或小于等于另一个日期时间差值。使用比较运算符>>=可以计算一个日期时间差值(timedelta对象)是否大于或大于等于另一个日期时间差值。

timedelta1 < timedelta2
timedelta1 <= timedelta2
timedelta1 > timedelta2
timedelta1 >= timedelta2

from datetime import timedelta
# 比较日期时间差值大小
timedelta(hours=1.5) > timedelta(minutes=80)
True
timedelta(milliseconds=1.234) > timedelta(microseconds=1235)
True

Python datetime 模块的 timedelta 对象与数字类型的运算

除了在 Pythondatetime模块的timedelta对象之间进行运算,以下运算符还可以完成timedelta对象与数字类型之间的运算,如果运算的结果是一个新的timedelta对象,并且日期时间差值超出了timedelta对象的表达范围,那么可能会引发异常OverflowError

使用乘法运算符*和除法运算符/,可以完成timedelta对象与 Python 整数或浮点数之间的乘法和除法运算,这相当日期时间差值被扩大或缩小指定的倍数,其运算结果是一个新的timedelta对象。

使用整除运算符//,可以完成timedelta对象与 Python 整数之间的整除运算,该运算符与除法运算符/类似,但会丢弃微秒的小数部分而不是进行舍入。

timedelta * int|float
int|float * timedelta
timedelta / int|float
timedelta1 // int

from datetime import timedelta
# 浮点数与日期时间差值相乘
3.5 * timedelta(days=1, hours=30)
datetime.timedelta(days=7, seconds=75600)
# 日期时间差值与整数相除
timedelta(days=1) / 35
# 微秒的小数部分会被舍入
datetime.timedelta(seconds=2468, microseconds=571429)
timedelta(days=1) // 35
# 丢弃微秒的小数部分
datetime.timedelta(seconds=2468, microseconds=571428)

Python datetime 模块的 timedelta 对象与 date,datetime 对象之间的运算

使用加法运算符+和减法运算符-,Pythondatetime模块的timedelta对象可以同datedatetime对象进行加法或减法运算,其运算结果是一个新的datedatetime对象,这相当于将日期时间增加或减去一个差值。

需要指出的是,对于 Pythondatetime模块的date对象,仅timedelta对象的days属性会参与运算。

date|datetime + timedelta
date|datetime - timedelta
timedelta + date|datetime
timedelta - date|datetime

from datetime import date, datetime, timedelta
# 增加 6 天
timedelta(weeks=0.9) + date(2024, 1, 1)
datetime.date(2024, 1, 7)
# 减去 1 天 11 小时
datetime(2024, 1, 1, 10, 10) - timedelta(days=1, hours=11)
datetime.datetime(2023, 12, 30, 23, 10)

时区

如果你想了解时区信息对timedeltadatetime对象运算的影响,那么可以查看Python datetime 模块的时区对象 tzinfo 对日期时间运算的影响一段。

获取 Python datetime 模块的 timedelta 对象所表示的日期时间差值的绝对值

通过 Python 的abs函数,可以获取 Pythondatetime模块的timedelta对象所表示的日期时间差值的绝对值,当timedelta对象的days属性大于等于0时,abs函数的返回值等价于使用一元运算符+,当timedelta对象的days属性小于0时,abs函数的返回值等价于使用一元运算符-

abs(timedelta)

from datetime import timedelta
# 虽然参数 days 为 1,但最终的 days 属性为 -1
td = timedelta(days=1, hours=-25)
td
datetime.timedelta(days=-1, seconds=82800)
abs(td)
# 等同于 timedelta(days=1, seconds=-82800)
datetime.timedelta(seconds=3600)

将 Python datetime 模块的 timedelta 对象所表示的日期时间差值转换为字符串

通过 Python 的repr函数或字符串类型的构造器str,可以将 Pythondatetime模块的timedelta对象所表示的日期时间差值转换为一个字符串。当然,调用timedelta对象的__repr____str__方法可实现相同效果。

repr(timedelta)
str(timedelta)
timedelta.__repr__()
timedelta.__str__()

from datetime import timedelta
td = timedelta(days=3, hours=0.5, milliseconds=123)
# 将日期时间差值转换为字符串
str(td)
'3 days, 0:30:00.123000'
td.__repr__()
'datetime.timedelta(days=3, seconds=1800, microseconds=123000)'

Python datetime 模块的 timedelta 对象与布尔类型

对于 Pythondatetime模块的timedelta对象,如果其表示的日期时间差值不为0,那么对象将被视为真(True),否则将被视为假(False)。

from datetime import timedelta
# 日期时间差值为 0 则等价于 False
bool(timedelta(days=1, hours=-24))
False
bool(timedelta())
False
# 日期时间差值不为 0 则等价于 True
bool(timedelta(microseconds=1))
True