diff --git a/l4d2web/l4d2web/services/timeago.py b/l4d2web/l4d2web/services/timeago.py index c3face6..eb329fe 100644 --- a/l4d2web/l4d2web/services/timeago.py +++ b/l4d2web/l4d2web/services/timeago.py @@ -1,5 +1,7 @@ from datetime import UTC, datetime +from markupsafe import Markup, escape + _MONTHS = ( "Jan", "Feb", "Mar", "Apr", "May", "Jun", @@ -51,3 +53,18 @@ def humanize_delta(then: datetime, now: datetime | None = None) -> str: return _format_date(then, now) return _relative_label(abs_seconds, past=(delta_seconds > 0)) + + +def format_time_html(then: datetime, now: datetime | None = None) -> Markup: + if now is None: + now = datetime.now(UTC) + then_utc = _ensure_utc(then).astimezone(UTC) + now = _ensure_utc(now) + + label = humanize_delta(then_utc, now=now) + iso = then_utc.isoformat() + title = then_utc.strftime("%Y-%m-%d %H:%M:%S UTC") + return Markup( + f'" + ) diff --git a/l4d2web/tests/test_timeago.py b/l4d2web/tests/test_timeago.py index 274cbab..e02d6ed 100644 --- a/l4d2web/tests/test_timeago.py +++ b/l4d2web/tests/test_timeago.py @@ -1,8 +1,9 @@ from datetime import UTC, datetime, timedelta import pytest +from markupsafe import Markup -from l4d2web.services.timeago import humanize_delta +from l4d2web.services.timeago import format_time_html, humanize_delta NOW = datetime(2026, 5, 16, 12, 0, 0, tzinfo=UTC) @@ -82,3 +83,35 @@ def test_humanize_delta_year_boundary_includes_year_when_years_differ(): now = datetime(2026, 1, 15, 12, 0, 0, tzinfo=UTC) then = datetime(2025, 11, 15, 12, 0, 0, tzinfo=UTC) assert humanize_delta(then, now=now) == "15 Nov 2025" + + +def test_format_time_html_returns_markup(): + then = NOW - timedelta(minutes=5) + out = format_time_html(then, now=NOW) + assert isinstance(out, Markup) + + +def test_format_time_html_contains_time_element_with_attrs(): + then = datetime(2026, 5, 16, 14, 32, 11, tzinfo=UTC) + now = then + timedelta(minutes=5) + out = str(format_time_html(then, now=now)) + assert out.startswith("