Как создать диапазон дат до определенной даты, включая python dateutils?

Я пытаюсь получить список месяцев в данном диапазоне. В частности, учитывая диапазон 2015-12-31 - 2016-01-01 , я хочу получить список 2015-12 и 2016-01 .

Я использую 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)]

Аналогичным образом, я хочу получить тот же результат для любого начального дня в декабре и любого конечного дня в январе. То есть, меня волнует только тот факт, что месяцы – 2015-12 и 2016-01 . Дневная часть для меня не важна, но мне нужно только одно время в месяц (максимум 2 для этих входов с любым значением для компонента day ).

Есть ли простое решение, или мне нужно увеличить ЕЖЕДНЕВНО и построить свой собственный набор месяцев?

Причина, по которой ваш list(rrule(MONTHLY, dtstart=datetime(2015, 12, 31), until=datetime(2016,01,01))) не возвращается Январь, потому что не существует месяца (на основе MONTHLY параметр) с 31 декабря по 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)] 

Я сделал это с помощью наборов:

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

Я думаю, вам придется выполнить какую-то итерацию. Например, используя 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)] 

Просто используйте разницу в месяцах как счет:

 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))