Skip to content

Commit 79a3160

Browse files
committed
Reject non-ZoneInfo tzinfo on Tz write; document read-side tzdata fallback
1 parent 146a629 commit 79a3160

3 files changed

Lines changed: 14 additions & 12 deletions

File tree

docs/types.rst

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,12 @@ Date and time
202202

203203
``TzDate``, ``TzDatetime`` and ``TzTimestamp`` carry an IANA timezone name.
204204
On write, pass a tz-aware ``datetime.datetime`` whose ``tzinfo`` is a
205-
``zoneinfo.ZoneInfo`` — its local wall-clock and zone name are stored. On
206-
read, they are returned as tz-aware ``datetime.datetime`` values (``TzDate``
207-
at midnight in that zone). When the matching
208-
``with_native_*_in_result_sets`` option is disabled, the raw
209-
``"<value>,<zone>"`` string is returned instead.
205+
``zoneinfo.ZoneInfo`` — its local wall-clock and zone name are stored; any
206+
other ``tzinfo`` raises ``ValueError``. On read, they are returned as
207+
tz-aware ``datetime.datetime`` values (``TzDate`` at midnight in that zone),
208+
or the raw ``"<value>,<zone>"`` string when the matching
209+
``with_native_*_in_result_sets`` option is disabled or the zone cannot be
210+
loaded from the system timezone database (e.g. no ``tzdata`` installed).
210211

211212
Other
212213
^^^^^

tests/query/test_types.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,11 @@ def test_type_str_repr(driver_sync, value, ydb_type, str_repr, result_value):
190190

191191

192192
def test_tz_conversion_fallbacks():
193-
# Defensive branches a real-server round-trip never reaches: an unresolvable
194-
# zone name is passed through as raw text, and a non-ZoneInfo tzinfo falls
195-
# back to its str() name.
193+
# Edge branches a real-server round-trip never reaches: an unresolvable zone
194+
# name is passed through as raw text on read, and a non-ZoneInfo tzinfo is
195+
# rejected on write.
196196
from ydb.types import _parse_tz, _tz_name
197197

198198
assert _parse_tz("2019-09-16T18:24:00,Not/AZone") == "2019-09-16T18:24:00,Not/AZone"
199-
assert _tz_name(datetime(2019, 9, 17, tzinfo=timezone.utc)) == "UTC"
199+
with pytest.raises(ValueError):
200+
_tz_name(datetime(2019, 9, 17, tzinfo=tz4h))

ydb/types.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ def _to_datetime64(pb: ydb_value_pb2.Value, value: typing.Union[datetime, int])
8383

8484
def _tz_name(value: datetime) -> str:
8585
tz = value.tzinfo
86-
if isinstance(tz, ZoneInfo):
87-
return tz.key
88-
return str(tz)
86+
if not isinstance(tz, ZoneInfo):
87+
raise ValueError(f"Tz types require a datetime whose tzinfo is a zoneinfo.ZoneInfo, got {tz!r}")
88+
return tz.key
8989

9090

9191
def _parse_tz(value: str) -> typing.Union[datetime, str]:

0 commit comments

Comments
 (0)