mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 16:50:48 +00:00
Using cctz library [#CLICKHOUSE-2].
This commit is contained in:
parent
ed60f63e26
commit
8de0740291
@ -4,6 +4,8 @@ SET(CONFIG_VERSION ${CMAKE_CURRENT_BINARY_DIR}/include/common/config_version.h)
|
|||||||
SET(CONFIG_COMMON ${CMAKE_CURRENT_BINARY_DIR}/include/common/config_common.h)
|
SET(CONFIG_COMMON ${CMAKE_CURRENT_BINARY_DIR}/include/common/config_common.h)
|
||||||
|
|
||||||
include_directories (include)
|
include_directories (include)
|
||||||
|
include_directories (BEFORE ${CMAKE_SOURCE_DIR}/contrib/libcctz/include)
|
||||||
|
|
||||||
include(${CMAKE_SOURCE_DIR}/cmake/dbms_include.cmake)
|
include(${CMAKE_SOURCE_DIR}/cmake/dbms_include.cmake)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
@ -77,16 +79,14 @@ else ()
|
|||||||
message (STATUS "Disabling libtcmalloc for valgrind better analysis")
|
message (STATUS "Disabling libtcmalloc for valgrind better analysis")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
include (${ClickHouse_SOURCE_DIR}/cmake/find_glib.cmake)
|
|
||||||
|
|
||||||
find_package (Threads)
|
find_package (Threads)
|
||||||
|
|
||||||
target_link_libraries (
|
target_link_libraries (
|
||||||
common
|
common
|
||||||
pocoext
|
pocoext
|
||||||
|
cctz
|
||||||
${MALLOC_LIBRARIES}
|
${MALLOC_LIBRARIES}
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
${GLIB_LIBS}
|
|
||||||
${ICU_LIBS}
|
${ICU_LIBS}
|
||||||
${RT_LIBRARIES})
|
${RT_LIBRARIES})
|
||||||
|
|
||||||
|
@ -1,121 +1,35 @@
|
|||||||
#pragma GCC diagnostic push
|
#include <civil_time.h>
|
||||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
#include <time_zone.h>
|
||||||
#if __clang__
|
|
||||||
#pragma GCC diagnostic ignored "-Wdeprecated-register"
|
|
||||||
#endif
|
|
||||||
#include <glib.h>
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
|
|
||||||
#include <common/DateLUTImpl.h>
|
#include <common/DateLUTImpl.h>
|
||||||
#include <Poco/Exception.h>
|
#include <Poco/Exception.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <chrono>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
namespace details
|
|
||||||
{
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
struct GTimeZoneUnref
|
UInt8 getDayOfWeek(const cctz::civil_day & date)
|
||||||
{
|
{
|
||||||
void operator()(GTimeZone * tz) const
|
cctz::weekday day_of_week = cctz::get_weekday(date);
|
||||||
|
switch (day_of_week)
|
||||||
{
|
{
|
||||||
g_time_zone_unref(tz);
|
case cctz::weekday::monday: return 1;
|
||||||
|
case cctz::weekday::tuesday: return 2;
|
||||||
|
case cctz::weekday::wednesday: return 3;
|
||||||
|
case cctz::weekday::thursday: return 4;
|
||||||
|
case cctz::weekday::friday: return 5;
|
||||||
|
case cctz::weekday::saturday: return 6;
|
||||||
|
case cctz::weekday::sunday: return 7;
|
||||||
|
default:
|
||||||
|
throw Poco::Exception("Logical error: incorrect week day.");
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
using GTimeZonePtr = std::unique_ptr<GTimeZone, GTimeZoneUnref>;
|
|
||||||
|
|
||||||
struct GDateTimeUnref
|
|
||||||
{
|
|
||||||
void operator()(GDateTime * dt) const
|
|
||||||
{
|
|
||||||
g_date_time_unref(dt);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using GDateTimePtr = std::unique_ptr<GDateTime, GDateTimeUnref>;
|
|
||||||
|
|
||||||
|
|
||||||
GTimeZonePtr createGTimeZone(const std::string & description)
|
|
||||||
{
|
|
||||||
GTimeZone * tz = g_time_zone_new(description.c_str());
|
|
||||||
if (tz == nullptr)
|
|
||||||
throw Poco::Exception("Failed to create GTimeZone object.");
|
|
||||||
|
|
||||||
return GTimeZonePtr(tz);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GDateTimePtr createGDateTimeUTC(time_t timestamp)
|
|
||||||
{
|
|
||||||
GDateTime * dt = g_date_time_new_from_unix_utc(timestamp);
|
|
||||||
if (dt == nullptr)
|
|
||||||
throw Poco::Exception("Failed to create GDateTime object.");
|
|
||||||
|
|
||||||
return GDateTimePtr(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Create GDateTime object, interpreting passed unix timestamp in passed timezone.
|
|
||||||
GDateTimePtr createGDateTimeLocal(const GTimeZonePtr & p_tz, time_t timestamp)
|
|
||||||
{
|
|
||||||
GDateTimePtr utc = createGDateTimeUTC(timestamp);
|
|
||||||
GDateTime * local = g_date_time_to_timezone(utc.get(), p_tz.get());
|
|
||||||
if (local == nullptr)
|
|
||||||
throw Poco::Exception("Failed to create GDateTime object.");
|
|
||||||
|
|
||||||
return GDateTimePtr(local);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Create GDateTime object, at beginning of same day in passed time zone.
|
|
||||||
GDateTimePtr createSameDayInDifferentTimeZone(const GTimeZonePtr & p_tz, const GDateTimePtr & p_dt)
|
|
||||||
{
|
|
||||||
GDateTime * dt = p_dt.get();
|
|
||||||
|
|
||||||
gint year;
|
|
||||||
gint month;
|
|
||||||
gint day;
|
|
||||||
g_date_time_get_ymd(dt, &year, &month, &day);
|
|
||||||
|
|
||||||
GDateTime * local_dt = g_date_time_new(p_tz.get(), year, month, day, 0, 0, 0);
|
|
||||||
if (local_dt == nullptr)
|
|
||||||
throw Poco::Exception("Failed to create GDateTime object.");
|
|
||||||
|
|
||||||
return GDateTimePtr(local_dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
GDateTimePtr toNextDay(const GTimeZonePtr & p_tz, const GDateTimePtr & p_dt)
|
|
||||||
{
|
|
||||||
GDateTime * dt = p_dt.get();
|
|
||||||
if (dt == nullptr)
|
|
||||||
throw Poco::Exception("Null pointer.");
|
|
||||||
|
|
||||||
dt = g_date_time_add_days(dt, 1);
|
|
||||||
if (dt == nullptr)
|
|
||||||
throw Poco::Exception("Failed to create GDateTime object.");
|
|
||||||
|
|
||||||
GDateTimePtr p_next_dt = GDateTimePtr(dt);
|
|
||||||
GDateTime * next_dt = p_next_dt.get();
|
|
||||||
|
|
||||||
gint year;
|
|
||||||
gint month;
|
|
||||||
gint day;
|
|
||||||
g_date_time_get_ymd(next_dt, &year, &month, &day);
|
|
||||||
|
|
||||||
dt = g_date_time_new(p_tz.get(), year, month, day, 0, 0, 0);
|
|
||||||
if (dt == nullptr)
|
|
||||||
throw Poco::Exception("Failed to create GDateTime object.");
|
|
||||||
|
|
||||||
return GDateTimePtr(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -125,28 +39,29 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
|||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
time_t start_of_day = DATE_LUT_MIN;
|
time_t start_of_day = DATE_LUT_MIN;
|
||||||
|
|
||||||
details::GTimeZonePtr p_tz = details::createGTimeZone(time_zone);
|
cctz::time_zone cctz_time_zone;
|
||||||
details::GDateTimePtr p_dt = details::createSameDayInDifferentTimeZone(p_tz, details::createGDateTimeUTC(start_of_day));
|
if (!cctz::load_time_zone(time_zone.data(), &cctz_time_zone))
|
||||||
|
throw Poco::Exception("Cannot load time zone " + time_zone_);
|
||||||
|
|
||||||
|
cctz::time_zone::absolute_lookup start_of_epoch_lookup = cctz_time_zone.lookup(std::chrono::system_clock::from_time_t(start_of_day));
|
||||||
|
cctz::civil_day date{start_of_epoch_lookup.cs};
|
||||||
|
|
||||||
|
offset_at_start_of_epoch = start_of_epoch_lookup.offset;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (i > DATE_LUT_MAX_DAY_NUM)
|
if (i > DATE_LUT_MAX_DAY_NUM)
|
||||||
throw Poco::Exception("Cannot create DateLUTImpl: i > DATE_LUT_MAX_DAY_NUM.");
|
throw Poco::Exception("Cannot create DateLUTImpl: i > DATE_LUT_MAX_DAY_NUM.");
|
||||||
|
|
||||||
GDateTime * dt = p_dt.get();
|
cctz::time_zone::civil_lookup lookup = cctz_time_zone.lookup(date);
|
||||||
|
|
||||||
start_of_day = g_date_time_to_unix(dt);
|
start_of_day = std::chrono::system_clock::to_time_t(lookup.pre); /// Ambiguouty is possible.
|
||||||
|
|
||||||
gint year;
|
|
||||||
gint month;
|
|
||||||
gint day;
|
|
||||||
g_date_time_get_ymd(dt, &year, &month, &day);
|
|
||||||
|
|
||||||
Values & values = lut[i];
|
Values & values = lut[i];
|
||||||
values.year = year;
|
values.year = date.year();
|
||||||
values.month = month;
|
values.month = date.month();
|
||||||
values.day_of_month = day;
|
values.day_of_month = date.day();
|
||||||
values.day_of_week = g_date_time_get_day_of_week(dt);
|
values.day_of_week = getDayOfWeek(date);
|
||||||
values.date = start_of_day;
|
values.date = start_of_day;
|
||||||
|
|
||||||
values.time_at_offset_change = 0;
|
values.time_at_offset_change = 0;
|
||||||
@ -160,8 +75,7 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
|||||||
{
|
{
|
||||||
lut[i - 1].amount_of_offset_change = amount_of_offset_change_at_prev_day;
|
lut[i - 1].amount_of_offset_change = amount_of_offset_change_at_prev_day;
|
||||||
|
|
||||||
const auto utc_offset_at_beginning_of_day = g_date_time_get_utc_offset(
|
const auto utc_offset_at_beginning_of_day = cctz_time_zone.lookup(std::chrono::system_clock::from_time_t(lut[i - 1].date)).offset;
|
||||||
details::createGDateTimeLocal(p_tz, lut[i - 1].date).get());
|
|
||||||
|
|
||||||
/// Find a time (timestamp offset from beginning of day),
|
/// Find a time (timestamp offset from beginning of day),
|
||||||
/// when UTC offset was changed. Search is performed with 15-minute granularity, assuming it is enough.
|
/// when UTC offset was changed. Search is performed with 15-minute granularity, assuming it is enough.
|
||||||
@ -169,8 +83,8 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
|||||||
time_t time_at_offset_change = 900;
|
time_t time_at_offset_change = 900;
|
||||||
while (time_at_offset_change < 65536)
|
while (time_at_offset_change < 65536)
|
||||||
{
|
{
|
||||||
auto utc_offset_at_current_time = g_date_time_get_utc_offset(
|
auto utc_offset_at_current_time = cctz_time_zone.lookup(std::chrono::system_clock::from_time_t(
|
||||||
details::createGDateTimeLocal(p_tz, lut[i - 1].date + time_at_offset_change).get());
|
lut[i - 1].date + time_at_offset_change)).offset;
|
||||||
|
|
||||||
if (utc_offset_at_current_time != utc_offset_at_beginning_of_day)
|
if (utc_offset_at_current_time != utc_offset_at_beginning_of_day)
|
||||||
break;
|
break;
|
||||||
@ -186,7 +100,7 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Going to next day.
|
/// Going to next day.
|
||||||
p_dt = details::toNextDay(p_tz, p_dt);
|
++date;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
while (start_of_day <= DATE_LUT_MAX);
|
while (start_of_day <= DATE_LUT_MAX);
|
||||||
@ -198,6 +112,4 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
|||||||
if (lut[day].month == 1 && lut[day].day_of_month == 1)
|
if (lut[day].month == 1 && lut[day].day_of_month == 1)
|
||||||
years_lut[lut[day].year - DATE_LUT_MIN_YEAR] = day;
|
years_lut[lut[day].year - DATE_LUT_MIN_YEAR] = day;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset_at_start_of_epoch = g_time_zone_get_offset(p_tz.get(), g_time_zone_find_interval(p_tz.get(), G_TIME_TYPE_UNIVERSAL, 0));
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user