This is an automated email from the ASF dual-hosted git repository.
kevinjqliu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-python.git
The following commit(s) were added to refs/heads/main by this push:
new 098174c2 Fix for ns timestamp non utc (#3142)
098174c2 is described below
commit 098174c2fbcf9dcbc94c2ef9277e05f5e862de1f
Author: Neelesh Salian <[email protected]>
AuthorDate: Thu Mar 12 10:36:21 2026 -0700
Fix for ns timestamp non utc (#3142)
Closes #3127
# Rationale for this change
`pa.timestamp("ns", tz="US/Pacific") converts to TimestampNanoType()`
(tz-naive) instead of raising `TypeError`. The `us` path correctly
rejects non-UTC timezones.
raises TypeError
`visit_pyarrow(pa.timestamp("us", tz="US/Pacific"),
_ConvertToIceberg())`
silently drops timezone
`visit_pyarrow(pa.timestamp("ns", tz="US/Pacific"),
_ConvertToIceberg(format_version=3))`
Fixes this by adding the correct elif clause
## Are these changes tested?
Yes - added a couple of tests in the pyarrow visitor
## Are there any user-facing changes?
It fixes the behavior that was a bug, so I think it would be.
---
pyiceberg/io/pyarrow.py | 2 +-
tests/io/test_pyarrow_visitor.py | 13 +++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/pyiceberg/io/pyarrow.py b/pyiceberg/io/pyarrow.py
index 0dfc5eb5..8f22261f 100644
--- a/pyiceberg/io/pyarrow.py
+++ b/pyiceberg/io/pyarrow.py
@@ -1451,7 +1451,7 @@ class _ConvertToIceberg(PyArrowSchemaVisitor[IcebergType
| Schema]):
elif self._format_version >= 3:
if primitive.tz in UTC_ALIASES:
return TimestamptzNanoType()
- else:
+ elif primitive.tz is None:
return TimestampNanoType()
else:
raise TypeError(
diff --git a/tests/io/test_pyarrow_visitor.py b/tests/io/test_pyarrow_visitor.py
index 433350c2..6727b8c7 100644
--- a/tests/io/test_pyarrow_visitor.py
+++ b/tests/io/test_pyarrow_visitor.py
@@ -63,6 +63,7 @@ from pyiceberg.types import (
NestedField,
StringType,
StructType,
+ TimestampNanoType,
TimestampType,
TimestamptzType,
TimeType,
@@ -226,6 +227,18 @@ def test_pyarrow_timestamp_tz_invalid_tz() -> None:
visit_pyarrow(pyarrow_type, _ConvertToIceberg())
+def test_pyarrow_timestamp_ns_tz_invalid_tz() -> None:
+ pyarrow_type = pa.timestamp(unit="ns", tz="US/Pacific")
+ with pytest.raises(TypeError, match=re.escape("Unsupported type:
timestamp[ns, tz=US/Pacific]")):
+ visit_pyarrow(pyarrow_type, _ConvertToIceberg(format_version=3))
+
+
+def test_pyarrow_timestamp_ns_no_tz_accepted() -> None:
+ pyarrow_type = pa.timestamp(unit="ns")
+ converted = visit_pyarrow(pyarrow_type,
_ConvertToIceberg(format_version=3))
+ assert converted == TimestampNanoType()
+
+
@pytest.mark.parametrize("pyarrow_type", [pa.string(), pa.large_string(),
pa.string_view()])
def test_pyarrow_string_to_iceberg(pyarrow_type: pa.DataType) -> None:
converted_iceberg_type = visit_pyarrow(pyarrow_type, _ConvertToIceberg())