Skip to content

Commit

Permalink
Merge pull request #21069 from ClickHouse/backport/21.2/21023
Browse files Browse the repository at this point in the history
Backport #21023 to 21.2: Fix wrong formatting of overflowed DateTime64
  • Loading branch information
alexey-milovidov committed Feb 22, 2021
2 parents 44932f1 + 05cb645 commit 0ece2fe
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 19 deletions.
36 changes: 17 additions & 19 deletions base/common/DateLUTImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <ctime>
#include <string>


#define DATE_LUT_MAX (0xFFFFFFFFU - 86400)
#define DATE_LUT_MAX_DAY_NUM (0xFFFFFFFFU / 86400)
/// Table size is bigger than DATE_LUT_MAX_DAY_NUM to fill all indices within UInt16 range: this allows to remove extra check.
Expand Down Expand Up @@ -249,7 +250,7 @@ class DateLUTImpl
{
DayNum index = findIndex(t);

if (unlikely(index == 0))
if (unlikely(index == 0 || index > DATE_LUT_MAX_DAY_NUM))
return t + offset_at_start_of_epoch;

time_t res = t - lut[index].date;
Expand All @@ -264,18 +265,18 @@ class DateLUTImpl
{
DayNum index = findIndex(t);

/// If it is not 1970 year (findIndex found nothing appropriate),
/// than limit number of hours to avoid insane results like 1970-01-01 89:28:15
if (unlikely(index == 0))
/// If it is overflow case,
/// then limit number of hours to avoid insane results like 1970-01-01 89:28:15
if (unlikely(index == 0 || index > DATE_LUT_MAX_DAY_NUM))
return static_cast<unsigned>((t + offset_at_start_of_epoch) / 3600) % 24;

time_t res = t - lut[index].date;
time_t time = t - lut[index].date;

/// Data is cleaned to avoid possibility of underflow.
if (res >= lut[index].time_at_offset_change)
res += lut[index].amount_of_offset_change;
if (time >= lut[index].time_at_offset_change)
time += lut[index].amount_of_offset_change;

return res / 3600;
unsigned res = time / 3600;
return res <= 23 ? res : 0;
}

/** Only for time zones with/when offset from UTC is multiple of five minutes.
Expand All @@ -289,12 +290,12 @@ class DateLUTImpl
* each minute, with added or subtracted leap second, spans exactly 60 unix timestamps.
*/

inline unsigned toSecond(time_t t) const { return t % 60; }
inline unsigned toSecond(time_t t) const { return UInt32(t) % 60; }

inline unsigned toMinute(time_t t) const
{
if (offset_is_whole_number_of_hours_everytime)
return (t / 60) % 60;
return (UInt32(t) / 60) % 60;

UInt32 date = find(t).date;
return (UInt32(t) - date) / 60 % 60;
Expand Down Expand Up @@ -530,9 +531,7 @@ class DateLUTImpl
}
}

/*
* check and change mode to effective
*/
/// Check and change mode to effective.
inline UInt8 check_week_mode(UInt8 mode) const
{
UInt8 week_format = (mode & 7);
Expand All @@ -541,10 +540,9 @@ class DateLUTImpl
return week_format;
}

/*
* Calc weekday from d
* Returns 0 for monday, 1 for tuesday ...
*/
/** Calculate weekday from d.
* Returns 0 for monday, 1 for tuesday...
*/
inline unsigned calc_weekday(DayNum d, bool sunday_first_day_of_week) const
{
if (!sunday_first_day_of_week)
Expand All @@ -553,7 +551,7 @@ class DateLUTImpl
return toDayOfWeek(DayNum(d + 1)) - 1;
}

/* Calc days in one year. */
/// Calculate days in one year.
inline unsigned calc_days_in_year(UInt16 year) const
{
return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)) ? 366 : 365);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- { echo }
SELECT toString(toDateTime('-922337203.6854775808', 1));
2106-02-07 15:41:33.6
SELECT toString(toDateTime('9922337203.6854775808', 1));
2104-12-30 00:50:11.6
SELECT toDateTime64(CAST('10000000000.1' AS Decimal64(1)), 1);
2106-02-07 20:50:08.1
SELECT toDateTime64(CAST('-10000000000.1' AS Decimal64(1)), 1);
2011-12-23 00:38:08.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- { echo }
SELECT toString(toDateTime('-922337203.6854775808', 1));
SELECT toString(toDateTime('9922337203.6854775808', 1));
SELECT toDateTime64(CAST('10000000000.1' AS Decimal64(1)), 1);
SELECT toDateTime64(CAST('-10000000000.1' AS Decimal64(1)), 1);

0 comments on commit 0ece2fe

Please sign in to comment.