Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

grass.temporal.datetime_math: Return a TypedDict from compute_datetime_delta #4700

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 31 additions & 14 deletions python/grass/temporal/datetime_math.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Functions for mathematical datetime operations

(C) 2011-2013 by the GRASS Development Team
(C) 2011-2024 by the GRASS Development Team
This program is free software under the GNU General Public
License (>=v2). Read the file COPYING that comes with GRASS
for details.
Expand All @@ -13,6 +13,7 @@

import copy
from datetime import datetime, timedelta
from typing import TypedDict

from .core import get_tgis_message_interface

Expand Down Expand Up @@ -490,7 +491,20 @@ def adjust_datetime_to_granularity(mydate: datetime, granularity):
###############################################################################


def compute_datetime_delta(start, end):
class datetime_delta(TypedDict):
"""Typed dictionary to return the accumulated delta in year, month, day,
hour, minute and second as well as max_days. At runtime, it is a plain dict."""

year: int
month: int
day: int
hour: int
minute: int
second: int
max_days: int


def compute_datetime_delta(start: datetime, end: datetime) -> datetime_delta:
"""Return a dictionary with the accumulated delta in year, month, day,
hour, minute and second

Expand Down Expand Up @@ -618,19 +632,25 @@ def compute_datetime_delta(start, end):
>>> compute_datetime_delta(start, end)
{'hour': 0, 'month': 12, 'second': 31622405, 'max_days': 366, 'year': 1, 'day': 0, 'minute': 0}

:return: A dictionary with year, month, day, hour, minute and second as
keys()
:return: A dictionary with year, month, day, hour, minute, second and max_days as keys()
""" # noqa: E501
comp = {}

day_diff = (end - start).days
# TODO: set default values here, and ensure processing below covers all situations,
# not leaking these default values
comp = datetime_delta(
year=0,
month=0,
day=0,
hour=0,
minute=0,
second=0,
max_days=(end - start).days,
)

comp["max_days"] = day_diff
day_diff = comp["max_days"]

# Date
# Count full years
d = end.year - start.year
comp["year"] = d
comp["year"] = end.year - start.year

# Count full months
if start.month == 1 and end.month == 1:
Expand All @@ -644,10 +664,7 @@ def compute_datetime_delta(start, end):
comp["month"] = d

# Count full days
if start.day == 1 and end.day == 1:
comp["day"] = 0
else:
comp["day"] = day_diff
comp["day"] = 0 if start.day == 1 and end.day == 1 else day_diff

# Time
# Hours
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
from datetime import datetime
from grass.temporal.datetime_math import compute_datetime_delta, datetime_delta


def test_datetime_delta_typeddict_dict() -> None:
assert datetime_delta(
month=3, day=2, minute=5, year=1, hour=8, max_days=455, second=30
) == dict( # noqa: C408
month=3, day=2, minute=5, year=1, hour=8, max_days=455, second=30
)


def test_datetime_delta_typeddict_dict_literal() -> None:
assert datetime_delta(
month=3, day=2, minute=5, year=1, hour=8, max_days=455, second=30
) == {
"month": 3,
"day": 2,
"minute": 5,
"year": 1,
"hour": 8,
"max_days": 455,
"second": 30,
}


def test_datetime_delta_typeddict_dict_different_order() -> None:
assert datetime_delta(
month=3, day=2, minute=5, year=1, hour=8, max_days=455, second=30
) == {
"max_days": 455,
"month": 3,
"minute": 5,
"year": 1,
"day": 2,
"hour": 8,
"second": 30,
}


def test_datetime_delta_typeddict_typeddict_different_order() -> None:
assert datetime_delta(
year=1,
month=3,
day=2,
hour=8,
minute=5,
second=30,
max_days=455,
) == datetime_delta(
month=3,
day=2,
minute=5,
year=1,
hour=8,
max_days=455,
second=30,
)


def test_datetime_delta_typeddict_dict_missing() -> None:
assert datetime_delta(
month=3, day=2, minute=5, year=1, hour=8, max_days=455, second=30
) != {"month": 3, "day": 2, "minute": 5, "hour": 8, "max_days": 455}


def test_compute_datetime_delta_same_date() -> None:
start = datetime(2001, 1, 1, 0, 0, 0)
end = datetime(2001, 1, 1, 0, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=0, hour=0, minute=0, second=0, max_days=0
)


def test_compute_datetime_delta_seconds_only() -> None:
start = datetime(2001, 1, 1, 0, 0, 14)
end = datetime(2001, 1, 1, 0, 0, 44)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=0, hour=0, minute=0, second=30, max_days=0
)


def test_compute_datetime_delta_minute_seconds() -> None:
start = datetime(2001, 1, 1, 0, 0, 44)
end = datetime(2001, 1, 1, 0, 1, 14)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=0, hour=0, minute=1, second=30, max_days=0
)


def test_compute_datetime_delta_minutes_seconds_same() -> None:
start = datetime(2001, 1, 1, 0, 0, 30)
end = datetime(2001, 1, 1, 0, 5, 30)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=0, hour=0, minute=5, second=300, max_days=0
)


def test_compute_datetime_delta_minute_only() -> None:
start = datetime(2001, 1, 1, 0, 0, 0)
end = datetime(2001, 1, 1, 0, 1, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=0, hour=0, minute=1, second=0, max_days=0
)


