From e38e357f63f4819eef320e814d90fe4c312db0d5 Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Sun, 7 Jul 2024 12:01:21 +0100 Subject: [PATCH 1/3] No need for DateOrDateTime type alias --- agenda/utils.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/agenda/utils.py b/agenda/utils.py index ff311d0..eb66a74 100644 --- a/agenda/utils.py +++ b/agenda/utils.py @@ -2,10 +2,8 @@ from datetime import date, datetime, timezone -DateOrDateTime = datetime | date - -def as_date(d: DateOrDateTime) -> date: +def as_date(d: datetime | date) -> date: """Convert datetime to date.""" match d: case datetime(): @@ -16,7 +14,7 @@ def as_date(d: DateOrDateTime) -> date: raise TypeError(f"Unsupported type: {type(d)}") -def as_datetime(d: DateOrDateTime) -> datetime: +def as_datetime(d: datetime | date) -> datetime: """Date/time of event.""" match d: case datetime(): From 128d7ac282db90999da56bee833cf426a059d453 Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Sun, 7 Jul 2024 12:01:56 +0100 Subject: [PATCH 2/3] Add support for plural/singular time periods --- agenda/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agenda/utils.py b/agenda/utils.py index eb66a74..e8f124d 100644 --- a/agenda/utils.py +++ b/agenda/utils.py @@ -49,10 +49,10 @@ def human_readable_delta(future_date: date) -> str | None: # Formatting the output parts = [] if months > 0: - parts.append(f"{months} months") + parts.append(f"{months} month{'s' if months > 1 else ''}") if weeks > 0: - parts.append(f"{weeks} weeks") + parts.append(f"{weeks} week{'s' if weeks > 1 else ''}") if days > 0: - parts.append(f"{days} days") + parts.append(f"{days} day{'s' if days > 1 else ''}") return " ".join(parts) if parts else None From e6770825606a3aaa160e353ae5a8f572abf660c8 Mon Sep 17 00:00:00 2001 From: Edward Betts Date: Sun, 7 Jul 2024 12:02:21 +0100 Subject: [PATCH 3/3] Add tests for utility functions --- tests/test_utils.py | 96 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 tests/test_utils.py diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..a1ed866 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,96 @@ +"""Test utility functions.""" + +from datetime import date, datetime, timedelta, timezone + +import pytest +from agenda.utils import as_date, as_datetime, human_readable_delta +from freezegun import freeze_time + + +def test_as_date_with_datetime() -> None: + """Test converting a datetime object to a date.""" + dt = datetime(2024, 7, 7, 12, 0, 0, tzinfo=timezone.utc) + result = as_date(dt) + assert result == date(2024, 7, 7) + + +def test_as_date_with_date() -> None: + """Test passing a date object through as_date.""" + d = date(2024, 7, 7) + result = as_date(d) + assert result == d + + +def test_as_date_with_invalid_type() -> None: + """Test as_date with an invalid type, expecting a TypeError.""" + with pytest.raises(TypeError): + as_date("2024-07-07") + + +def test_as_datetime_with_datetime() -> None: + """Test passing a datetime object through as_datetime.""" + dt = datetime(2024, 7, 7, 12, 0, 0, tzinfo=timezone.utc) + result = as_datetime(dt) + assert result == dt + + +def test_as_datetime_with_date() -> None: + """Test converting a date object to a datetime.""" + d = date(2024, 7, 7) + result = as_datetime(d) + expected = datetime(2024, 7, 7, 0, 0, 0, tzinfo=timezone.utc) + assert result == expected + + +def test_as_datetime_with_invalid_type() -> None: + """Test as_datetime with an invalid type, expecting a TypeError.""" + with pytest.raises(TypeError): + as_datetime("2024-07-07") + + +@freeze_time("2024-07-01") +def test_human_readable_delta_future_date() -> None: + """Test human_readable_delta with a future date 45 days from today.""" + future_date = date.today() + timedelta(days=45) + result = human_readable_delta(future_date) + assert result == "1 month 2 weeks 1 day" + + +@freeze_time("2024-07-01") +def test_human_readable_delta_today() -> None: + """Test human_readable_delta with today's date, expecting None.""" + today = date.today() + result = human_readable_delta(today) + assert result is None + + +@freeze_time("2024-07-01") +def test_human_readable_delta_past_date() -> None: + """Test human_readable_delta with a past date, expecting None.""" + past_date = date.today() - timedelta(days=1) + result = human_readable_delta(past_date) + assert result is None + + +@freeze_time("2024-07-01") +def test_human_readable_delta_months_only() -> None: + """Test human_readable_delta with a future date 60 days from today.""" + future_date = date.today() + timedelta(days=60) + result = human_readable_delta(future_date) + assert result == "2 months" + + +@freeze_time("2024-07-01") +def test_human_readable_delta_weeks_only() -> None: + """Test human_readable_delta with a future date 14 days from today.""" + future_date = date.today() + timedelta(days=14) + result = human_readable_delta(future_date) + assert result == "2 weeks" + + +@freeze_time("2024-07-01") +def test_human_readable_delta_days_only() -> None: + """Test human_readable_delta with a future date 3 days from today.""" + future_date = date.today() + timedelta(days=3) + result = human_readable_delta(future_date) + assert result == "3 days"