Created
January 24, 2022 10:05
-
-
Save adoankim/f23f0c4a0f66b5549eb596141304ee44 to your computer and use it in GitHub Desktop.
Datetime generator between to given dates and a step
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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