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

raminqaf pushed a commit to branch release-2.2
in repository https://gitbox.apache.org/repos/asf/flink.git


The following commit(s) were added to refs/heads/release-2.2 by this push:
     new de3664ec022 [FLINK-41280][table] Fix CAST of a TIMESTAMP before 1970 
to DATE, TIME and a lower precision (#29774)
de3664ec022 is described below

commit de3664ec022118af20e03a96d1387b80716735bf
Author: Rui Fan <[email protected]>
AuthorDate: Wed Nov 4 11:54:07 2026 +0100

    [FLINK-41280][table] Fix CAST of a TIMESTAMP before 1970 to DATE, TIME and 
a lower precision (#29774)
    
    Three spots divided the epoch milliseconds with / or %, which round toward 
zero, so a TIMESTAMP before 1970 moved toward 1970: TimestampToDateCastRule for 
DATE, DateTimeUtils.timestampWithoutLocalZoneToTime for TIME, and 
DateTimeUtils.zeroLastDigits, which truncate() uses for a TIMESTAMP or 
TIMESTAMP_LTZ precision of 3 or less. Use floor division in all three. The 
other callers of zeroLastDigits pass the nano-of-millisecond or a TIME 
millis-of-day, which are never negative, so floor a [...]
    
    Generated-by: Claude Code 2.1.314 (Claude Opus 5.5)
    (cherry picked from commit 0196674040113fa18b8731e17817bbb8f0db8732)
    
    Co-authored-by: Ramin Gharib <[email protected]>
---
 .../main/java/org/apache/flink/table/utils/DateTimeUtils.java  |  4 ++--
 .../planner/functions/casting/TimestampToDateCastRule.java     |  6 +++---
 .../flink/table/planner/functions/CastFunctionITCase.java      | 10 ++++++++++
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git 
a/flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java
 
b/flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java
index aaf2b075266..18368182f18 100644
--- 
a/flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java
+++ 
b/flink-table/flink-table-common/src/main/java/org/apache/flink/table/utils/DateTimeUtils.java
@@ -1542,7 +1542,7 @@ public class DateTimeUtils {
     }
 
     public static int timestampWithoutLocalZoneToTime(TimestampData ts, int 
precision) {
-        final int millisecond = (int) (ts.getMillisecond() % 
DateTimeUtils.MILLIS_PER_DAY);
+        final int millisecond = (int) Math.floorMod(ts.getMillisecond(), 
MILLIS_PER_DAY);
         return applyTimePrecisionTruncation(millisecond, precision);
     }
 
@@ -1700,7 +1700,7 @@ public class DateTimeUtils {
 
     private static long zeroLastDigits(long l, int n) {
         long tenToTheN = (long) Math.pow(10, n);
-        return (l / tenToTheN) * tenToTheN;
+        return Math.floorDiv(l, tenToTheN) * tenToTheN;
     }
 
     public static long unixDateCeil(TimeUnitRange range, long date) {
diff --git 
a/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/functions/casting/TimestampToDateCastRule.java
 
b/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/functions/casting/TimestampToDateCastRule.java
index 0d3858f017c..168b43e84a0 100644
--- 
a/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/functions/casting/TimestampToDateCastRule.java
+++ 
b/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/functions/casting/TimestampToDateCastRule.java
@@ -26,7 +26,6 @@ import org.apache.flink.table.utils.DateTimeUtils;
 
 import static 
org.apache.flink.table.planner.functions.casting.CastRuleUtils.cast;
 import static 
org.apache.flink.table.planner.functions.casting.CastRuleUtils.methodCall;
-import static 
org.apache.flink.table.planner.functions.casting.CastRuleUtils.operator;
 import static 
org.apache.flink.table.planner.functions.casting.CastRuleUtils.staticCall;
 
 /**
@@ -57,9 +56,10 @@ class TimestampToDateCastRule
         if (inputLogicalType.is(LogicalTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE)) {
             return cast(
                     "int",
-                    operator(
+                    staticCall(
+                            Math.class,
+                            "floorDiv",
                             methodCall(inputTerm, "getMillisecond"),
-                            "/",
                             DateTimeUtils.MILLIS_PER_DAY));
         } else if 
(inputLogicalType.is(LogicalTypeRoot.TIMESTAMP_WITH_LOCAL_TIME_ZONE)) {
             return staticCall(
diff --git 
a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/CastFunctionITCase.java
 
b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/CastFunctionITCase.java
index a5b31c0dbac..f46ca41de20 100644
--- 
a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/CastFunctionITCase.java
+++ 
b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/functions/CastFunctionITCase.java
@@ -107,6 +107,8 @@ public class CastFunctionITCase extends 
BuiltInFunctionTestBase {
     private static final LocalDateTime DEFAULT_TIMESTAMP =
             LocalDateTime.parse("2021-09-24T12:34:56.1234567");
     private static final Instant DEFAULT_TIMESTAMP_LTZ = 
fromLocalTZ("2021-09-24T22:34:56.1234567");
+    private static final LocalDateTime TIMESTAMP_BEFORE_EPOCH =
+            LocalDateTime.parse("1969-12-31T23:59:59.999");
 
     private static final Period DEFAULT_INTERVAL_YEAR = Period.of(10, 4, 0);
     private static final Duration DEFAULT_INTERVAL_DAY = Duration.ofHours(12);
@@ -699,6 +701,7 @@ public class CastFunctionITCase extends 
BuiltInFunctionTestBase {
                         //
                         .fromCase(TIMESTAMP(), DEFAULT_TIMESTAMP, 
LocalDate.of(2021, 9, 24))
                         .fromCase(TIMESTAMP(4), DEFAULT_TIMESTAMP, 
LocalDate.of(2021, 9, 24))
+                        .fromCase(TIMESTAMP(3), TIMESTAMP_BEFORE_EPOCH, 
LocalDate.of(1969, 12, 31))
 
                         // https://issues.apache.org/jira/browse/FLINK-20869
                         // TIMESTAMP_WITH_TIME_ZONE
@@ -747,6 +750,7 @@ public class CastFunctionITCase extends 
BuiltInFunctionTestBase {
                         .fromCase(TIME(5), DEFAULT_TIME, LocalTime.of(12, 34, 
56, 0))
                         .fromCase(TIMESTAMP(), DEFAULT_TIMESTAMP, 
LocalTime.of(12, 34, 56, 0))
                         .fromCase(TIMESTAMP(4), DEFAULT_TIMESTAMP, 
LocalTime.of(12, 34, 56, 0))
+                        .fromCase(TIMESTAMP(3), TIMESTAMP_BEFORE_EPOCH, 
LocalTime.of(23, 59, 59))
 
                         // https://issues.apache.org/jira/browse/FLINK-20869
                         // TIMESTAMP_WITH_TIME_ZONE
@@ -830,6 +834,12 @@ public class CastFunctionITCase extends 
BuiltInFunctionTestBase {
                         // ROW
                         // RAW
                         .build(),
+                CastTestSpecBuilder.testCastTo(TIMESTAMP(0))
+                        .fromCase(
+                                TIMESTAMP(3),
+                                TIMESTAMP_BEFORE_EPOCH,
+                                LocalDateTime.of(1969, 12, 31, 23, 59, 59))
+                        .build(),
                 CastTestSpecBuilder.testCastTo(TIMESTAMP_LTZ(9))
                         .fromCase(TIMESTAMP_LTZ(), null, null)
                         .failRuntime(CHAR(3), "foo", 
DateTimeParseException.class)

Reply via email to