def test_compute_datetime_delta_hour_minutes_same() -> None:
start = datetime(2011, 10, 31, 0, 45, 0)
end = datetime(2011, 10, 31, 1, 45, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=0, hour=1, minute=60, second=0, max_days=0
)


def test_compute_datetime_delta_hour_minutes() -> None:
start = datetime(2011, 10, 31, 0, 45, 0)
end = datetime(2011, 10, 31, 1, 15, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=0, hour=1, minute=30, second=0, max_days=0
)


def test_compute_datetime_delta_hours_minutes() -> None:
start = datetime(2011, 10, 31, 0, 45, 0)
end = datetime(2011, 10, 31, 12, 15, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=0, hour=12, minute=690, second=0, max_days=0
)


def test_compute_datetime_delta_hour_only() -> None:
start = datetime(2011, 10, 31, 0, 0, 0)
end = datetime(2011, 10, 31, 1, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=0, hour=1, minute=0, second=0, max_days=0
)


def test_compute_datetime_delta_month_day_hour() -> None:
start = datetime(2011, 10, 31, 0, 0, 0)
end = datetime(2011, 11, 1, 1, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=1, hour=25, minute=0, second=0, max_days=1
)


def test_compute_datetime_delta_month_day_hours() -> None:
start = datetime(2011, 10, 31, 12, 0, 0)
end = datetime(2011, 11, 1, 6, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=0, hour=18, minute=0, second=0, max_days=0
)


def test_compute_datetime_delta_month_hour() -> None:
start = datetime(2011, 11, 1, 0, 0, 0)
end = datetime(2011, 12, 1, 1, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=1, day=0, hour=721, minute=0, second=0, max_days=30
)


def test_compute_datetime_delta_days_only() -> None:
start = datetime(2011, 11, 1, 0, 0, 0)
end = datetime(2011, 11, 5, 0, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=4, hour=0, minute=0, second=0, max_days=4
)


def test_compute_datetime_delta_month_days_less_than_month() -> None:
start = datetime(2011, 10, 6, 0, 0, 0)
end = datetime(2011, 11, 5, 0, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=30, hour=0, minute=0, second=0, max_days=30
)


def test_compute_datetime_delta_year_month_days_less_than_month() -> None:
start = datetime(2011, 12, 2, 0, 0, 0)
end = datetime(2012, 1, 1, 0, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=1, month=0, day=30, hour=0, minute=0, second=0, max_days=30
)


def test_compute_datetime_delta_month_only() -> None:
start = datetime(2011, 1, 1, 0, 0, 0)
end = datetime(2011, 2, 1, 0, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=1, day=0, hour=0, minute=0, second=0, max_days=31
)


def test_compute_datetime_delta_year_month() -> None:
start = datetime(2011, 12, 1, 0, 0, 0)
end = datetime(2012, 1, 1, 0, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=1, month=1, day=0, hour=0, minute=0, second=0, max_days=31
)


def test_compute_datetime_delta_year_months() -> None:
start = datetime(2011, 12, 1, 0, 0, 0)
end = datetime(2012, 6, 1, 0, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=1, month=6, day=0, hour=0, minute=0, second=0, max_days=183
)


def test_compute_datetime_delta_years_only() -> None:
start = datetime(2011, 6, 1, 0, 0, 0)
end = datetime(2021, 6, 1, 0, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=10, month=120, day=0, hour=0, minute=0, second=0, max_days=3653
)


def test_compute_datetime_delta_year_hours() -> None:
start = datetime(2011, 6, 1, 0, 0, 0)
end = datetime(2012, 6, 1, 12, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=1, month=12, day=0, hour=8796, minute=0, second=0, max_days=366
)


def test_compute_datetime_delta_year_hours_minutes() -> None:
start = datetime(2011, 6, 1, 0, 0, 0)
end = datetime(2012, 6, 1, 12, 30, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=1, month=12, day=0, hour=8796, minute=527790, second=0, max_days=366
)


def test_compute_datetime_delta_year_hours_seconds() -> None:
start = datetime(2011, 6, 1, 0, 0, 0)
end = datetime(2012, 6, 1, 12, 0, 5)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=1, month=12, day=0, hour=8796, minute=0, second=31665605, max_days=366
)


def test_compute_datetime_delta_year_minutes() -> None:
start = datetime(2011, 6, 1, 0, 0, 0)
end = datetime(2012, 6, 1, 0, 30, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=1, month=12, day=0, hour=0, minute=527070, second=0, max_days=366
)


def test_compute_datetime_delta_year_seconds() -> None:
start = datetime(2011, 6, 1, 0, 0, 0)
end = datetime(2012, 6, 1, 0, 0, 5)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=1, month=12, day=0, hour=0, minute=0, second=31622405, max_days=366
)


def test_compute_datetime_delta_month_full() -> None:
start = datetime(2011, 7, 3, 0, 0, 0)
end = datetime(2011, 8, 2, 0, 0, 0)
comp: datetime_delta = compute_datetime_delta(start, end)
assert comp == datetime_delta(
year=0, month=0, day=30, hour=0, minute=0, second=0, max_days=30
)
Loading
Loading