hubgeter commented on code in PR #40695: URL: https://github.com/apache/doris/pull/40695#discussion_r1756586321
########## be/src/vec/functions/function_timestamp.cpp: ########## @@ -1182,6 +1184,139 @@ class FunctionOtherTypesToDateType : public IFunction { } }; +struct FromIso8601DateV2 { + static constexpr auto name = "from_iso8601_date"; + + static bool is_variadic() { return true; } //todo : check is or not is_variadic + + static DataTypes get_variadic_argument_types() { return {std::make_shared<DataTypeString>()}; } + + static DataTypePtr get_return_type_impl(const DataTypes& arguments) { + return make_nullable(std::make_shared<DataTypeDateV2>()); + } + + static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + size_t result, size_t input_rows_count) { + const auto* src_column_ptr = block.get_by_position(arguments[0]).column.get(); + + std::regex calendar_regex(R"((\d{4})(-)?(\d{2})(-)?(\d{2}))"); // YYYY-MM-DD or YYYYMMDD + std::regex year_month_regex(R"((\d{4})-(\d{2}))"); // YYYY-MM + std::regex year_only_regex(R"((\d{4}))"); // YYYY + std::regex week_regex( + R"((\d{4})(-)?W(\d{2})(-)?(\d)?)"); // YYYY-Www or YYYY-Www-D or YYYYWww or YYYYWwwD + std::regex day_of_year_regex(R"((\d{4})(-)?(\d{3}))"); // YYYY-DDD or YYYYDDD + std::smatch match; + + auto null_map = ColumnUInt8::create(input_rows_count, 0); + + ColumnPtr res = ColumnDateV2::create(input_rows_count); + auto& result_data = static_cast<ColumnDateV2*>(res->assume_mutable().get())->get_data(); + + for (size_t i = 0; i < input_rows_count; ++i) { + std::string iso_date = src_column_ptr->get_data_at(i).to_string(); + auto& ts_value = *reinterpret_cast<DateV2Value<DateV2ValueType>*>(&result_data[i]); + if (std::regex_match(iso_date, match, calendar_regex)) { + int year = std::stoi(match[1]); + int month = std::stoi(match[3]); + int day = std::stoi(match[5]); + + if (!(ts_value.template set_time_unit<YEAR>(year) && + ts_value.template set_time_unit<MONTH>(month) && + ts_value.template set_time_unit<DAY>(day))) { + null_map->get_data().data()[i] = true; + } + } else if ( + std::regex_match( + iso_date, match, + year_month_regex)) { // Year and Month format (YYYY-MM, but NOT YYYYMM) + int year = std::stoi(match[1]); + int month = std::stoi(match[2]); + + if (!(ts_value.template set_time_unit<YEAR>(year) && + ts_value.template set_time_unit<MONTH>(month))) { + null_map->get_data().data()[i] = true; + } + ts_value.template unchecked_set_time_unit<DAY>(1); + } else if (std::regex_match(iso_date, match, + year_only_regex)) { // Year only format (YYYY) + int year = std::stoi(match[1]); + + if (!ts_value.template set_time_unit<YEAR>(year)) { + null_map->get_data().data()[i] = true; + } + ts_value.template unchecked_set_time_unit<MONTH>(1); + ts_value.template unchecked_set_time_unit<DAY>(1); + + } else if ( + std::regex_match( + iso_date, match, + week_regex)) { // Week date format (YYYY-Www, YYYY-Www-D, YYYYWww or YYYYWwwD) + int year = std::stoi(match[1]); + int week = std::stoi(match[3]); + int weekday = match[5].matched ? std::stoi(match[5]) + : 1; // Default to Monday if no day is specified + + // weekday [1,7] week [1,53] + if (weekday < 1 || weekday > 7 || week < 1 || week > 53) { + null_map->get_data().data()[i] = true; + continue; + } + + auto first_day_of_week = getFirstDayOfISOWeek(year); + ts_value.template unchecked_set_time_unit<YEAR>( + first_day_of_week.year().operator int()); + ts_value.template unchecked_set_time_unit<MONTH>( + first_day_of_week.month().operator unsigned int()); + ts_value.template unchecked_set_time_unit<DAY>( + first_day_of_week.day().operator unsigned int()); + + auto day_diff = (week - 1) * 7 + weekday - 1; + TimeInterval interval(DAY, day_diff, false); + ts_value.date_add_interval<DAY>(interval); + + } else if (std::regex_match( + iso_date, match, + day_of_year_regex)) { // Day of year format (YYYYDDD or YYYY-DDD) + int year = std::stoi(match[1]); + int day_of_year = std::stoi(match[3]); + + if (is_leap(year)) { + if (day_of_year < 0 || day_of_year > 366) { Review Comment: i will add it -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org