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 9c0432797b [common] Fix negative time-of-day when casting pre-epoch 
timestamp to TIME (#8769)
9c0432797b is described below

commit 9c0432797bb34cf4a24971de0ca88289399d666a
Author: Eunbin Son <[email protected]>
AuthorDate: Tue Jul 21 14:15:10 2026 +0900

    [common] Fix negative time-of-day when casting pre-epoch timestamp to TIME 
(#8769)
---
 .../paimon/casting/TimestampToTimeCastRule.java    |  3 ++-
 .../apache/paimon/casting/CastExecutorTest.java    | 24 ++++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git 
a/paimon-common/src/main/java/org/apache/paimon/casting/TimestampToTimeCastRule.java
 
b/paimon-common/src/main/java/org/apache/paimon/casting/TimestampToTimeCastRule.java
index ec8822f2b9..cc5c2e1876 100644
--- 
a/paimon-common/src/main/java/org/apache/paimon/casting/TimestampToTimeCastRule.java
+++ 
b/paimon-common/src/main/java/org/apache/paimon/casting/TimestampToTimeCastRule.java
@@ -45,7 +45,8 @@ class TimestampToTimeCastRule extends 
AbstractCastRule<Timestamp, Number> {
     @Override
     public CastExecutor<Timestamp, Number> create(DataType inputType, DataType 
targetType) {
         if (inputType.is(DataTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE)) {
-            return value -> (int) (value.getMillisecond() % 
DateTimeUtils.MILLIS_PER_DAY);
+            return value ->
+                    (int) Math.floorMod(value.getMillisecond(), 
DateTimeUtils.MILLIS_PER_DAY);
         } else if (inputType.is(DataTypeRoot.TIMESTAMP_WITH_LOCAL_TIME_ZONE)) {
             return value ->
                     DateTimeUtils.timestampWithLocalZoneToTime(value, 
TimeZone.getDefault());
diff --git 
a/paimon-common/src/test/java/org/apache/paimon/casting/CastExecutorTest.java 
b/paimon-common/src/test/java/org/apache/paimon/casting/CastExecutorTest.java
index 0bcc455986..7a4ddc7097 100644
--- 
a/paimon-common/src/test/java/org/apache/paimon/casting/CastExecutorTest.java
+++ 
b/paimon-common/src/test/java/org/apache/paimon/casting/CastExecutorTest.java
@@ -51,6 +51,7 @@ import org.apache.paimon.utils.DecimalUtils;
 
 import org.junit.jupiter.api.Test;
 
+import java.time.LocalDateTime;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -826,6 +827,29 @@ public class CastExecutorTest {
                 DateTimeUtils.timestampWithLocalZoneToTime(timestamp, 
TimeZone.getDefault()));
     }
 
+    @Test
+    public void testTimestampToTimePreEpoch() {
+        CastExecutor<?, ?> cast = CastExecutors.resolve(new TimestampType(3), 
new TimeType(3));
+
+        // pre-epoch 1969-12-31 23:00:00 -> time-of-day 23:00:00 == 82_800_000 
ms
+        compareCastResult(
+                cast,
+                Timestamp.fromLocalDateTime(LocalDateTime.of(1969, 12, 31, 23, 
0, 0)),
+                82800000);
+
+        // pre-epoch 1969-12-31 12:34:56.789 -> 12*3600000 + 34*60000 + 
56*1000 + 789
+        compareCastResult(
+                cast,
+                Timestamp.fromLocalDateTime(LocalDateTime.of(1969, 12, 31, 12, 
34, 56, 789000000)),
+                45296789);
+
+        // post-epoch 1970-01-01 10:00:00 -> 36_000_000 ms (unchanged behavior)
+        compareCastResult(
+                cast,
+                Timestamp.fromLocalDateTime(LocalDateTime.of(1970, 1, 1, 10, 
0, 0)),
+                36000000);
+    }
+
     @Test
     public void testDateToTimestamp() {
         String date = "2023-06-06";

Reply via email to