Relativedelta
class dateutil.relativedelta.relativedelta(dt1=None, dt2=None, years=0, months=0,
days=0, leapdays=0, weeks=0, hours=0,
minutes=0, seconds=0, microseconds=0,
year=None, month=None, day=None, weekday=None, yearday=None, nlyearday=None,
hour=None, minute=None, second=None,
microsecond=None)
relativedelta对象是应用于datetime对象的,可以替换datetime的元素或者计算两个datetime对象时间间隔。
参数
1、传入两个datetime对象
relativedelta(datetime1, datetime2),可以计算两个datetime对象的时间间隔。
import dateutil.relativedelta as dr
import datetime as dt
dr.relativedelta(dt.datetime(2020,9,18),dt.datetime(2019,10,20))
Out[4]: relativedelta(months=+10, days=+29)
2、传递以下的任意数目的参数
relativedelta(arg1=x,arg2=y,arg3=z...)
arg:
(1) 单数形式的year, month, day, hour, minute, second, microsecond,这个是绝对时间,会使用参数的值直接替换datetime里面对应的值。
dt.datetime(2020,9,18)+dr.relativedelta(day=1,month=12)
Out[5]: datetime.datetime(2020, 12, 1, 0, 0)
如果月份给定的值超过了正常的日期表示的数,会报错。但是日期超过最大值不会报错而是直接取使得日期有效的上限值。
(2) 复数形式的years, months, weeks, days, hours, minutes, seconds, microseconds,这个是相对量,可能是正数或者负数。加上或者减去一个relativedelta对象里面对应参数就是在datetime对象里面对相应的参数进行算术运算操作。
dt.datetime(2020,9,18)+dr.relativedelta(days=2,months=1)
Out[8]: datetime.datetime(2020, 10, 20, 0, 0)
dt.datetime(2020,9,18)+dr.relativedelta(days=-2,months=+1)
Out[9]: datetime.datetime(2020, 10, 16, 0, 0)
(3) Weekday:relativedelta库里面可用的任意一个weekday实例,比如MO,TU等。实例后面加上一个数字,这个数字可以是正数或者是负数,如果不指定数字的话默认就是+1,。也可以像使用枚举类型一样使用这个参数,也就是0=MO。如果这一天本身就是某个星期,那么这个参数传进为星期几将会无效。这个是一个相对的值,比如MO(1)代表从某个日期开始的下一个星期一,MO(-1)代表上一个星期一。
dt.datetime(2020,9,18)+dr.relativedelta(weekday=dr.MO(1))
Out[15]: datetime.datetime(2020, 9, 21, 0, 0)#9月18号之后的第一个星期一
dt.datetime(2020,9,21)+dr.relativedelta(weekday=dr.MO(1))
Out[16]: datetime.datetime(2020, 9, 21, 0, 0)#因为9月21号已经是星期一,那么这个weekday参数不会生效。
(4) Leapdays:如果给定的某天是闰年的话,就把该参数的值加进该日期。
dt.datetime(1880,9,18)+dr.relativedelta(leapdays=1)
Out[17]: datetime.datetime(1880, 9, 19, 0, 0)#1880是闰年
dt.datetime(1881,9,18)+dr.relativedelta(leapdays=1)
Out[18]: datetime.datetime(1881, 9, 18, 0, 0)#1881是平年
(5) Yearday,nlyearday:在该年的基础上加上yearday的值,nlyearday表示该年是闰年时候的参数。
dt.datetime(1881,9,18)+dr.relativedelta(yearday=260)
Out[20]: datetime.datetime(1881, 9, 17, 0, 0)#表示在1881年的基础上开始数260天时候的日期。
rrule
class dateutil.rrule.rrule(freq, dtstart=None, interval=1, wkst=None, count=None, until=None,
bysetpos=None, bymonth=None, bymonthday=None, byyearday=None, byeaster=None, byweekno=None, byweekday=None,
byhour=None, byminute=None, bysecond=None, cache=False)
freq参数:一定要是YEARLY,MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY 或者SECONDLY之一,是递归产生时间序列的依据。比如如果选择YEARLY就是根据年来产生序列,其他的参数也类似。
dtstart参数:是递归开始的时间,如果没有传入参数,那么将会调用datetime.now()使用当前的时间。
import dateutil.rrule as drr
list(drr.rrule(drr.DAILY,dtstart=dt.datetime(2020,8,18),count=3))
Out[27]: [datetime.datetime(2020, 8, 18, 0, 0),
datetime.datetime(2020, 8, 19, 0, 0),
datetime.datetime(2020, 8, 20, 0, 0)]
产生了以2020年8月18开始,以日期为根据递归的三个时间。
interval参数:是两个合适的序列之间的间隔,比如freq参数设置为YEARLY,interval参数设置为2就代表了每两年取一个时间,参数的默认值是1。
list(drr.rrule(drr.YEARLY,dtstart=dt.datetime(2020,8,18),count=5,interval=2)) Out[28]: [datetime.datetime(2020, 8, 18, 0, 0),
datetime.datetime(2022, 8, 18, 0, 0),
datetime.datetime(2024, 8, 18, 0, 0),
datetime.datetime(2026, 8, 18, 0, 0),
datetime.datetime(2028, 8, 18, 0, 0)]
wkst参数:是周开始时间,一定是库自带的MO,TU等对象,或者是一个整数(类似于枚举类型)来说明周开始的时间。这个参数会影响基于周的递归。默认的参数会从calendar.firstweekday()里面获取,可以使用calendar.setdirstweekday()来进行调整。
一般设置周开始时间不会影响取到的序列,但是当freq参数是WEEKLY并且有一定取时间间隔的时候会产生影响。下面是两个官方的例子:
list(rrule(drr.WEEKLY, interval=2, count=4,byweekday=(drr.TU,drr.SU), wkst=drr.SU,dtstart=dt.datetime(1997,8,5,9)))

