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

davidzollo pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git


The following commit(s) were added to refs/heads/dev by this push:
     new 49350f376a [Fix][Format] Refresh JSON timestamp formatter on mixed 
precision (#11264)
49350f376a is described below

commit 49350f376abd42e2516ea9367b691e4cd7c15ca2
Author: Daniel <[email protected]>
AuthorDate: Sun Aug 23 16:15:17 2026 +0800

    [Fix][Format] Refresh JSON timestamp formatter on mixed precision (#11264)
    
    Co-authored-by: DanielLeens <[email protected]>
---
 .../seatunnel/format/json/JsonToRowConverters.java | 28 +++++++++++++++++++++-
 .../format/json/JsonRowDataSerDeSchemaTest.java    | 22 +++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git 
a/seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/JsonToRowConverters.java
 
b/seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/JsonToRowConverters.java
index c4aaf5e436..040329a869 100644
--- 
a/seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/JsonToRowConverters.java
+++ 
b/seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/JsonToRowConverters.java
@@ -45,6 +45,7 @@ import java.time.LocalTime;
 import java.time.OffsetDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoField;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalQueries;
@@ -312,12 +313,37 @@ public class JsonToRowConverters implements Serializable {
             throw CommonError.formatDateTimeError(datetimeStr, fieldName);
         }
 
-        TemporalAccessor parsedTimestamp = 
dateTimeFormatter.parse(datetimeStr);
+        TemporalAccessor parsedTimestamp =
+                parseDateTimeWithFormatterRefresh(datetimeStr, fieldName, 
dateTimeFormatter);
         LocalTime localTime = 
parsedTimestamp.query(TemporalQueries.localTime());
         LocalDate localDate = 
parsedTimestamp.query(TemporalQueries.localDate());
         return LocalDateTime.of(localDate, localTime);
     }
 
+    /**
+     * Re-resolves the formatter when the cached per-field formatter no longer 
matches the current
+     * timestamp text. This happens when one JSON field mixes second-only and 
fractional-second
+     * values across rows.
+     */
+    private TemporalAccessor parseDateTimeWithFormatterRefresh(
+            String datetimeStr, String fieldName, DateTimeFormatter 
dateTimeFormatter) {
+        try {
+            return dateTimeFormatter.parse(datetimeStr);
+        } catch (DateTimeParseException parseException) {
+            if (StringUtils.isBlank(fieldName)) {
+                throw parseException;
+            }
+
+            DateTimeFormatter refreshedFormatter =
+                    DateTimeUtils.matchDateTimeFormatter(datetimeStr);
+            if (refreshedFormatter == null) {
+                throw CommonError.formatDateTimeError(datetimeStr, fieldName);
+            }
+            fieldFormatterMap.put(fieldName, refreshedFormatter);
+            return refreshedFormatter.parse(datetimeStr);
+        }
+    }
+
     private OffsetDateTime convertToOffsetDateTime(JsonNode jsonNode, String 
fieldName) {
         String datetimeStr = jsonNode.asText();
         return OffsetDateTime.parse(datetimeStr);
diff --git 
a/seatunnel-formats/seatunnel-format-json/src/test/java/org/apache/seatunnel/format/json/JsonRowDataSerDeSchemaTest.java
 
b/seatunnel-formats/seatunnel-format-json/src/test/java/org/apache/seatunnel/format/json/JsonRowDataSerDeSchemaTest.java
index 66d038e105..80224658fa 100644
--- 
a/seatunnel-formats/seatunnel-format-json/src/test/java/org/apache/seatunnel/format/json/JsonRowDataSerDeSchemaTest.java
+++ 
b/seatunnel-formats/seatunnel-format-json/src/test/java/org/apache/seatunnel/format/json/JsonRowDataSerDeSchemaTest.java
@@ -768,4 +768,26 @@ public class JsonRowDataSerDeSchemaTest {
         assertEquals(LocalDate.of(2024, 1, 15), row.getField(0));
         assertEquals(LocalDate.of(2024, 6, 20), row.getField(1));
     }
+
+    @Test
+    public void testTimestampFieldSupportsMixedPrecisionAcrossRows() throws 
IOException {
+        SeaTunnelRowType rowType =
+                new SeaTunnelRowType(
+                        new String[] {"timestamp_field"},
+                        new SeaTunnelDataType<?>[] 
{LocalTimeType.LOCAL_DATE_TIME_TYPE});
+        JsonDeserializationSchema deserializationSchema =
+                new JsonDeserializationSchema(false, false, rowType);
+
+        SeaTunnelRow secondPrecisionRow =
+                deserializationSchema.deserialize(
+                        
"{\"timestamp_field\":\"2022-09-24T22:45:00\"}".getBytes());
+        SeaTunnelRow fractionalPrecisionRow =
+                deserializationSchema.deserialize(
+                        
"{\"timestamp_field\":\"2022-09-24T22:45:00.123\"}".getBytes());
+
+        assertEquals(LocalDateTime.of(2022, 9, 24, 22, 45, 0), 
secondPrecisionRow.getField(0));
+        assertEquals(
+                LocalDateTime.of(2022, 9, 24, 22, 45, 0, 123_000_000),
+                fractionalPrecisionRow.getField(0));
+    }
 }

Reply via email to