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));
+ }
}