上面红线代表第一段代码的过程,绿色的线代表第二段代码的过程。
count参数:设置进行递归产生的序列的数目。
until参数:设置了递归日期的上限值,递归可以通过dtstart参数自动获取结束的日期,但是这个日期不能超过until参数表示的值。
list(drr.rrule(drr.DAILY,dtstart=dt.datetime(2020,8,18),interval=1,count=18,until=dt.datetime(2020,8,25)))
Out[29]: [datetime.datetime(2020, 8, 18, 0, 0), datetime.datetime(2020, 8, 19, 0, 0), datetime.datetime(2020, 8, 20, 0, 0), datetime.datetime(2020, 8, 21, 0, 0), datetime.datetime(2020, 8, 22, 0, 0), datetime.datetime(2020, 8, 23, 0, 0), datetime.datetime(2020, 8, 24, 0, 0), datetime.datetime(2020, 8, 25, 0, 0)]
上面原本应该产生18个日期,但是由于until参数的存在,日期只能设置到8月25号
bysetpos参数:如果有的话一定是一个整数或者是一个数字序列,数字可以是正数或者是负数,数字指定了取在freq里面序列出现的位置。比如freq=MONTHLY,bysetpos取1,byweekday取MO,TU就代表了取每个月里面第一个出现的周一或者周二。
By-参数:指定了要取的序列。比如bymonth就是指定了要取哪几个月作为序列。一般会配合bysetpos使用。有bymonth,bymonthday,byyearday,byeaster,byweekno,byweekday,byhour,byminute,bysecond。
list(drr.rrule(drr.MONTHLY,count=3,byweekday=(drr.MO,drr.TU),bysetpos=-2,dtstart=dt.datetime(1997,9,29)))
Out[31]: [datetime.datetime(1997, 9, 29, 0, 0),
datetime.datetime(1997, 10, 27, 0, 0),
datetime.datetime(1997, 11, 24, 0, 0)]
指定了要筛选周一和周二(byweekday=(drr.MO,drr.TU)),指定了要筛选的对象(bysetpos=-2)也即是每个月的第二个对象。