Skip to content

Commit cdfadee

Browse files
authored
Merge pull request #1192 from NHSDigital/DTOSS-12370-improve-relative-date-formatting
Improve relative date formatting
2 parents b63cfc8 + 56dd285 commit cdfadee

3 files changed

Lines changed: 43 additions & 17 deletions

File tree

manage_breast_screening/core/utils/date_formatting.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def format_date(value):
2020
return value.strftime("%-d %B %Y")
2121

2222

23-
def format_relative_date(value: datetime | date):
23+
def format_relative_date(value: datetime | date, round_days=True):
2424
"""
2525
Format a date relative to today as a number of days.
2626
"""
@@ -30,7 +30,7 @@ def format_relative_date(value: datetime | date):
3030
today = date.today()
3131
days = (value - today).days
3232

33-
amount = _format_date_difference(value, today)
33+
amount = _format_date_difference(value, today, round_days=round_days)
3434

3535
if days < -1:
3636
return f"{amount} ago"
@@ -80,9 +80,25 @@ def format_year_with_relative(value: int | None):
8080
return str(value)
8181

8282

83-
def _format_date_difference(date1, date2):
83+
def _format_date_difference(date1, date2, round_days=True):
8484
diff = relativedelta(date1, date2) if date1 > date2 else relativedelta(date2, date1)
8585

86+
if round_days and diff.days and (diff.months or diff.years):
87+
# If the delta is at least 1 month, and we don't want the exact days,
88+
# then pretend that date1 is more recent than the true value so that
89+
# the month aligns with date2.
90+
#
91+
# If the delta is positive (date1 is in the future of date2) then
92+
# the formatted delta will be bigger than the true delta.
93+
#
94+
# If the delta is negative (date1 is in the past of date2) then
95+
# the formatted delta will be smaller than the true delta.
96+
diff.days = 0
97+
if date1 > date2:
98+
months = diff.months
99+
diff.months = (months + 1) % 12
100+
diff.years += (months + 1) // 12
101+
86102
parts = []
87103
if diff.years:
88104
parts.append("1 year" if diff.years == 1 else f"{diff.years} years")

manage_breast_screening/core/utils/tests/test_date_formatting.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,32 @@
1515

1616
@time_machine.travel(datetime(2025, 5, 2, 10, tzinfo=ZoneInfo("Europe/London")))
1717
@pytest.mark.parametrize(
18-
("dateiso", "output"),
18+
("dateiso", "round_days", "output"),
1919
(
20-
("2025-05-02T09:00:00", "today"),
21-
("2025-05-01T09:00:00", "yesterday"),
22-
("2025-05-01T11:59:00", "yesterday"),
23-
("2025-04-30T08:00:00", "2 days ago"),
24-
("2025-05-03T07:00:00", "tomorrow"),
25-
("2025-05-04T12:00:00", "in 2 days"),
26-
("2024-05-02T12:00:00", "1 year ago"),
27-
("2024-04-02T12:00:00", "1 year, 1 month ago"),
28-
("2024-03-31T12:00:00", "1 year, 1 month, 2 days ago"),
29-
("2026-03-31T12:00:00", "in 10 months, 29 days"),
20+
("2025-05-02T09:00:00", True, "today"),
21+
("2025-05-02T09:00:00", False, "today"),
22+
("2025-05-01T09:00:00", True, "yesterday"),
23+
("2025-05-01T11:59:00", True, "yesterday"),
24+
("2025-04-30T08:00:00", True, "2 days ago"),
25+
("2025-04-30T08:00:00", False, "2 days ago"),
26+
("2025-05-03T07:00:00", True, "tomorrow"),
27+
("2025-05-04T12:00:00", True, "in 2 days"),
28+
("2024-05-02T12:00:00", True, "1 year ago"),
29+
("2024-04-02T12:00:00", True, "1 year, 1 month ago"),
30+
("2024-03-31T12:00:00", False, "1 year, 1 month, 2 days ago"),
31+
("2024-03-31T12:00:00", True, "1 year, 1 month ago"),
32+
("2026-03-31T12:00:00", True, "in 11 months"),
33+
("2026-03-31T12:00:00", False, "in 10 months, 29 days"),
34+
("2026-04-30T12:00:00", True, "in 1 year"),
35+
("2026-04-30T12:00:00", False, "in 11 months, 28 days"),
36+
("2027-04-30T12:00:00", True, "in 2 years"),
3037
),
3138
)
32-
def test_relative_dates(dateiso, output):
33-
assert format_relative_date(datetime.fromisoformat(dateiso)) == output
39+
def test_relative_dates(dateiso, round_days, output):
40+
assert (
41+
format_relative_date(datetime.fromisoformat(dateiso), round_days=round_days)
42+
== output
43+
)
3444

3545

3646
@time_machine.travel(datetime(2025, 5, 2, 10, tzinfo=ZoneInfo("Europe/London")))

manage_breast_screening/mammograms/tests/presenters/test_appointment_presenters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ def test_slot_timestamp_multi_line(self, clinic_slot_mock):
757757

758758
assert (
759759
ClinicSlotPresenter(clinic_slot_mock).slot_timestamp_multi_line
760-
== "9:30am (30 minutes) - 2 January 2025 (4 months, 17 days ago)"
760+
== "9:30am (30 minutes) - 2 January 2025 (4 months ago)"
761761
)
762762

763763
@time_machine.travel(datetime(2025, 5, 19, tzinfo=tz.utc))

0 commit comments

Comments
 (0)