Мои небольшие изменения в теме (изначально я создавал начальный / конечный списки и упаковывал их в архивы для возврата кортежей, но я предпочел подход генератора @Karl Knechtel):
from datetime import date, timedelta
ONE_DAY = timedelta(days=1)
def find_date_windows(dates):
# guard against getting empty list
if not dates:
return
# convert strings to sorted list of datetime.dates
dates = sorted(date(*map(int,d.split('-'))) for d in dates)
# build list of window starts and matching ends
lastStart = lastEnd = dates[0]
for d in dates[1:]:
if d-lastEnd > ONE_DAY:
yield {'start_date':lastStart, 'end_date':lastEnd}
lastStart = d
lastEnd = d
yield {'start_date':lastStart, 'end_date':lastEnd}
Вот тестовые примеры:
tests = [
['2011-02-27', '2011-02-28', '2011-03-01', '2011-04-12', '2011-04-13', '2011-06-08'],
['2011-06-08'],
[],
['2011-02-27', '2011-02-28', '2011-03-01', '2011-04-12', '2011-04-13', '2011-06-08', '2011-06-10'],
]
for dates in tests:
print dates
for window in find_date_windows(dates):
print window
print
Печать:
['2011-02-27', '2011-02-28', '2011-03-01', '2011-04-12', '2011-04-13', '2011-06-08']
{'start_date': datetime.date(2011, 2, 27), 'end_date': datetime.date(2011, 3, 1)}
{'start_date': datetime.date(2011, 4, 12), 'end_date': datetime.date(2011, 4, 13)}
{'start_date': datetime.date(2011, 6, 8), 'end_date': datetime.date(2011, 6, 8)}
['2011-06-08']
{'start_date': datetime.date(2011, 6, 8), 'end_date': datetime.date(2011, 6, 8)}
[]
['2011-02-27', '2011-02-28', '2011-03-01', '2011-04-12', '2011-04-13', '2011-06-08', '2011-06-10']
{'start_date': datetime.date(2011, 2, 27), 'end_date': datetime.date(2011, 3, 1)}
{'start_date': datetime.date(2011, 4, 12), 'end_date': datetime.date(2011, 4, 13)}
{'start_date': datetime.date(2011, 6, 8), 'end_date': datetime.date(2011, 6, 8)}
{'start_date': datetime.date(2011, 6, 10), 'end_date': datetime.date(2011, 6, 10)}