This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new 1b3a51ab21 [arrow] Fix second-precision timestamp conversion for
pre-epoch values (#9600)
1b3a51ab21 is described below
commit 1b3a51ab21c9ca5dc5ba57d63ca668504be81a6e
Author: Eunbin Son <[email protected]>
AuthorDate: Mon Sep 7 23:44:47 2026 +0900
[arrow] Fix second-precision timestamp conversion for pre-epoch values
(#9600)
---
.../java/org/apache/paimon/arrow/ArrowUtils.java | 2 +-
.../paimon/arrow/vector/ArrowFormatWriterTest.java | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/paimon-arrow/src/main/java/org/apache/paimon/arrow/ArrowUtils.java
b/paimon-arrow/src/main/java/org/apache/paimon/arrow/ArrowUtils.java
index 92812bbeab..298180de6b 100644
--- a/paimon-arrow/src/main/java/org/apache/paimon/arrow/ArrowUtils.java
+++ b/paimon-arrow/src/main/java/org/apache/paimon/arrow/ArrowUtils.java
@@ -325,7 +325,7 @@ public class ArrowUtils {
private static long nonCastedTimestampToEpoch(Timestamp timestamp, int
precision) {
if (precision == 0) {
- return timestamp.getMillisecond() / 1000;
+ return Math.floorDiv(timestamp.getMillisecond(), 1000L);
} else if (precision >= 1 && precision <= 3) {
return timestamp.getMillisecond();
} else if (precision >= 4 && precision <= 6) {
diff --git
a/paimon-arrow/src/test/java/org/apache/paimon/arrow/vector/ArrowFormatWriterTest.java
b/paimon-arrow/src/test/java/org/apache/paimon/arrow/vector/ArrowFormatWriterTest.java
index 1742b836c2..a13f7ee9b2 100644
---
a/paimon-arrow/src/test/java/org/apache/paimon/arrow/vector/ArrowFormatWriterTest.java
+++
b/paimon-arrow/src/test/java/org/apache/paimon/arrow/vector/ArrowFormatWriterTest.java
@@ -163,6 +163,26 @@ public class ArrowFormatWriterTest {
}
}
+ @Test
+ public void testWritePreEpochSecondPrecisionTimestamp() {
+ RowType rowType =
+ RowType.of(DataTypes.TIMESTAMP(0),
DataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(0));
+ try (ArrowFormatWriter writer = new ArrowFormatWriter(rowType, 16,
true)) {
+ // 1969-12-31T23:59:59.500, i.e. 500 millis before the epoch
+ Timestamp preEpoch = Timestamp.fromEpochMillis(-500);
+ writer.write(GenericRow.of(preEpoch, preEpoch));
+ writer.flush();
+
+ VectorSchemaRoot vectorSchemaRoot = writer.getVectorSchemaRoot();
+ ArrowBatchReader arrowBatchReader = new ArrowBatchReader(rowType,
true);
+ InternalRow row =
arrowBatchReader.readBatch(vectorSchemaRoot).iterator().next();
+
+ // sub-second millis must be truncated towards negative infinity,
not towards zero
+ assertThat(row.getTimestamp(0,
0).toString()).isEqualTo("1969-12-31T23:59:59");
+ assertThat(row.getTimestamp(1,
0).toString()).isEqualTo("1969-12-31T23:59:59");
+ }
+ }
+
@Test
public void testMissingMapColumnVectorizedRoundTrip() {
RowType inputRowType = RowType.builder().field("id",
DataTypes.INT()).build();