from datetime import datetime, timedelta
from typing import Iterable
from math import ceil
class DateTimeRange:
def __init__(self, start: datetime, end_:datetime, step:timedelta = timedelta(seconds=1)):
self._start = start
self._end = end_
self._step = step
def __iter__(self) -> Iterable[datetime]:
point = self._start
while point < self._end:
yield point
point += self._step
def __len__(self) -> int:
return ceil((self._end - self._start) / self._step)
def __contains__(self, item: datetime) -> bool:
mod = divmod(item - self._start, self._step) # divmod return the tuple (x//y, x%y). Invariant: div*y + mod == x.
return item >= self._start and item < self._end and mod[1] == timedelta(0)
def __getitem__(self, item: int) -> datetime:
n_steps = item if item >= 0 else len(self) + item
return_value = self._start + n_steps * self._step
if return_value not in self:
raise IndexError()
return return_value
def __str__(self):
return f"Datetime Range [{self._start}, {self._end}) with step {self._step}"
def main():
my_range = DateTimeRange(datetime(2021,1,1), datetime(2021,12,1), timedelta(days=12))
print(my_range)
print(f"{len(my_range) == len(list(my_range)) = }")
print(f"{my_range[-2] in my_range = }")
print(f"{my_range[2] + timedelta(seconds=12) in my_range = }")
for r in my_range:
print(r)
#do_something(r)
if __name__ == '__main__':
main()