From b5ae01f1eb64ae7a54a3c66b1528aa910659bb4c Mon Sep 17 00:00:00 2001 From: HangyuanLiu <460660596@qq.com> Date: Fri, 20 Sep 2019 16:16:56 +0800 Subject: [PATCH] fix two digit year bug in to_days function --- .../apache/doris/analysis/DateLiteral.java | 24 +++++++- .../doris/analysis/DateLiteralTest.java | 58 +++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 fe/src/test/java/org/apache/doris/analysis/DateLiteralTest.java diff --git a/fe/src/main/java/org/apache/doris/analysis/DateLiteral.java b/fe/src/main/java/org/apache/doris/analysis/DateLiteral.java index eafcd190b7b896..9aefc093c376ef 100644 --- a/fe/src/main/java/org/apache/doris/analysis/DateLiteral.java +++ b/fe/src/main/java/org/apache/doris/analysis/DateLiteral.java @@ -56,10 +56,21 @@ public class DateLiteral extends LiteralExpr { private static DateTimeFormatter DATE_TIME_FORMATTER = null; private static DateTimeFormatter DATE_FORMATTER = null; + /* + * Dates containing two-digit year values are ambiguous because the century is unknown. + * MySQL interprets two-digit year values using these rules: + * Year values in the range 70-99 are converted to 1970-1999. + * Year values in the range 00-69 are converted to 2000-2069. + * */ + private static DateTimeFormatter DATE_TIME_FORMATTER_TWO_DIGIT = null; + private static DateTimeFormatter DATE_FORMATTER_TWO_DIGIT = null; + static { try { DATE_TIME_FORMATTER = formatBuilder("%Y-%m-%d %H:%i:%s").toFormatter(); DATE_FORMATTER = formatBuilder("%Y-%m-%d").toFormatter(); + DATE_TIME_FORMATTER_TWO_DIGIT = formatBuilder("%y-%m-%d %H:%i:%s").toFormatter(); + DATE_FORMATTER_TWO_DIGIT = formatBuilder("%y-%m-%d").toFormatter(); } catch (AnalysisException e) { LOG.error("invalid date format", e); System.exit(-1); @@ -171,10 +182,19 @@ private void init(String s, Type type) throws AnalysisException { Preconditions.checkArgument(type.isDateType()); LocalDateTime dateTime; if (type == Type.DATE) { - dateTime = DATE_FORMATTER.parseLocalDateTime(s); + if (s.split("-")[0].length() == 2) { + dateTime = DATE_FORMATTER_TWO_DIGIT.parseLocalDateTime(s); + } else { + dateTime = DATE_FORMATTER.parseLocalDateTime(s); + } } else { - dateTime = DATE_TIME_FORMATTER.parseLocalDateTime(s); + if (s.split("-")[0].length() == 2) { + dateTime = DATE_TIME_FORMATTER_TWO_DIGIT.parseLocalDateTime(s); + } else { + dateTime = DATE_TIME_FORMATTER.parseLocalDateTime(s); + } } + year = dateTime.getYear(); month = dateTime.getMonthOfYear(); day = dateTime.getDayOfMonth(); diff --git a/fe/src/test/java/org/apache/doris/analysis/DateLiteralTest.java b/fe/src/test/java/org/apache/doris/analysis/DateLiteralTest.java new file mode 100644 index 00000000000000..21211315896176 --- /dev/null +++ b/fe/src/test/java/org/apache/doris/analysis/DateLiteralTest.java @@ -0,0 +1,58 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.analysis; + +import org.apache.doris.catalog.Type; +import org.apache.doris.common.AnalysisException; +import org.junit.Assert; +import org.junit.Test; + +public class DateLiteralTest { + + @Test + public void TwoDigitYear() { + boolean hasException = false; + try { + DateLiteral literal = new DateLiteral("1997-10-07", Type.DATE); + Assert.assertEquals(1997, literal.getYear()); + + DateLiteral literal2 = new DateLiteral("97-10-07", Type.DATE); + Assert.assertEquals(1997, literal2.getYear()); + + DateLiteral literal3 = new DateLiteral("0097-10-07", Type.DATE); + Assert.assertEquals(97, literal3.getYear()); + + DateLiteral literal4 = new DateLiteral("99-10-07", Type.DATE); + Assert.assertEquals(1999, literal4.getYear()); + + DateLiteral literal5 = new DateLiteral("70-10-07", Type.DATE); + Assert.assertEquals(1970, literal5.getYear()); + + DateLiteral literal6 = new DateLiteral("69-10-07", Type.DATE); + Assert.assertEquals(2069, literal6.getYear()); + + DateLiteral literal7 = new DateLiteral("00-10-07", Type.DATE); + Assert.assertEquals(2000, literal7.getYear()); + + } catch (AnalysisException e) { + e.printStackTrace(); + hasException = true; + } + Assert.assertFalse(hasException); + } +}