From 549ced0860e7251cad78fb04f4fea5f49df9a40e Mon Sep 17 00:00:00 2001 From: morrySnow Date: Fri, 27 Sep 2024 14:34:39 +0800 Subject: [PATCH] [fix](Nereids) could not parse date/datetime with blank + zone for example: 2008-08-08 20:08:08 +08:00 parse failed because the blank before +08:00 --- .../expressions/literal/DateLiteral.java | 12 ++++++--- .../expressions/literal/DateLiteralTest.java | 6 +++++ .../util/DateTimeFormatterUtilsTest.java | 26 +++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java index f1946463aa71eb..efef246d4e8171 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteral.java @@ -220,7 +220,11 @@ static String normalize(String s) { while (i < s.length() && (isPunctuation(s.charAt(i)) || s.charAt(i) == ' ' || s.charAt(i) == 'T')) { i += 1; } - sb.append(' '); + // avoid add blank before zone-id, for example 2008-08-08 +08:00 + // should be normalized to 2008-08-08+08:00 + if (i >= s.length() || Character.isDigit(s.charAt(i))) { + sb.append(' '); + } } else if (partNumber > 3 && isPunctuation(c)) { sb.append(':'); } else { @@ -240,18 +244,20 @@ static String normalize(String s) { // parse MicroSecond // Keep up to 7 digits at most, 7th digit is use for overflow. + int j = i; if (partNumber == 6 && i < s.length() && s.charAt(i) == '.') { sb.append(s.charAt(i)); i += 1; while (i < s.length() && Character.isDigit(s.charAt(i))) { - if (i - 19 <= 7) { + if (i - j <= 7) { sb.append(s.charAt(i)); } i += 1; } } - sb.append(s.substring(i)); + // trim use to remove any blank before zone id or zone offset + sb.append(s.substring(i).trim()); return sb.toString(); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java index 3430676b14d5ba..7c8ad5ed0e69a4 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/literal/DateLiteralTest.java @@ -47,6 +47,12 @@ void testNormalize() { Assertions.assertEquals("2021-05-01 00:00:00", s); s = DateLiteral.normalize("2021-5-01 0:0:0.001"); Assertions.assertEquals("2021-05-01 00:00:00.001", s); + s = DateLiteral.normalize("2021-5-01 0:0:0.12345678"); + Assertions.assertEquals("2021-05-01 00:00:00.1234567", s); + s = DateLiteral.normalize("2021-5-1 Asia/Shanghai"); + Assertions.assertEquals("2021-05-01Asia/Shanghai", s); + s = DateLiteral.normalize("2021-5-1 0:0:0.12345678 Asia/Shanghai"); + Assertions.assertEquals("2021-05-01 00:00:00.1234567Asia/Shanghai", s); } @Test diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/DateTimeFormatterUtilsTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/DateTimeFormatterUtilsTest.java index 8437fdb0092025..e067bbaa479e40 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/DateTimeFormatterUtilsTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/DateTimeFormatterUtilsTest.java @@ -111,4 +111,30 @@ void testTimeFormatter() { Assertions.assertThrows(DateTimeParseException.class, () -> timeFormatter.parse("01:01")); Assertions.assertThrows(DateTimeParseException.class, () -> timeFormatter.parse("01")); } + + @Test + void testZoneDateFormatter() { + DateTimeFormatter formatter = DateTimeFormatterUtils.ZONE_DATE_FORMATTER; + TemporalAccessor date = formatter.parse("2020-02-19Asia/Shanghai"); + assertDatePart(date); + date = formatter.parse("2020-02-19UTC+08:00"); + assertDatePart(date); + date = formatter.parse("2020-02-19+08:00"); + assertDatePart(date); + Assertions.assertThrows(DateTimeParseException.class, () -> formatter.parse("2020-02-19 Asia/Shanghai")); + Assertions.assertThrows(DateTimeParseException.class, () -> formatter.parse("2020-02-19++08:00")); + } + + @Test + void testZoneDateTimeFormatter() { + DateTimeFormatter formatter = DateTimeFormatterUtils.ZONE_DATE_FORMATTER; + TemporalAccessor dateTime = formatter.parse("2020-02-19 00:00:00Asia/Shanghai"); + assertDatePart(dateTime); + dateTime = formatter.parse("2020-02-19 00:00:00UTC+08:00"); + assertDatePart(dateTime); + dateTime = formatter.parse("2020-02-19 00:00:00+08:00"); + assertDatePart(dateTime); + Assertions.assertThrows(DateTimeParseException.class, () -> formatter.parse("2020-02-19 00:00:00 Asia/Shanghai")); + Assertions.assertThrows(DateTimeParseException.class, () -> formatter.parse("2020-02-19 00:00:00++08:00")); + } }