I've created a function to split a period into the biggest different time unit possible. It can be years
, months
, weeks
or days
.
However, it ended up being quite big and I feel it can be greatly improved, but I'm having difficulties finding ways to do it.
import calendar
from datetime import datetime, timedelta
def create_intervals(start_date, end_date):
start = datetime.strptime(start_date, "%Y-%m-%d")
end = datetime.strptime(end_date, "%Y-%m-%d")
di = []
# Year
if (sy := start.year) < (ey := end.year):
for y in range(sy, ey + 1):
if sy == y:
di.append((start_date, f"{y}-12-31"))
elif sy < y < ey:
di.append((f"{y}-01-01", f"{y}-12-31"))
else:
di.append((f"{y}-01-01", end_date))
# Month
elif (sm := start.month) < (em := end.month):
for m in range(sm, em + 1):
last_day = calendar.monthrange(sy, m)[1]
if sm == m:
di.append((start_date, f"{sy}-{m:02d}-{last_day}"))
elif sm < m < em:
di.append((f"{sy}-{m:02d}-01", f"{sy}-{m:02d}-{last_day}"))
else:
di.append((f"{sy}-{m:02d}-01", end_date))
# Week
elif (sw := start.isocalendar().week) < (ew := end.isocalendar().week):
for w in range(sw, ew + 1):
if sw == w:
last = start - timedelta(days=start.weekday()) + timedelta(days=6)
di.append((start_date, f"{sy}-{sm:02d}-{last.day:02d}"))
elif sw < w < ew:
wd = datetime.strptime(f"{sy}-W{w}-1", "%Y-W%W-%w")
first = wd - timedelta(days=wd.weekday())
last = wd - timedelta(days=wd.weekday()) + timedelta(days=6)
di.append((f"{sy}-{sm:02d}-{first.day:02d}", f"{sy}-{sm:02d}-{last.day:02d}"))
else:
first = end - timedelta(days=end.weekday())
di.append((f"{sy}-{sm:02d}-{first.day:02d}", end_date))
# Day
elif start.day < end.day:
for d in range(start.day, end.day + 1):
di.append((f"{sy}-{sm:02d}-{d:02d}", f"{sy}-{sm:02d}-{d:02d}"))
# None
else:
di.append((start_date, end_date))
return di
Example for years as biggest different time unit:
create_intervals("2021-10-22", "2023-03-02")
# Outputs intervals for each year:
# [("2021-10-22", "2021-12-31"),
# ("2022-01-01", "2022-12-31"),
# ("2023-01-01", "2023-03-02")]
Example for days as biggest different time unit:
create_intervals("2021-10-22", "2021-10-24")
# Outputs:
# [("2021-10-22", "2021-10-22"),
# ("2021-10-23", "2021-10-23"),
# ("2021-10-24", "2021-10-24")]