Skip to content

[python] Normalize nested naive timestamps when writing Avro to object stores and HDFS - #10356

Merged
JingsongLi merged 1 commit into
apache:masterfrom
jackylee-ch:python-avro-nested-timestamp-objectstore
Oct 26, 2026
Merged

JingsongLi merged 1 commit into
apache:masterfrom
jackylee-ch:python-avro-nested-timestamp-objectstore

Conversation

@jackylee-ch

Copy link
Copy Markdown
Contributor

Purpose

LocalFileIO.write_avro recursively attaches UTC to naive datetimes nested in ROW/ARRAY/MAP values, but PyArrowFileIO (OSS/S3/GCS) and HdfsNativeFileIO normalized only top-level column values. On a non-UTC host, fastavro interprets a naive datetime using the host timezone, so a naive TIMESTAMP nested in a struct or list is persisted shifted by the host offset — silent data corruption on the object-store and HDFS Avro write paths that the local path already handled.

This moves the recursive normalizer onto FileIO and uses it in all three write_avro implementations.

Tests

data_types_test.py: the existing test_avro_nested_timestamp_roundtrips_on_non_utc_host (LocalFileIO) now exercises the shared helper; a new test_pyarrow_file_io_avro_normalizes_nested_naive_timestamps asserts a nested TIMESTAMP survives a PyArrowFileIO.write_avro round-trip under TZ=Asia/Shanghai. Disabling the recursion fails both.

API and Format

No change.

Documentation

No change.

@JingsongLi

Copy link
Copy Markdown
Contributor

Please rebase master.

@Akash3121 Akash3121 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jackylee-ch Rebase to master, code looks good.

@jackylee-ch
jackylee-ch force-pushed the python-avro-nested-timestamp-objectstore branch from 328b761 to df5b0f4 Compare October 26, 2026 00:41
…t stores and HDFS

LocalFileIO.write_avro recursively attaches UTC to naive datetimes nested in
ROW/ARRAY/MAP values, but PyArrowFileIO (OSS/S3/GCS) and HdfsNativeFileIO
normalized only top-level columns. On a non-UTC host, fastavro then interprets
a naive datetime nested in a struct or list using the host timezone, so the
persisted instant is shifted by the host offset -- silent data corruption on
the object-store and HDFS Avro write paths that the local path already handled.

Move the recursive normalizer to FileIO (common) and use it in all three
write_avro implementations. Add a PyArrowFileIO round-trip test alongside the
existing LocalFileIO one, both asserting a nested TIMESTAMP survives a write
under TZ=Asia/Shanghai.
@jackylee-ch
jackylee-ch force-pushed the python-avro-nested-timestamp-objectstore branch from df5b0f4 to 2797968 Compare October 26, 2026 08:02
@JingsongLi

Copy link
Copy Markdown
Contributor

+1

@JingsongLi
JingsongLi merged commit 3f5e9fc into apache:master Oct 26, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants