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 501e33211e [common] Fix DateTimeUtils.truncate dropping sub-precision 
fractional seconds (#8767)
501e33211e is described below

commit 501e33211ec6a427ffd4d2046e8cd141845a43fc
Author: Eunbin Son <[email protected]>
AuthorDate: Tue Jul 21 14:16:37 2026 +0900

    [common] Fix DateTimeUtils.truncate dropping sub-precision fractional 
seconds (#8767)
---
 .../org/apache/paimon/utils/DateTimeUtils.java     | 10 +++++--
 .../org/apache/paimon/utils/DateTimeUtilsTest.java | 34 ++++++++++++++++++++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git 
a/paimon-common/src/main/java/org/apache/paimon/utils/DateTimeUtils.java 
b/paimon-common/src/main/java/org/apache/paimon/utils/DateTimeUtils.java
index e8b57caf1d..90c6d447f5 100644
--- a/paimon-common/src/main/java/org/apache/paimon/utils/DateTimeUtils.java
+++ b/paimon-common/src/main/java/org/apache/paimon/utils/DateTimeUtils.java
@@ -649,8 +649,14 @@ public class DateTimeUtils {
     }
 
     public static Timestamp truncate(Timestamp ts, int precision) {
-        String fraction = Integer.toString(ts.toLocalDateTime().getNano());
-        if (fraction.length() <= precision) {
+        // Pad to 9 digits so leading zeros are preserved, then count the 
significant
+        // fractional digits by stripping trailing zeros (same approach as 
formatTimestamp).
+        String fraction = pad(9, ts.toLocalDateTime().getNano());
+        int significant = fraction.length();
+        while (significant > 0 && fraction.charAt(significant - 1) == '0') {
+            significant--;
+        }
+        if (significant <= precision) {
             return ts;
         } else {
             // need to truncate
diff --git 
a/paimon-common/src/test/java/org/apache/paimon/utils/DateTimeUtilsTest.java 
b/paimon-common/src/test/java/org/apache/paimon/utils/DateTimeUtilsTest.java
index 61cc0ac8f8..cbc8267e42 100644
--- a/paimon-common/src/test/java/org/apache/paimon/utils/DateTimeUtilsTest.java
+++ b/paimon-common/src/test/java/org/apache/paimon/utils/DateTimeUtilsTest.java
@@ -99,4 +99,38 @@ public class DateTimeUtilsTest {
             TimeZone.setDefault(timeZone);
         }
     }
+
+    @Test
+    public void testTruncateDropsSubPrecisionFraction() {
+        // A fractional second below 0.1s has leading zeros in its nano 
representation.
+        // The narrowing cast to precision 3 must drop all nanoseconds below 
the millisecond.
+        Timestamp nineNanos = 
Timestamp.fromLocalDateTime(LocalDateTime.of(1970, 1, 1, 0, 0, 0, 9));
+        assertThat(nineNanos.toLocalDateTime().getNano()).isEqualTo(9);
+        assertThat(DateTimeUtils.truncate(nineNanos, 
3).toLocalDateTime().getNano()).isEqualTo(0);
+
+        // Truncating .000123456 to precision 6 must keep exactly 6 fractional 
digits (.000123).
+        Timestamp micros =
+                Timestamp.fromLocalDateTime(LocalDateTime.of(1970, 1, 1, 0, 0, 
0, 123_456));
+        assertThat(micros.toLocalDateTime().getNano()).isEqualTo(123_456);
+        assertThat(DateTimeUtils.truncate(micros, 
6).toLocalDateTime().getNano())
+                .isEqualTo(123_000);
+    }
+
+    @Test
+    public void testTruncateIsIdempotent() {
+        // An already-truncated value stays unchanged when truncated again to 
the same precision.
+        Timestamp truncated =
+                Timestamp.fromLocalDateTime(LocalDateTime.of(1970, 1, 1, 0, 0, 
0, 123_000));
+        assertThat(DateTimeUtils.truncate(truncated, 
6).toLocalDateTime().getNano())
+                .isEqualTo(123_000);
+    }
+
+    @Test
+    public void testTruncateNoOpAtMaxPrecision() {
+        // Precision 9 preserves all nanoseconds.
+        Timestamp full =
+                Timestamp.fromLocalDateTime(LocalDateTime.of(1970, 1, 1, 0, 0, 
0, 123_456_789));
+        assertThat(DateTimeUtils.truncate(full, 9).toLocalDateTime().getNano())
+                .isEqualTo(123_456_789);
+    }
 }

Reply via email to