Skip to content

Instantly share code, notes, and snippets.

@adoankim
Created January 24, 2022 10:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adoankim/f23f0c4a0f66b5549eb596141304ee44 to your computer and use it in GitHub Desktop.
Save adoankim/f23f0c4a0f66b5549eb596141304ee44 to your computer and use it in GitHub Desktop.
Datetime generator between to given dates and a step
from typing import Iterator
from datetime import datetime, timedelta, timezone
def gen_dates(
start_datetime: datetime,
end_datetime: datetime,
delta: timedelta = timedelta(hours = 1)
) -> Iterator[datetime]:
"""
Generate datetimes between two given datetimes with a given delta step
Parameters:
start_datetime (datetime): start date from where sequence will start
end_datetime (datetime): end date from where sequence will finish, this date inclusive.
delta (timedelta): step that will be taken from start to end.
it will generate dates backwards if negative.
Yields:
datetime: a datetime that is between start_datetime end_datetime
"""
if start_datetime > end_datetime:
start_datetime, end_datetime = end_datetime, start_datetime
if (start_datetime + delta) < start_datetime:
start_datetime, end_datetime = end_datetime, start_datetime
checker = lambda current, end: current >= end
else:
checker = lambda current, end: current <= end
while checker(start_datetime, end_datetime):
yield start_datetime
start_datetime = start_datetime + delta
def tests():
print("Generating 5 datetimes between to given dates")
start_date = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
end_date = start_date + timedelta(hours=4)
expected = [0, 1, 2, 3, 4]
result = list(map(lambda d: d.hour, gen_dates(start_date, end_date)))
assert expected == result, f"From midnight to 4am there should be 4 hours: expected={expected}, got={result}"
print("Generating 5 datetimes backwards between to given dates")
start_date = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
end_date = start_date + timedelta(hours=4)
expected = list(reversed([0, 1, 2, 3, 4]))
result = list(map(lambda d: d.hour, gen_dates(start_date, end_date, delta=timedelta(hours=-1))))
assert expected == result, f"From 4am to midnight in backwards there should be 4 hours: expected={expected}, got={result}"
print("Swapping date boundaries shouldn't affect on the result")
start_date = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
end_date = start_date + timedelta(hours=4)
expected = [0, 1, 2, 3, 4]
result = list(map(lambda d: d.hour, gen_dates(end_date, start_date)))
assert expected == result, f"From midnight to 4am there should be 4 hours: expected={expected}, got={result}"
print("If boundaries are the same date we get only that date generated")
start_date = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
expected = [0]
result = list(map(lambda d: d.hour, gen_dates(start_date, start_date)))
assert expected == result, f"With a large step we get only the start date, expected={expected}, got={result}"
print("If the step between the boundaries is greater than the different between them we get only the start date generated")
start_date = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
end_date = start_date + timedelta(hours=4)
delta = timedelta(hours=5)
expected = [0]
result = list(map(lambda d: d.hour, gen_dates(end_date, start_date, delta=delta)))
assert expected == result, f"With a large step we get only the start date, expected={expected}, got={result}"
tests()
def sample():
start_date = datetime.now(timezone.utc).replace(minute=0, second=0, microsecond=0)
end_date = start_date + timedelta(hours=4)
print(f"Dates between {start_date} and {end_date}")
for d in gen_dates(start_date, end_date):
print(d)
# Backwards generation
print(f"Backward dates between {start_date} and {end_date}")
for d in gen_dates(start_date, end_date, delta=timedelta(hours=-1)):
print(d)
sample()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment