diff --git a/src/IO/parseDateTimeBestEffort.cpp b/src/IO/parseDateTimeBestEffort.cpp index 3b05d8c76b6..3c6f9b8f9f5 100644 --- a/src/IO/parseDateTimeBestEffort.cpp +++ b/src/IO/parseDateTimeBestEffort.cpp @@ -194,7 +194,7 @@ ReturnType parseDateTimeBestEffortImpl( } else if (num_digits == 6) { - /// This is YYYYMM + /// This is YYYYMM or hhmmss if (!year && !month) { readDecimalNumber<4>(year, digits); @@ -435,47 +435,59 @@ ReturnType parseDateTimeBestEffortImpl( else if (c == '+' || c == '-') { ++in.position(); - has_time_zone_offset = true; - if (c == '-') - time_zone_offset_negative = true; - 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); - 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) - { - readDecimalNumber<1>(time_zone_offset_hour, digits); + /// It looks like hhmmss + readDecimalNumber<2>(hour, digits); + readDecimalNumber<2>(minute, digits + 2); + readDecimalNumber<2>(second, digits + 4); + has_time = true; } 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) { - readDecimalNumber<1>(time_zone_offset_minute, digits); + readDecimalNumber<1>(time_zone_offset_hour, 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); + 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 diff --git a/tests/queries/0_stateless/02191_parse_date_time_best_effort_more_cases.reference b/tests/queries/0_stateless/02191_parse_date_time_best_effort_more_cases.reference new file mode 100644 index 00000000000..227e3b013b2 --- /dev/null +++ b/tests/queries/0_stateless/02191_parse_date_time_best_effort_more_cases.reference @@ -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 diff --git a/tests/queries/0_stateless/02191_parse_date_time_best_effort_more_cases.sql b/tests/queries/0_stateless/02191_parse_date_time_best_effort_more_cases.sql new file mode 100644 index 00000000000..d30834b90a3 --- /dev/null +++ b/tests/queries/0_stateless/02191_parse_date_time_best_effort_more_cases.sql @@ -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');