mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 00:52:02 +00:00
Unit tests passing
This commit is contained in:
parent
8271cec093
commit
1bb62f578b
@ -59,7 +59,7 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
||||
|
||||
offset_at_start_of_epoch = cctz_time_zone.lookup(cctz_time_zone.lookup(epoch).pre).offset;
|
||||
offset_at_start_of_lut = cctz_time_zone.lookup(cctz_time_zone.lookup(lut_start).pre).offset;
|
||||
offset_is_whole_number_of_hours_everytime = true;
|
||||
offset_is_whole_number_of_hours_during_epoch = true;
|
||||
|
||||
cctz::civil_day date = lut_start;
|
||||
|
||||
@ -105,8 +105,8 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
||||
values.time_at_offset_change_value = 0;
|
||||
values.amount_of_offset_change_value = 0;
|
||||
|
||||
if (offset_is_whole_number_of_hours_everytime && start_of_day > 0 && start_of_day % 3600)
|
||||
offset_is_whole_number_of_hours_everytime = false;
|
||||
if (offset_is_whole_number_of_hours_during_epoch && start_of_day > 0 && start_of_day % 3600)
|
||||
offset_is_whole_number_of_hours_during_epoch = false;
|
||||
|
||||
/// If UTC offset was changed this day.
|
||||
/// Change in time zone without transition is possible, e.g. Moscow 1991 Sun, 31 Mar, 02:00 MSK to EEST
|
||||
|
@ -185,7 +185,7 @@ private:
|
||||
time_t offset_at_start_of_epoch;
|
||||
/// UTC offset at the beginning of the first supported year.
|
||||
time_t offset_at_start_of_lut;
|
||||
bool offset_is_whole_number_of_hours_everytime;
|
||||
bool offset_is_whole_number_of_hours_during_epoch;
|
||||
|
||||
/// Time zone name.
|
||||
std::string time_zone;
|
||||
@ -193,15 +193,19 @@ private:
|
||||
inline LUTIndex findIndex(time_t t) const
|
||||
{
|
||||
/// First guess.
|
||||
const UInt32 guess = ((t / 86400) + daynum_offset_epoch) & date_lut_mask;
|
||||
UInt32 guess = ((t / 86400) + daynum_offset_epoch) & date_lut_mask;
|
||||
|
||||
/// For negative time_t the integer division was rounded up, so the guess is offset by one.
|
||||
if (unlikely(t < 0))
|
||||
--guess;
|
||||
|
||||
/// UTC offset is from -12 to +14 in all known time zones. This requires checking only three indices.
|
||||
if (t >= lut[guess].date && t < lut[UInt32(guess + 1)].date)
|
||||
if (t >= lut[guess].date && t < lut[guess + 1].date)
|
||||
return LUTIndex(guess);
|
||||
|
||||
/// Time zones that have offset 0 from UTC do daylight saving time change (if any)
|
||||
/// towards increasing UTC offset (example: British Standard Time).
|
||||
if (t >= lut[UInt32(guess + 1)].date)
|
||||
if (t >= lut[guess + 1].date)
|
||||
return LUTIndex(guess + 1);
|
||||
|
||||
return LUTIndex(guess - 1);
|
||||
@ -253,7 +257,6 @@ public:
|
||||
|
||||
// Methods only for unit-testing, it makes very little sense to use it from user code.
|
||||
auto getOffsetAtStartOfEpoch() const { return offset_at_start_of_epoch; }
|
||||
auto getOffsetIsWholNumberOfHoursEveryWhere() const { return offset_is_whole_number_of_hours_everytime; }
|
||||
auto getTimeOffsetAtStartOfLUT() const { return offset_at_start_of_lut; }
|
||||
|
||||
/// All functions below are thread-safe; arguments are not checked.
|
||||
@ -456,8 +459,8 @@ public:
|
||||
|
||||
inline unsigned toMinute(time_t t) const
|
||||
{
|
||||
if (offset_is_whole_number_of_hours_everytime)
|
||||
return ((t + DATE_LUT_ADD) / 60) % 60;
|
||||
if (t >= 0 && offset_is_whole_number_of_hours_during_epoch)
|
||||
return (t / 60) % 60;
|
||||
|
||||
/// To consider the DST changing situation within this day
|
||||
/// also make the special timezones with no whole hour offset such as 'Australia/Lord_Howe' been taken into account.
|
||||
@ -478,8 +481,8 @@ public:
|
||||
|
||||
inline time_t toStartOfTenMinutes(time_t t) const
|
||||
{
|
||||
if (offset_is_whole_number_of_hours_everytime)
|
||||
return roundDown(t, 600);
|
||||
if (t >= 0 && offset_is_whole_number_of_hours_during_epoch)
|
||||
return t / 600 * 600;
|
||||
|
||||
/// More complex logic is for Nepal - it has offset 05:45. Australia/Eucla is also unfortunate.
|
||||
Int64 date = find(t).date;
|
||||
@ -489,8 +492,8 @@ public:
|
||||
/// NOTE: Assuming timezone transitions are multiple of hours. Lord Howe Island in Australia is a notable exception.
|
||||
inline time_t toStartOfHour(time_t t) const
|
||||
{
|
||||
if (offset_is_whole_number_of_hours_everytime)
|
||||
return roundDown(t, 3600);
|
||||
if (t >= 0 && offset_is_whole_number_of_hours_during_epoch)
|
||||
return t / 3600 * 3600;
|
||||
|
||||
Int64 date = find(t).date;
|
||||
return date + (t - date) / 3600 * 3600;
|
||||
@ -773,8 +776,8 @@ public:
|
||||
/// We count all hour-length intervals, unrelated to offset changes.
|
||||
inline time_t toRelativeHourNum(time_t t) const
|
||||
{
|
||||
if (offset_is_whole_number_of_hours_everytime)
|
||||
return (t + DATE_LUT_ADD) / 3600 - (DATE_LUT_ADD / 3600);
|
||||
if (t >= 0 && offset_is_whole_number_of_hours_during_epoch)
|
||||
return t / 3600;
|
||||
|
||||
/// Assume that if offset was fractional, then the fraction is the same as at the beginning of epoch.
|
||||
/// NOTE This assumption is false for "Pacific/Pitcairn" and "Pacific/Kiritimati" time zones.
|
||||
@ -848,7 +851,7 @@ public:
|
||||
|
||||
t = roundDown(t, seconds);
|
||||
|
||||
if (offset_is_whole_number_of_hours_everytime)
|
||||
if (t >= 0 && offset_is_whole_number_of_hours_during_epoch)
|
||||
return t;
|
||||
|
||||
/// TODO check if it's correct.
|
||||
|
@ -297,7 +297,6 @@ TEST_P(DateLUTWithTimeZone, VaidateTimeComponentsAroundEpoch)
|
||||
<< "\n\tTimezone: " << timezone_name
|
||||
<< "\n\ttimestamp: " << i
|
||||
<< "\n\t offset at start of epoch : " << lut.getOffsetAtStartOfEpoch()
|
||||
<< "\n\t offset_is_whole_number_of_hours_everytime : " << lut.getOffsetIsWholNumberOfHoursEveryWhere()
|
||||
<< "\n\t offset_at_start_of_lut : " << lut.getTimeOffsetAtStartOfLUT());
|
||||
|
||||
EXPECT_GE(24, lut.toHour(i));
|
||||
@ -336,7 +335,7 @@ INSTANTIATE_TEST_SUITE_P(ExoticTimezones,
|
||||
})
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimeZones,
|
||||
INSTANTIATE_TEST_SUITE_P(AllTimeZones,
|
||||
DateLUTWithTimeZone,
|
||||
::testing::ValuesIn(allTimezones())
|
||||
);
|
||||
@ -391,11 +390,15 @@ TEST_P(DateLUTWithTimeZoneAndTimeRange, InRange)
|
||||
{
|
||||
SCOPED_TRACE(expected_time_t);
|
||||
|
||||
const auto tz_time = cctz::convert(std::chrono::system_clock::from_time_t(expected_time_t), tz);
|
||||
const cctz::civil_second tz_time = cctz::convert(std::chrono::system_clock::from_time_t(expected_time_t), tz);
|
||||
|
||||
/// Weird offset, not supported.
|
||||
/// Example: Africa/Monrovia has offset UTC-0:44:30 in year 1970.
|
||||
if (tz.lookup(std::chrono::system_clock::from_time_t(expected_time_t)).offset % 900)
|
||||
|
||||
auto timestamp_current_day_pre = std::chrono::system_clock::to_time_t(tz.lookup(cctz::civil_day(tz_time)).pre);
|
||||
auto timestamp_current_day_post = std::chrono::system_clock::to_time_t(tz.lookup(cctz::civil_day(tz_time) + 1).post);
|
||||
|
||||
if (timestamp_current_day_pre % 900 || timestamp_current_day_post % 900)
|
||||
continue;
|
||||
|
||||
/// Unsupported timezone transitions - not in 15-minute time point or to different day.
|
||||
@ -410,7 +413,7 @@ TEST_P(DateLUTWithTimeZoneAndTimeRange, InRange)
|
||||
|
||||
bool has_transition = false;
|
||||
cctz::time_zone::civil_transition transition{};
|
||||
if (tz.next_transition(std::chrono::system_clock::from_time_t(expected_time_t), &transition)
|
||||
if (tz.next_transition(std::chrono::system_clock::from_time_t(expected_time_t - 1), &transition)
|
||||
&& (transition.from.day() == tz_time.day() || transition.to.day() == tz_time.day()))
|
||||
{
|
||||
has_transition = true;
|
||||
@ -418,9 +421,9 @@ TEST_P(DateLUTWithTimeZoneAndTimeRange, InRange)
|
||||
|
||||
if (has_transition && (transition.from.second() != 0 || transition.from.minute() % 15 != 0))
|
||||
{
|
||||
std::cerr << "Skipping " << timezone_name << " " << tz_time
|
||||
/*std::cerr << "Skipping " << timezone_name << " " << tz_time
|
||||
<< " because of unsupported timezone transition from " << transition.from << " to " << transition.to
|
||||
<< " (not divisible by 15 minutes)\n";
|
||||
<< " (not divisible by 15 minutes)\n";*/
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -428,9 +431,9 @@ TEST_P(DateLUTWithTimeZoneAndTimeRange, InRange)
|
||||
if (has_transition && cctz::civil_day(transition.from) == cctz::civil_day(transition.to) + 1
|
||||
&& transition.from != cctz::civil_day(transition.from))
|
||||
{
|
||||
std::cerr << "Skipping " << timezone_name << " " << tz_time
|
||||
/*std::cerr << "Skipping " << timezone_name << " " << tz_time
|
||||
<< " because of unsupported timezone transition from " << transition.from << " to " << transition.to
|
||||
<< " (to previous day but not at midnight)\n";
|
||||
<< " (to previous day but not at midnight)\n";*/
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -438,9 +441,9 @@ TEST_P(DateLUTWithTimeZoneAndTimeRange, InRange)
|
||||
if (has_transition
|
||||
&& std::abs(transition.from - transition.to) > 3600 * 3)
|
||||
{
|
||||
std::cerr << "Skipping " << timezone_name << " " << tz_time
|
||||
/*std::cerr << "Skipping " << timezone_name << " " << tz_time
|
||||
<< " because of unsupported timezone transition from " << transition.from << " to " << transition.to
|
||||
<< " (it is too large)\n";
|
||||
<< " (it is too large)\n";*/
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -457,23 +460,14 @@ TEST_P(DateLUTWithTimeZoneAndTimeRange, InRange)
|
||||
const auto time_string = cctz::format("%E4Y-%m-%d %H:%M:%S", std::chrono::system_clock::from_time_t(expected_time_t), tz);
|
||||
EXPECT_EQ(time_string, lut.timeToString(expected_time_t));
|
||||
|
||||
// it makes sense to let test execute all checks above to simplify debugging,
|
||||
// but once we've found a bad apple, no need to dig deeper.
|
||||
/// It makes sense to let test execute all checks above to simplify debugging,
|
||||
/// but once we've found a bad apple, no need to dig deeper.
|
||||
if (countFailures(*test_info->result()).total >= max_failures_per_case)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Next tests are disabled due to following reasons:
|
||||
* 1. They are huge and take enormous amount of time to run
|
||||
* 2. Current implementation of DateLUTImpl is inprecise and some cases fail and it seems impractical to try to fix those.
|
||||
* 3. Many failures (~300) were fixed while refactoring, about ~40 remain the same and 3 new introduced:
|
||||
* "Asia/Gaza"
|
||||
* "Pacific/Enderbury"
|
||||
* "Pacific/Kiritimati"
|
||||
* So it would be tricky to skip knonw failures to allow all unit tests to pass.
|
||||
*/
|
||||
INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_Year2010,
|
||||
INSTANTIATE_TEST_SUITE_P(AllTimezones_Year2010,
|
||||
DateLUTWithTimeZoneAndTimeRange,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(allTimezones()),
|
||||
@ -484,7 +478,7 @@ INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_Year2010,
|
||||
}))
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_Year1970_WHOLE,
|
||||
INSTANTIATE_TEST_SUITE_P(AllTimezones_Year1970_WHOLE,
|
||||
DateLUTWithTimeZoneAndTimeRange,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(allTimezones(false)),
|
||||
@ -494,7 +488,7 @@ INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_Year1970_WHOLE,
|
||||
}))
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_Year2010_WHOLE,
|
||||
INSTANTIATE_TEST_SUITE_P(AllTimezones_Year2010_WHOLE,
|
||||
DateLUTWithTimeZoneAndTimeRange,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(allTimezones(false)),
|
||||
@ -504,7 +498,7 @@ INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_Year2010_WHOLE,
|
||||
}))
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_Year2020_WHOLE,
|
||||
INSTANTIATE_TEST_SUITE_P(AllTimezones_Year2020_WHOLE,
|
||||
DateLUTWithTimeZoneAndTimeRange,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(allTimezones()),
|
||||
@ -514,7 +508,7 @@ INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_Year2020_WHOLE,
|
||||
}))
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_PreEpoch,
|
||||
INSTANTIATE_TEST_SUITE_P(AllTimezones_PreEpoch,
|
||||
DateLUTWithTimeZoneAndTimeRange,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(allTimezones(false)),
|
||||
@ -524,7 +518,7 @@ INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_PreEpoch,
|
||||
}))
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DISABLED_AllTimezones_Year1970,
|
||||
INSTANTIATE_TEST_SUITE_P(AllTimezones_Year1970,
|
||||
DateLUTWithTimeZoneAndTimeRange,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(allTimezones(false)),
|
||||
|
Loading…
Reference in New Issue
Block a user