This is an automated email from the ASF dual-hosted git repository.

JackieTien97 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 7dcad2b6b44 Fix Python client CI: handle Timestamps outside Python 
stdlib range (#17715)
7dcad2b6b44 is described below

commit 7dcad2b6b449b9cda07cd8f8662e228664fc2991
Author: Jackie Tien <[email protected]>
AuthorDate: Tue May 19 12:07:50 2026 +0800

    Fix Python client CI: handle Timestamps outside Python stdlib range (#17715)
---
 iotdb-client/client-py/iotdb/utils/rpc_utils.py | 56 +++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 3 deletions(-)

diff --git a/iotdb-client/client-py/iotdb/utils/rpc_utils.py 
b/iotdb-client/client-py/iotdb/utils/rpc_utils.py
index 7b292737f0c..0912fd14d95 100644
--- a/iotdb-client/client-py/iotdb/utils/rpc_utils.py
+++ b/iotdb-client/client-py/iotdb/utils/rpc_utils.py
@@ -79,15 +79,34 @@ def 
verify_success_with_redirection_for_multi_devices(status: TSStatus, devices:
 
 def convert_to_timestamp(time: int, precision: str, timezone: str):
     try:
-        return pd.Timestamp(time, unit=precision, tz=timezone)
+        ts = pd.Timestamp(time, unit=precision, tz=timezone)
     except OutOfBoundsDatetime:
-        return pd.Timestamp(time, unit=precision).tz_localize(timezone)
+        try:
+            ts = pd.Timestamp(time, unit=precision).tz_localize(timezone)
+        except NotImplementedError:
+            return pd.Timestamp(time, unit=precision)
     except ValueError:
         logger.warning(
             f"Timezone string '{timezone}' cannot be recognized by pandas. "
             f"Falling back to local timezone: '{get_localzone_name()}'."
         )
-        return pd.Timestamp(time, unit=precision, tz=get_localzone_name())
+        ts = pd.Timestamp(time, unit=precision, tz=get_localzone_name())
+    except NotImplementedError:
+        # Timestamp falls outside Python's stdlib datetime range (year < 1 or
+        # > 9999). pandas >= 3.0 cannot attach a timezone to such Timestamps
+        # because tz conversion relies on toordinal(). Return naive instead.
+        return pd.Timestamp(time, unit=precision)
+    # Construction succeeded but utcoffset() may still fail downstream (e.g.
+    # in pd.DataFrame's tz alignment) when the Timestamp's year is outside
+    # 1..9999 and tz is not the canonical UTC. Probe early and fall back to
+    # naive so callers like result_set_to_pandas() don't blow up. NaT does
+    # not need this check (and does not support utcoffset()).
+    if ts is not pd.NaT:
+        try:
+            ts.utcoffset()
+        except NotImplementedError:
+            return pd.Timestamp(time, unit=precision)
+    return ts
 
 
 unit_map = {
@@ -108,3 +127,34 @@ def isoformat(ts: pd.Timestamp, unit: str):
             f"Falling back to use auto timespec'."
         )
         return ts.isoformat()
+    except NotImplementedError:
+        # Timestamp falls outside Python's stdlib datetime range. pandas >= 3.0
+        # routes isoformat through datetime.isoformat, which calls toordinal()
+        # and fails. Build the ISO 8601 string from individual components.
+        return _isoformat_from_components(ts, unit)
+
+
+def _isoformat_from_components(ts: pd.Timestamp, unit: str) -> str:
+    base = (
+        f"{ts.year:04d}-{ts.month:02d}-{ts.day:02d}"
+        f"T{ts.hour:02d}:{ts.minute:02d}:{ts.second:02d}"
+    )
+    if unit == "ms":
+        base += f".{ts.microsecond // 1000:03d}"
+    elif unit == "us":
+        base += f".{ts.microsecond:06d}"
+    elif unit == "ns":
+        base += f".{ts.microsecond:06d}{ts.nanosecond:03d}"
+    if ts.tzinfo is not None:
+        try:
+            offset = ts.utcoffset()
+        except NotImplementedError:
+            # utcoffset() needs toordinal() for zones like Etc/UTC. Omit 
offset.
+            offset = None
+        if offset is not None:
+            total_seconds = int(offset.total_seconds())
+            sign = "+" if total_seconds >= 0 else "-"
+            total_seconds = abs(total_seconds)
+            hh, mm = divmod(total_seconds // 60, 60)
+            base += f"{sign}{hh:02d}:{mm:02d}"
+    return base

Reply via email to