Merge pull request #34208 from ClickHouse/parse-date-time-best-effort-more-cases

More cases for `parseDateTimeBestEffort`
This commit is contained in:
alexey-milovidov 2022-02-01 16:22:52 +03:00 committed by GitHub
commit 2b1d1a9a6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 29 deletions

View File

@ -194,7 +194,7 @@ ReturnType parseDateTimeBestEffortImpl(
} }
else if (num_digits == 6) else if (num_digits == 6)
{ {
/// This is YYYYMM /// This is YYYYMM or hhmmss
if (!year && !month) if (!year && !month)
{ {
readDecimalNumber<4>(year, digits); readDecimalNumber<4>(year, digits);
@ -435,47 +435,59 @@ ReturnType parseDateTimeBestEffortImpl(
else if (c == '+' || c == '-') else if (c == '+' || c == '-')
{ {
++in.position(); ++in.position();
has_time_zone_offset = true;
if (c == '-')
time_zone_offset_negative = true;
num_digits = readDigits(digits, sizeof(digits), in); num_digits = readDigits(digits, sizeof(digits), in);
if (num_digits == 4) if (num_digits == 6 && !has_time && year && month && day_of_month)
{ {
readDecimalNumber<2>(time_zone_offset_hour, digits); /// It looks like hhmmss
readDecimalNumber<2>(time_zone_offset_minute, digits + 2); readDecimalNumber<2>(hour, digits);
} readDecimalNumber<2>(minute, digits + 2);
else if (num_digits == 3) readDecimalNumber<2>(second, digits + 4);
{ has_time = true;
readDecimalNumber<1>(time_zone_offset_hour, digits);
readDecimalNumber<2>(time_zone_offset_minute, digits + 1);
}
else if (num_digits == 2)
{
readDecimalNumber<2>(time_zone_offset_hour, digits);
}
else if (num_digits == 1)
{
readDecimalNumber<1>(time_zone_offset_hour, digits);
} }
else else
return on_error("Cannot read DateTime: unexpected number of decimal digits for time zone offset: " + toString(num_digits), ErrorCodes::CANNOT_PARSE_DATETIME);
if (num_digits < 3 && checkChar(':', in))
{ {
num_digits = readDigits(digits, sizeof(digits), in); /// It looks like time zone offset
has_time_zone_offset = true;
if (c == '-')
time_zone_offset_negative = true;
if (num_digits == 2) if (num_digits == 4)
{ {
readDecimalNumber<2>(time_zone_offset_minute, digits); readDecimalNumber<2>(time_zone_offset_hour, digits);
readDecimalNumber<2>(time_zone_offset_minute, digits + 2);
}
else if (num_digits == 3)
{
readDecimalNumber<1>(time_zone_offset_hour, digits);
readDecimalNumber<2>(time_zone_offset_minute, digits + 1);
}
else if (num_digits == 2)
{
readDecimalNumber<2>(time_zone_offset_hour, digits);
} }
else if (num_digits == 1) else if (num_digits == 1)
{ {
readDecimalNumber<1>(time_zone_offset_minute, digits); readDecimalNumber<1>(time_zone_offset_hour, digits);
} }
else else
return on_error("Cannot read DateTime: unexpected number of decimal digits for time zone offset in minutes: " + toString(num_digits), ErrorCodes::CANNOT_PARSE_DATETIME); return on_error("Cannot read DateTime: unexpected number of decimal digits for time zone offset: " + toString(num_digits), ErrorCodes::CANNOT_PARSE_DATETIME);
if (num_digits < 3 && checkChar(':', in))
{
num_digits = readDigits(digits, sizeof(digits), in);
if (num_digits == 2)
{
readDecimalNumber<2>(time_zone_offset_minute, digits);
}
else if (num_digits == 1)
{
readDecimalNumber<1>(time_zone_offset_minute, digits);
}
else
return on_error("Cannot read DateTime: unexpected number of decimal digits for time zone offset in minutes: " + toString(num_digits), ErrorCodes::CANNOT_PARSE_DATETIME);
}
} }
} }
else else

View File

@ -0,0 +1,10 @@
2022-01-01 01:02:03
2022-01-01 01:02:03
2022-01-01 01:02:03
2022-01-01 01:02:03
2022-01-01 01:02:00
2022-01-01 01:02:00
2021-12-31 22:58:00
2022-01-01 02:02:03
2022-01-01 00:02:03
2022-01-01 02:02:03

View File

@ -0,0 +1,10 @@
SELECT parseDateTimeBestEffort('20220101-010203', 'UTC');
SELECT parseDateTimeBestEffort('20220101+010203', 'UTC');
SELECT parseDateTimeBestEffort('20220101 010203', 'UTC');
SELECT parseDateTimeBestEffort('20220101T010203', 'UTC');
SELECT parseDateTimeBestEffort('20220101T01:02', 'UTC');
SELECT parseDateTimeBestEffort('20220101-0102', 'UTC');
SELECT parseDateTimeBestEffort('20220101+0102', 'UTC');
SELECT parseDateTimeBestEffort('20220101-010203-01', 'UTC');
SELECT parseDateTimeBestEffort('20220101-010203+0100', 'UTC');
SELECT parseDateTimeBestEffort('20220101-010203-01:00', 'UTC');