2016-01-22 55 views
3

我想要获得给定范围内的月份列表。具体来说,给定的范围2015-12-31 - 2016-01-01,我想获得列表2015-122016-01如何创建日期范围,直到包含python dateutils的日期?

我使用的是dateutil的rrule,但until参数并没有真正的帮助,因为它似乎在寻找完整的月份。

例如为:

from dateutil.relativedelta import relativedelta 
from dateutil.rrule import rrule, MONTHLY 

list(rrule(MONTHLY, dtstart=datetime(2015, 12, 31), until=datetime(2016,01,01))) 

这只回报[datetime.datetime(2015, 12, 31, 0, 0)],不[datetime.datetime(2015, 12, 31, 0, 0), datetime.datetime(2016, 01, 01, 0, 0)]

同样,我想对于任何开始日期在12月相同的输出,以及任何一天结束一月。也就是说,我只关心月份为2015-122016-01的事实。这一天对我来说并不重要,但我只希望每个月只有一个datetime(这些输入的最大值为2,对于day组件的值为最大值)。

是否有一个简单的解决方案,或者我将不得不增加每日和建立自己的一套月?

回答

3

list(rrule(MONTHLY, dtstart=datetime(2015, 12, 31), until=datetime(2016,01,01)))没有返回一月的原因是因为没有一个月(以MONTHLY参数)在012月31日到1月1日之间。

由于您不需要日间组件,因此我将执行一个小日期操作:

def date_list(start, end): 
    start = datetime.date(start.year, start.month, 1) 
    end = datetime.date(end.year, end.month, 1) 
    dates = [dt for dt in rrule(MONTHLY, dtstart=start, until=end)] 
    return dates 

这是做什么接受任何开始和结束日期,然后重置这两个是第一个月。这确保了整个月的存在。它会返回一个日期列表,每个日期将是本月的第一个日期。

例如,您输入

>>> print date_list(datetime.date(2015,12,28), datetime.date(2016,1,1)) 
[datetime.datetime(2015, 12, 1, 0, 0), datetime.datetime(2016, 1, 1, 0, 0)] 

同月:

>>> print date_list(datetime.date(2015,12,28), datetime.date(2015,12,31)) 
[datetime.datetime(2015, 12, 1, 0, 0)] 

使用无效范围(启动前结束):

>>> print date_list(datetime.date(2015,12,28), datetime.date(2015,11,30)) 
[] 

拥有射程更远:

>>> print date_list(datetime.date(2015,12,28), datetime.date(2016,8,3)) 
[datetime.datetime(2015, 12, 1, 0, 0), 
datetime.datetime(2016, 1, 1, 0, 0), 
datetime.datetime(2016, 2, 1, 0, 0), 
datetime.datetime(2016, 3, 1, 0, 0), 
datetime.datetime(2016, 4, 1, 0, 0), 
datetime.datetime(2016, 5, 1, 0, 0), 
datetime.datetime(2016, 6, 1, 0, 0), 
datetime.datetime(2016, 7, 1, 0, 0), 
datetime.datetime(2016, 8, 1, 0, 0)] 
+0

很好的回答。虽然,不是'[dt for rrule(...)]'有点冗长'list(rrule(...))'就足够了。 – AChampion

1

我已经使用几组做到了:

months = set() 

for dt in rrule(DAILY, dtstart=start_date, until=end_date): 
    months.add(dt.strftime('%Y-%m-.*')) 
0

认为你将不得不进行某种形式的迭代。例如,使用deltas,下面会做的伎俩:

import datetime 

start = datetime.datetime(2015, 12, 31) 
stop = datetime.datetime(2016, 1, 8) 

delta = stop - start 

answer = [start+datetime.timedelta(days=idx) for idx in range(delta.days+1)] 
print(answer) 

输出

[datetime.datetime(2015, 12, 31, 0, 0), 
datetime.datetime(2016, 1, 1, 0, 0), 
datetime.datetime(2016, 1, 2, 0, 0), 
datetime.datetime(2016, 1, 3, 0, 0), 
datetime.datetime(2016, 1, 4, 0, 0), 
datetime.datetime(2016, 1, 5, 0, 0), 
datetime.datetime(2016, 1, 6, 0, 0), 
datetime.datetime(2016, 1, 7, 0, 0), 
datetime.datetime(2016, 1, 8, 0, 0)] 
0

只需使用差异月作为计数:

start = datetime(2015, 12, 31) 
end = datetime(2016,01,01) 
diff_month = lambda e, s: (e.year - s.year)*12 + e.month - s.month 
list(rrule(MONTHLY, count=diff_month(end,start)+1, dtstart=start)) 
+0

OP想要一个月份列表 – PaulMcG

+0

OP只关心年月,但不要求他们(尽管这将很容易提取)。这将返回DateTime对象中的正确年份 - 月份列表。接受的答案也是一样的。 – AChampion

+0

对不起,我误解了您的解决方案,我认为这只是给予月数而不是月份列表。 – PaulMcG