目的:
给定一个年月区间,比如:2019.01 至 2019.05,要求返回一个包含期间所有的月份的列表,比如:['2019.01', '2019.02', '2019.03', '2019.04', '2019.05']
Note:参考的博客代码逻辑存在问题,若时间年份之差超过两年,比如 2014 至 2016,计算结果就不对了,我在分析了其计算逻辑后,根据自身的功能需求,对函数功能进行了改进。
思路:
这里要求得到给定区间的所有月份,那么我们先可以计算给定区间的时间差,即两者之间总共包含多少个月;之后由第一个月(起始时间)逐步累加,最终得到给定时间区间的所有月份的列表。
1.时间差计算:我们可以使用第三方库 dateutil 中的 rrule.count 函数来实现。
首先看下以下代码:
importdatetimefrom dateutil importrrule
start=datetime.datetime.strptime('2019.01','%Y.%m')
end=datetime.datetime.strptime('2019.05','%Y.%m')print(start.month)
rrule.rrule(rrule.MONTHLY,dtstart=start,until=end).count()
输出结果如下:
在上面的代码中,我们使用了 rrule.count 函数 以月份为尺度,计算量两个时间段之间的差,得到了 2019.01 至 2019.05 这段时间里,总共有5个月。
2.累加计算每个月:在这里我们可以利用 for 循环以及 range() 函数,根据总月份数量,逐步累加,比如:2019.01 - 2019.05 共5个月,从0到4进行迭代,由 1+0=1 到 1+4=5,即可得到所有月份;另外,当月份迭代累加结果超过12时,对累加结果除以12取余,并对年份进行加1,即可得到正确的年月时间。
解析:
Python 第三方库 dateutil 提供了 rrule.count() 方法,方便我们计算时间差,它有以下特点:
① rrule 方法允许用户根据日期(DAILY),星期(WEEKLY),月(MONTHLY),年(YEARLY)来设置时间差计算的尺度。
② count()返回的结果是一个整数。
代码实现:
根据上面的思路,定义以下函数:
importdatetimefrom dateutil importrruledefget_each_month(start_month, end_month):if str(start_month).count('.') != 1 or str(end_month).count('.') != 1:print("Parameter Error: Pls input a string such as '2019.01'")return[]if int(str(start_month).split('.')[1]) > 12 or int(str(end_month).split('.')[1]) > 12:print('Parameter Error: Pls input correct month range such as between 1 to 12')return[]if int(str(start_month).split('.')[1]) == 0 or int(str(end_month).split('.')[1]) == 12:print('Parameter Error: Pls input correct month range such as between 1 to 12')return[]
start= datetime.datetime.strptime(start_month, "%Y.%m")
end= datetime.datetime.strptime(end_month, "%Y.%m")
month_count= rrule.rrule(rrule.MONTHLY,dtstart=start,until=end).count() #计算总月份数
if end
list_month=[]
year= int(str(start)[:7].split('-')[0]) #截取起始年份
for m in range(month_count): #利用range函数填充结果列表
month = int(str(start)[:7].split('-')[1]) #截取起始月份,写在for循环里,作为每次迭代的累加基数
month = month +mif month > 12:if month%12 >0:
month= month%12 #计算结果大于12,取余数
if month==1:
year+= 1 #只需在1月份的时候对年份加1,注意year的初始化在for循环外
else:
month= 12
if len(str(month))==1:
list_month.append(str(year)+ '.0' +str(month))else:
list_month.append(str(year)+ '.' +str(month))return list_month
调用结果如下: