DateTimeChecker.java
// 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.nereids.trees.expressions.literal.format;
import org.apache.doris.nereids.trees.expressions.literal.DateLiteral;
/** DateTimeChecker */
public class DateTimeChecker extends FormatChecker {
private static final DateTimeChecker INSTANCE = new DateTimeChecker();
private final FormatChecker checker;
private DateTimeChecker() {
super("DateTimeChecker");
this.checker =
or(
// date
and("Date",
or(
// 20241012
digit(8, 8),
// 2024-10-12
and(
digit(1, 4), // year
chars(DateLiteral.punctuations::contains),
digit(1, 2), // month
chars(DateLiteral.punctuations::contains),
digit(1, 2) // day
)
)
),
// datetime
and("DateTime",
or("YearToSecond",
// 20241012010203
and("FullCompactDateTime",
digit(8, 8),
atLeast(0, c -> c == 'T'),
digit(6, 6)
),
// 241012010203 or 241012T010203
and("ShortCompactDateTime",
digit(6, 6),
atLeast(0, c -> c == 'T'),
digit(6, 6)
),
// 2024-01-01 01:02:03
and("NormalDateTime",
digit(1, 4), // year
chars(DateLiteral.punctuations::contains),
digit(1, 2), // month
chars(DateLiteral.punctuations::contains),
digit(1, 2), // day
atLeast(1, c -> c == 'T' || c == ' ' || DateLiteral.punctuations.contains(c)),
digit(1, 2), // hour
option(
and(
chars(DateLiteral.punctuations::contains),
digit(1, 2), // minute
option(
and(
chars(DateLiteral.punctuations::contains),
digit(1, 2) // second
)
)
)
)
)
),
option("NanoSecond", nanoSecond()),
option("TimeZone", timeZone())
)
);
}
public static boolean isValidDateTime(String str) {
str = str.trim();
StringInspect stringInspect = new StringInspect(str.trim());
return INSTANCE.check(stringInspect).matched && stringInspect.eos();
}
@Override
protected boolean doCheck(StringInspect stringInspect) {
return checker.check(stringInspect).matched;
}
private FormatChecker nanoSecond() {
return and(
ch('.'),
digit(1)
);
}
private FormatChecker timeZone() {
// Z or +08:00 or UTC-01:00
return and(
// timezone: Europe/London, America/New_York
atLeast(0, c -> ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '/' || c == '_'),
option(
and(
chars(c -> c == '+' || c == '-'),
digit(1, 2),
option(
and(
ch(':'),
digit(1, 2),
option(
and(
ch(':'),
digit(1, 2)
)
)
)
)
)
)
);
}
}