diff --git a/pyiceberg/utils/datetime.py b/pyiceberg/utils/datetime.py index 0cb6926efa..29fdb0a724 100644 --- a/pyiceberg/utils/datetime.py +++ b/pyiceberg/utils/datetime.py @@ -155,12 +155,14 @@ def to_human_time(micros_from_midnight: int) -> str: def to_human_timestamptz(timestamp_micros: int) -> str: """Convert a TimestamptzType value to human string.""" - return (EPOCH_TIMESTAMPTZ + timedelta(microseconds=timestamp_micros)).isoformat() + dt = micros_to_timestamptz(timestamp_micros) + return _to_java_offsetdatetime_str(dt) def to_human_timestamp(timestamp_micros: int) -> str: """Convert a TimestampType value to human string.""" - return (EPOCH_TIMESTAMP + timedelta(microseconds=timestamp_micros)).isoformat() + dt = micros_to_timestamp(timestamp_micros) + return _to_java_localdatetime_str(dt) def micros_to_hours(micros: int) -> int: @@ -184,3 +186,25 @@ def days_to_years(days: int) -> int: def micros_to_years(micros: int) -> int: return micros_to_timestamp(micros).year - EPOCH_TIMESTAMP.year + + +def _to_java_localdatetime_str(dt: datetime) -> str: + if dt.microsecond == 0: + if dt.second == 0: + return dt.strftime("%Y-%m-%dT%H:%M") + else: + return dt.strftime("%Y-%m-%dT%H:%M:%S") + return dt.strftime("%Y-%m-%dT%H:%M:%S.%f").rstrip("0") + + +def _to_java_offsetdatetime_str(dt: datetime) -> str: + if dt.tzinfo is None: + raise ValueError(f"Missing zone offset: {dt}") + + tz = dt.strftime("%z") + if tz == "+0000": + tz = "Z" + else: + tz = tz[:3] + ":" + tz[3:] + + return _to_java_localdatetime_str(dt) + tz diff --git a/tests/test_transforms.py b/tests/test_transforms.py index 51e8e23953..5963a7128d 100644 --- a/tests/test_transforms.py +++ b/tests/test_transforms.py @@ -354,7 +354,9 @@ def test_satisfies_order_of_method(transform: TimeTransform[Any], other_transfor (LongType(), None, "null"), (DateType(), 17501, "2017-12-01"), (TimeType(), 36775038194, "10:12:55.038194"), - (TimestamptzType(), 1512151975038194, "2017-12-01T18:12:55.038194+00:00"), + (TimestamptzType(), 1735689600000000, "2025-01-01T00:00Z"), + (TimestamptzType(), 1512151975038194, "2017-12-01T18:12:55.038194Z"), + (TimestampType(), 1735689600000000, "2025-01-01T00:00"), (TimestampType(), 1512151975038194, "2017-12-01T18:12:55.038194"), (LongType(), -1234567890000, "-1234567890000"), (StringType(), "a/b/c=d", "a/b/c=d"),