mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 08:40:50 +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)
|
||||
|
||||
include_directories (include)
|
||||
include_directories (BEFORE ${CMAKE_SOURCE_DIR}/contrib/libcctz/include)
|
||||
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/dbms_include.cmake)
|
||||
|
||||
if (APPLE)
|
||||
@ -77,16 +79,14 @@ else ()
|
||||
message (STATUS "Disabling libtcmalloc for valgrind better analysis")
|
||||
endif ()
|
||||
|
||||
include (${ClickHouse_SOURCE_DIR}/cmake/find_glib.cmake)
|
||||
|
||||
find_package (Threads)
|
||||
|
||||
target_link_libraries (
|
||||
common
|
||||
pocoext
|
||||
cctz
|
||||
${MALLOC_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${GLIB_LIBS}
|
||||
${ICU_LIBS}
|
||||
${RT_LIBRARIES})
|
||||
|
||||
|
@ -1,121 +1,35 @@
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#if __clang__
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-register"
|
||||
#endif
|
||||
#include <glib.h>
|
||||
#pragma GCC diagnostic pop
|
||||
#include <civil_time.h>
|
||||
#include <time_zone.h>
|
||||
|
||||
#include <common/DateLUTImpl.h>
|
||||
#include <Poco/Exception.h>
|
||||
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace details
|
||||
{
|
||||
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;
|
||||
time_t start_of_day = DATE_LUT_MIN;
|
||||
|
||||
details::GTimeZonePtr p_tz = details::createGTimeZone(time_zone);
|
||||
details::GDateTimePtr p_dt = details::createSameDayInDifferentTimeZone(p_tz, details::createGDateTimeUTC(start_of_day));
|
||||
cctz::time_zone cctz_time_zone;
|
||||
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
|
||||
{
|
||||
if (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);
|
||||
|
||||
gint year;
|
||||
gint month;
|
||||
gint day;
|
||||
g_date_time_get_ymd(dt, &year, &month, &day);
|
||||
start_of_day = std::chrono::system_clock::to_time_t(lookup.pre); /// Ambiguouty is possible.
|
||||
|
||||
Values & values = lut[i];
|
||||
values.year = year;
|
||||
values.month = month;
|
||||
values.day_of_month = day;
|
||||
values.day_of_week = g_date_time_get_day_of_week(dt);
|
||||
values.year = date.year();
|
||||
values.month = date.month();
|
||||
values.day_of_month = date.day();
|
||||
values.day_of_week = getDayOfWeek(date);
|
||||
values.date = start_of_day;
|
||||
|
||||
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;
|
||||
|
||||
const auto utc_offset_at_beginning_of_day = g_date_time_get_utc_offset(
|
||||
details::createGDateTimeLocal(p_tz, lut[i - 1].date).get());
|
||||
const auto utc_offset_at_beginning_of_day = cctz_time_zone.lookup(std::chrono::system_clock::from_time_t(lut[i - 1].date)).offset;
|
||||
|
||||
/// 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.
|
||||
@ -169,8 +83,8 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
||||
time_t time_at_offset_change = 900;
|
||||
while (time_at_offset_change < 65536)
|
||||
{
|
||||
auto utc_offset_at_current_time = g_date_time_get_utc_offset(
|
||||
details::createGDateTimeLocal(p_tz, lut[i - 1].date + time_at_offset_change).get());
|
||||
auto utc_offset_at_current_time = cctz_time_zone.lookup(std::chrono::system_clock::from_time_t(
|
||||
lut[i - 1].date + time_at_offset_change)).offset;
|
||||
|
||||
if (utc_offset_at_current_time != utc_offset_at_beginning_of_day)
|
||||
break;
|
||||
@ -186,7 +100,7 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
|
||||
}
|
||||
|
||||
/// Going to next day.
|
||||
p_dt = details::toNextDay(p_tz, p_dt);
|
||||
++date;
|
||||
++i;
|
||||
}
|
||||
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)
|
||||
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