diff --git a/be/src/vec/runtime/vdatetime_value.cpp b/be/src/vec/runtime/vdatetime_value.cpp index 7755cbea7a..58c6c25f9b 100644 --- a/be/src/vec/runtime/vdatetime_value.cpp +++ b/be/src/vec/runtime/vdatetime_value.cpp @@ -30,6 +30,7 @@ #include // IWYU pragma: keep // IWYU pragma: no_include #include +#include #include #include #include @@ -1588,11 +1589,24 @@ bool VecDateTimeValue::from_date_format_str(const char* format, int format_len, // so we only need to set date part // 3. if both are true, means all part of date_time be set, no need check_range_and_set_time bool already_set_date_part = yearday > 0 || (week_num >= 0 && weekday > 0); - if (already_set_date_part && already_set_time_part) return true; - if (already_set_date_part) + if (already_set_date_part && already_set_time_part) { + return true; + } + // for two special date cases, complete default month/day + if (!time_part_used && year > 0) { + if (std::string_view {format, end} == "%Y") { + month = day = 1; + } else if (std::string_view {format, end} == "%Y-%m") { + day = 1; + } + } + + if (already_set_date_part) { return check_range_and_set_time(_year, _month, _day, hour, minute, second, _type); - if (already_set_time_part) + } + if (already_set_time_part) { return check_range_and_set_time(year, month, day, _hour, _minute, _second, _type); + } return check_range_and_set_time(year, month, day, hour, minute, second, _type); } @@ -2578,6 +2592,16 @@ bool DateV2Value::from_date_format_str(const char* format, int format_len, co date_v2_value_.day_, 0, 0, 0, 0); } } + + // for two special date cases, complete default month/day + if (!time_part_used && year > 0) { + if (std::string_view {format, end} == "%Y") { + month = day = 1; + } else if (std::string_view {format, end} == "%Y-%m") { + day = 1; + } + } + if (already_set_time_part) { if constexpr (is_datetime) { return check_range_and_set_time(year, month, day, date_v2_value_.hour_, diff --git a/docs/en/docs/sql-manual/sql-functions/date-time-functions/str-to-date.md b/docs/en/docs/sql-manual/sql-functions/date-time-functions/str-to-date.md index 1e2a7942cd..4b46dc2554 100644 --- a/docs/en/docs/sql-manual/sql-functions/date-time-functions/str-to-date.md +++ b/docs/en/docs/sql-manual/sql-functions/date-time-functions/str-to-date.md @@ -33,7 +33,7 @@ under the License. Convert STR to DATE type by format specified, if the conversion result does not return NULL. Note that the 'format' parameter specifies the format of the first parameter. -The `format` supported is consistent with [date_format](date_format.md) +All formats in [date_format](./date-format) are supported. In addition, support auto completing the remainder of date part for '%Y' and '%Y-%m'. ### example @@ -65,7 +65,13 @@ mysql> select str_to_date("2020-09-01", "%Y-%m-%d %H:%i:%s"); +------------------------------------------------+ | 2020-09-01 00:00:00 | +------------------------------------------------+ -1 row in set (0.01 sec) + +mysql> select str_to_date('2023','%Y'); ++---------------------------+ +| str_to_date('2023', '%Y') | ++---------------------------+ +| 2023-01-01 | ++---------------------------+ ``` ### keywords diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/str-to-date.md b/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/str-to-date.md index fc15fc31a6..3c219a29fa 100644 --- a/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/str-to-date.md +++ b/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/str-to-date.md @@ -32,7 +32,7 @@ under the License. 通过format指定的方式将str转化为DATE类型,如果转化结果不对返回NULL。注意format指定的是第一个参数的格式。 -支持的format格式与[date_format](date_format.md)一致 +支持[date_format](./date-format)中的所有 format 格式,此外对于 '%Y' 和 '%Y-%m',支持补齐日期剩余部分。 ### example @@ -64,7 +64,13 @@ mysql> select str_to_date("2020-09-01", "%Y-%m-%d %H:%i:%s"); +------------------------------------------------+ | 2020-09-01 00:00:00 | +------------------------------------------------+ -1 row in set (0.01 sec) + +mysql> select str_to_date('2023','%Y'); ++---------------------------+ +| str_to_date('2023', '%Y') | ++---------------------------+ +| 2023-01-01 | ++---------------------------+ ``` ### keywords diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java index be72f5b0cf..8b0921f9b1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java @@ -1536,6 +1536,14 @@ public class DateLiteral extends LiteralExpr { getDateFromDaynr(days); } + if (!timePartUsed && year > 0) { + if (format.equals("%Y")) { + month = day = 1; + } else if (format.equals("%Y-%m")) { + day = 1; + } + } + // Compute timestamp type // TODO(Gabriel): we still use old version datetime/date and change this to new version when // we think it's stable enough diff --git a/regression-test/data/correctness/test_str_to_date.out b/regression-test/data/correctness/test_str_to_date.out index af6342ecf6..5aa1f75a2c 100644 --- a/regression-test/data/correctness/test_str_to_date.out +++ b/regression-test/data/correctness/test_str_to_date.out @@ -13,6 +13,15 @@ -- !select4 -- 2020-12-03T11:45:14 +-- !add_1 -- +2023-01-01 + +-- !add_2 -- +2023-12-01 + +-- !add_3 -- +2023-01-01 + -- !select5 -- 2019-12-01 yyyy-MM-dd 2019-12-01T00:00 20201203 yyyyMMdd 2020-12-03T00:00 @@ -27,3 +36,12 @@ -- !select8 -- 2020-12-03T11:45:14 +-- !add_4 -- +2023-01-01 + +-- !add_5 -- +2023-12-01 + +-- !add_6 -- +2023-01-01 + diff --git a/regression-test/suites/correctness/test_str_to_date.groovy b/regression-test/suites/correctness/test_str_to_date.groovy index 6c26a8db24..43c80d4f4b 100644 --- a/regression-test/suites/correctness/test_str_to_date.groovy +++ b/regression-test/suites/correctness/test_str_to_date.groovy @@ -36,43 +36,38 @@ suite("test_str_to_date") { sql """ INSERT INTO test_str_to_date_db VALUES(2,'20201203', 'yyyyMMdd');""" sql """ INSERT INTO test_str_to_date_db VALUES(3,'2020-12-03 11:45:14', 'yyyy-MM-dd HH:mm:ss');""" - sql """ set enable_nereids_planner=true , enable_fallback_to_original_planner=false;""" - - +sql """ set enable_nereids_planner=true , enable_fallback_to_original_planner=false;""" qt_select1 """ select s1,s2,STR_TO_DATE(s1,s2) from test_str_to_date_db order by id; """ - qt_select2 """ SELECT STR_TO_DATE('2019-12-01', 'yyyy-MM-dd'); """ - qt_select3 """ SELECT STR_TO_DATE('20201203', 'yyyyMMdd'); """ - qt_select4 """ SELECT STR_TO_DATE('2020-12-03 11:45:14', 'yyyy-MM-dd HH:mm:ss'); """ + qt_add_1 " select STR_TO_DATE('2023', '%Y') " + qt_add_2 " select STR_TO_DATE('2023-12', '%Y-%m') " + qt_add_3 " select STR_TO_DATE('2023-12', '%Y')" - sql """ set enable_nereids_planner=false;""" - +sql """ set enable_nereids_planner=false;""" qt_select5 """ select s1,s2,STR_TO_DATE(s1,s2) from test_str_to_date_db order by id; """ - qt_select6 """ SELECT STR_TO_DATE('2019-12-01', 'yyyy-MM-dd'); """ - qt_select7 """ SELECT STR_TO_DATE('20201203', 'yyyyMMdd'); """ - qt_select8 """ SELECT STR_TO_DATE('2020-12-03 11:45:14', 'yyyy-MM-dd HH:mm:ss'); """ - - + qt_add_4 " select STR_TO_DATE('2023', '%Y') " + qt_add_5 " select STR_TO_DATE('2023-12', '%Y-%m') " + qt_add_6 " select STR_TO_DATE('2023-12', '%Y')" }