fluttersmith/py-snippetsGitHub ↗

Iterate over a range of dates

Yield the dates from start up to end, like range() for days, with an optional step.

Dates#calendar#iterationO(1) time✓ 4 examples pass on 3.11–3.14

Days in a billing period, weeks in a year, dates on a chart axis.

daterange.py✓ ruff · mypy --strict
from collections.abc import Iterator
from datetime import date, timedelta


def daterange(start: date, end: date, step: int = 1) -> Iterator[date]:
    """Yield dates from ``start`` up to, but not including, ``end``."""
    if step < 1:
        raise ValueError(f"step must be at least 1 day, got {step}")
    for offset in range(0, (end - start).days, step):
        yield start + timedelta(days=offset)
  1. like range(): end is excluded, and it's lazy
examples✓ 4 doctests · 3.11–3.14
passed on Python 3.11 to 3.14: >>> from datetime import datepassed on Python 3.11 to 3.14: >>> [d.isoformat() for d in daterange(date(2024, 2, 27), date(2024, 3, 2))]['2024-02-27', '2024-02-28', '2024-02-29', '2024-03-01']passed on Python 3.11 to 3.14: >>> len(list(daterange(date(2024, 1, 1), date(2025, 1, 1), step=7)))53passed on Python 3.11 to 3.14: >>> list(daterange(date(2024, 1, 2), date(2024, 1, 1)))[]
Edit the function or the examples and run the doctests here, on Python 3.14. Python loads only when you click (about 7 MB, cached after the first time).

How it works

  • (end - start).days is the number of days between the dates.
  • range does the stepping; timedelta turns each offset into a date.
  • Like range, the end is excluded and a backwards range is empty.

Complexity: O(1) per date, lazy

Importfrom pysnippets.dates.daterange import daterangeNo dependencies: copy daterange.py into your project, or clone the repo.

Adapted from daterange in 30-seconds-of-python by the 30 seconds of code contributors, CC BY 4.0. Changed: A lazy generator with a step; typed. Suggest an edit.