diff --git a/snuba/util.py b/snuba/util.py index 6d6b73f27d..0a08b8611d 100644 --- a/snuba/util.py +++ b/snuba/util.py @@ -113,7 +113,7 @@ def get_re(format: Sequence[PartSegment]) -> Pattern[Any]: if date_str and retention_days: return Part( part_str, - datetime.strptime(date_str, "%Y-%m-%d").astimezone(UTC), + datetime.strptime(date_str, "%Y-%m-%d").replace(tzinfo=UTC), int(retention_days), ) diff --git a/tests/test_util.py b/tests/test_util.py index 08f48076b3..b0ae674c79 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,4 +1,11 @@ +import time +from collections.abc import Generator +from datetime import UTC, datetime + +import pytest + from snuba.clickhouse.escaping import escape_alias, escape_identifier +from snuba.util import PartSegment, decode_part_str def test_escape_identifier() -> None: @@ -21,3 +28,21 @@ def test_escape_alias() -> None: assert escape_alias("foo") == "foo" assert escape_alias("foo.bar") == "`foo.bar`" assert escape_alias("foo:bar") == "`foo:bar`" + + +@pytest.fixture +def local_timezone(monkeypatch: pytest.MonkeyPatch) -> Generator[None]: + # A zone east of UTC, where local midnight falls on the previous UTC day. + with monkeypatch.context() as m: + m.setenv("TZ", "Asia/Tokyo") + time.tzset() + yield + time.tzset() + + +@pytest.mark.usefixtures("local_timezone") +def test_decode_part_str_ignores_local_timezone() -> None: + part = decode_part_str("(90,'2026-10-12')", [PartSegment.RETENTION_DAYS, PartSegment.DATE]) + assert part.date == datetime(2026, 10, 12, tzinfo=UTC) + assert part.date.weekday() == 0 + assert part.retention_days == 90