@@ -619,7 +619,7 @@ inline bool tryToConvertToDayNum(DayNum & date, ExtendedDayNum & from)
619619}
620620
621621template <typename ReturnType = void >
622- inline ReturnType readDateTextImpl (DayNum & date, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_delimiters = nullptr )
622+ inline ReturnType readDateTextImpl (DayNum & date, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_delimiters = nullptr , bool saturate_on_overflow = true )
623623{
624624 static constexpr bool throw_exception = std::is_same_v<ReturnType, void >;
625625
@@ -636,12 +636,22 @@ inline ReturnType readDateTextImpl(DayNum & date, ReadBuffer & buf, const DateLU
636636 if (!readDateTextImpl<ReturnType>(local_date, buf, allowed_delimiters))
637637 return false ;
638638
639- auto ret = tryToMakeDayNum (date_lut, local_date.year (), local_date.month (), local_date.day ());
640- if (!ret)
641- return false ;
639+ if (saturate_on_overflow)
640+ {
641+ // / Use saturating versions - makeDayNum saturates out-of-range years, convertToDayNum saturates to 0 or 0xFFFF
642+ ExtendedDayNum ret = makeDayNum (date_lut, local_date.year (), local_date.month (), local_date.day ());
643+ convertToDayNum (date, ret);
644+ }
645+ else
646+ {
647+ // / Use non-saturating versions - return false for out-of-range values
648+ auto ret = tryToMakeDayNum (date_lut, local_date.year (), local_date.month (), local_date.day ());
649+ if (!ret)
650+ return false ;
642651
643- if (!tryToConvertToDayNum (date, *ret))
644- return false ;
652+ if (!tryToConvertToDayNum (date, *ret))
653+ return false ;
654+ }
645655
646656 return true ;
647657 }
@@ -685,9 +695,9 @@ inline bool tryReadDateText(LocalDate & date, ReadBuffer & buf, const char * all
685695 return readDateTextImpl<bool >(date, buf, allowed_delimiters);
686696}
687697
688- inline bool tryReadDateText (DayNum & date, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance(), const char * allowed_delimiters = nullptr)
698+ inline bool tryReadDateText (DayNum & date, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance(), const char * allowed_delimiters = nullptr, bool saturate_on_overflow = true )
689699{
690- return readDateTextImpl<bool >(date, buf, time_zone, allowed_delimiters);
700+ return readDateTextImpl<bool >(date, buf, time_zone, allowed_delimiters, saturate_on_overflow );
691701}
692702
693703inline bool tryReadDateText (ExtendedDayNum & date, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance(), const char * allowed_delimiters = nullptr)
@@ -815,7 +825,7 @@ inline T parseFromStringWithoutAssertEOF(std::string_view str)
815825}
816826
817827template <typename ReturnType = void , bool dt64_mode = false >
818- ReturnType readDateTimeTextFallback (time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters = nullptr , const char * allowed_time_delimiters = nullptr );
828+ ReturnType readDateTimeTextFallback (time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters = nullptr , const char * allowed_time_delimiters = nullptr , bool saturate_on_overflow = true );
819829
820830template <typename ReturnType = void , bool t64_mode = false >
821831ReturnType readTimeTextFallback (time_t & time, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters = nullptr , const char * allowed_time_delimiters = nullptr );
@@ -824,7 +834,7 @@ ReturnType readTimeTextFallback(time_t & time, ReadBuffer & buf, const DateLUTIm
824834 * As an exception, also supported parsing of unix timestamp in form of decimal number.
825835 */
826836template <typename ReturnType = void , bool dt64_mode = false >
827- inline ReturnType readDateTimeTextImpl (time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters = nullptr , const char * allowed_time_delimiters = nullptr )
837+ inline ReturnType readDateTimeTextImpl (time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters = nullptr , const char * allowed_time_delimiters = nullptr , bool saturate_on_overflow = true )
828838{
829839 static constexpr bool throw_exception = std::is_same_v<ReturnType, void >;
830840
@@ -898,15 +908,30 @@ inline ReturnType readDateTimeTextImpl(time_t & datetime, ReadBuffer & buf, cons
898908 }
899909 else
900910 {
901- auto datetime_maybe = tryToMakeDateTime (date_lut, year, month, day, hour, minute, second);
902- if (!datetime_maybe)
903- return false ;
904-
905- // / For usual DateTime check if value is within supported range
906- if (!dt64_mode && (*datetime_maybe < 0 || *datetime_maybe > UINT32_MAX))
907- return false ;
908-
909- datetime = *datetime_maybe;
911+ if (saturate_on_overflow)
912+ {
913+ // / Use saturating version - makeDateTime saturates out-of-range years
914+ if (unlikely (year == 0 ))
915+ datetime = 0 ;
916+ else
917+ datetime = makeDateTime (date_lut, year, month, day, hour, minute, second);
918+ }
919+ else
920+ {
921+ // / Use non-saturating version - return false for out-of-range values
922+ auto datetime_maybe = tryToMakeDateTime (date_lut, year, month, day, hour, minute, second);
923+ if (!datetime_maybe)
924+ return false ;
925+
926+ // / For usual DateTime check if value is within supported range
927+ if constexpr (!dt64_mode)
928+ {
929+ if (*datetime_maybe < 0 || *datetime_maybe > static_cast <Int64>(UINT32_MAX))
930+ return false ;
931+ }
932+
933+ datetime = *datetime_maybe;
934+ }
910935 }
911936
912937 if (dt_long)
@@ -919,7 +944,7 @@ inline ReturnType readDateTimeTextImpl(time_t & datetime, ReadBuffer & buf, cons
919944 // / Why not readIntTextUnsafe? Because for needs of AdFox, parsing of unix timestamp with leading zeros is supported: 000...NNNN.
920945 return readIntTextImpl<time_t , ReturnType, ReadIntTextCheckOverflow::CHECK_OVERFLOW>(datetime, buf);
921946 }
922- return readDateTimeTextFallback<ReturnType, dt64_mode>(datetime, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters);
947+ return readDateTimeTextFallback<ReturnType, dt64_mode>(datetime, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters, saturate_on_overflow );
923948}
924949
925950/* * In hhh:mm:ss format, according to specified time zone.
@@ -1107,7 +1132,7 @@ inline ReturnType readTimeTextImpl(time_t & time, ReadBuffer & buf, const DateLU
11071132}
11081133
11091134template <typename ReturnType>
1110- inline ReturnType readDateTimeTextImpl (DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters = nullptr , const char * allowed_time_delimiters = nullptr )
1135+ inline ReturnType readDateTimeTextImpl (DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut, const char * allowed_date_delimiters = nullptr , const char * allowed_time_delimiters = nullptr , bool saturate_on_overflow = true )
11111136{
11121137 static constexpr bool throw_exception = std::is_same_v<ReturnType, void >;
11131138
@@ -1121,7 +1146,7 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re
11211146 {
11221147 try
11231148 {
1124- readDateTimeTextImpl<ReturnType, true >(whole, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters);
1149+ readDateTimeTextImpl<ReturnType, true >(whole, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters, saturate_on_overflow );
11251150 }
11261151 catch (const DB::Exception &)
11271152 {
@@ -1131,7 +1156,7 @@ inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, Re
11311156 }
11321157 else
11331158 {
1134- auto ok = readDateTimeTextImpl<ReturnType, true >(whole, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters);
1159+ auto ok = readDateTimeTextImpl<ReturnType, true >(whole, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters, saturate_on_overflow );
11351160 if (!ok && (buf.eof () || *buf.position () != ' .' ))
11361161 return ReturnType (false );
11371162 }
@@ -1367,14 +1392,14 @@ inline bool tryReadTimeText(time_t & time, ReadBuffer & buf, const DateLUTImpl &
13671392 return readTimeTextImpl<bool >(time, buf, time_zone, allowed_date_delimiters, allowed_time_delimiters);
13681393}
13691394
1370- inline bool tryReadDateTimeText (time_t & datetime, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance(), const char * allowed_date_delimiters = nullptr, const char * allowed_time_delimiters = nullptr)
1395+ inline bool tryReadDateTimeText (time_t & datetime, ReadBuffer & buf, const DateLUTImpl & time_zone = DateLUT::instance(), const char * allowed_date_delimiters = nullptr, const char * allowed_time_delimiters = nullptr, bool saturate_on_overflow = true )
13711396{
1372- return readDateTimeTextImpl<bool >(datetime, buf, time_zone, allowed_date_delimiters, allowed_time_delimiters);
1397+ return readDateTimeTextImpl<bool >(datetime, buf, time_zone, allowed_date_delimiters, allowed_time_delimiters, saturate_on_overflow );
13731398}
13741399
1375- inline bool tryReadDateTime64Text (DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance(), const char * allowed_date_delimiters = nullptr, const char * allowed_time_delimiters = nullptr)
1400+ inline bool tryReadDateTime64Text (DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance(), const char * allowed_date_delimiters = nullptr, const char * allowed_time_delimiters = nullptr, bool saturate_on_overflow = true )
13761401{
1377- return readDateTimeTextImpl<bool >(datetime64, scale, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters);
1402+ return readDateTimeTextImpl<bool >(datetime64, scale, buf, date_lut, allowed_date_delimiters, allowed_time_delimiters, saturate_on_overflow );
13781403}
13791404
13801405inline bool tryReadTime64Text (Time64 & time64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance(), const char * allowed_date_delimiters = nullptr, const char * allowed_time_delimiters = nullptr)
0 commit comments