[Enhancement] function hour_from_unixtime (#60331)
Signed-off-by: Murphy <mofei@starrocks.com>
This commit is contained in:
parent
31168b0ac1
commit
d9b23cffb4
|
|
@ -17,11 +17,16 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <testutil/assert.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include "bench/bench_util.h"
|
||||
#include "exprs/hash_functions.h"
|
||||
#include "exprs/time_functions.h"
|
||||
#include "runtime/runtime_state.h"
|
||||
#include "testutil/function_utils.h"
|
||||
#include "util/hash.h"
|
||||
#include "util/phmap/phmap.h"
|
||||
|
||||
|
|
@ -201,6 +206,88 @@ BENCHMARK(BM_PhmapFlatHashSet_CrcHash64_Insert_Unmixed)->Arg(10 * 1000)->Arg(100
|
|||
BENCHMARK(BM_PhmapFlatHashSet_CrcHash64_Lookup)->Arg(10 * 1000)->Arg(100 * 1000)->Arg(1000 * 1000);
|
||||
BENCHMARK(BM_PhmapFlatHashSet_CrcHash64_Lookup_Unmixed)->Arg(10 * 1000)->Arg(100 * 1000)->Arg(1000 * 1000);
|
||||
|
||||
class HourFromUnixtimeBench {
|
||||
public:
|
||||
HourFromUnixtimeBench(int N = 4096)
|
||||
: N(N), min_ts(946684800), max_ts(1893456000), rng(12345), dist(min_ts, max_ts) {
|
||||
// Generate N random unix timestamps
|
||||
timestamps.reserve(N);
|
||||
for (int i = 0; i < N; ++i) {
|
||||
timestamps.push_back(dist(rng));
|
||||
}
|
||||
// Construct Column
|
||||
col = Int64Column::create();
|
||||
for (int i = 0; i < N; ++i) {
|
||||
col->append(timestamps[i]);
|
||||
}
|
||||
columns.emplace_back(col);
|
||||
// Construct context
|
||||
globals.__set_now_string("2020-01-01 00:00:00");
|
||||
globals.__set_timestamp_ms(1577836800000);
|
||||
globals.__set_time_zone("UTC");
|
||||
state = std::make_unique<starrocks::RuntimeState>(globals);
|
||||
utils = std::make_unique<starrocks::FunctionUtils>(state.get());
|
||||
}
|
||||
|
||||
void bench_hour_from_unixtime(benchmark::State& state_bench) {
|
||||
for (auto _ : state_bench) {
|
||||
auto result = starrocks::TimeFunctions::hour_from_unixtime(utils->get_fn_ctx(), columns).value();
|
||||
benchmark::DoNotOptimize(result);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_from_unixtime_extract_hour(benchmark::State& state_bench) {
|
||||
for (auto _ : state_bench) {
|
||||
auto dt_col_ptr = starrocks::TimeFunctions::from_unix_to_datetime_64(utils->get_fn_ctx(), columns).value();
|
||||
auto dt_col = starrocks::ColumnHelper::cast_to<starrocks::TYPE_DATETIME>(dt_col_ptr);
|
||||
int64_t sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
int year, month, day, hour, minute, second, usec;
|
||||
dt_col->get_data()[i].to_timestamp(&year, &month, &day, &hour, &minute, &second, &usec);
|
||||
sum += hour;
|
||||
}
|
||||
benchmark::DoNotOptimize(sum);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int N;
|
||||
int64_t min_ts, max_ts;
|
||||
std::mt19937_64 rng;
|
||||
std::uniform_int_distribution<int64_t> dist;
|
||||
std::vector<int64_t> timestamps;
|
||||
starrocks::Int64Column::Ptr col;
|
||||
starrocks::Columns columns;
|
||||
starrocks::TQueryGlobals globals;
|
||||
std::unique_ptr<starrocks::RuntimeState> state;
|
||||
std::unique_ptr<starrocks::FunctionUtils> utils;
|
||||
};
|
||||
|
||||
static void BM_HourFromUnixtime(benchmark::State& state) {
|
||||
static HourFromUnixtimeBench suite;
|
||||
suite.bench_hour_from_unixtime(state);
|
||||
}
|
||||
|
||||
static void BM_FromUnixtime_HourExtract(benchmark::State& state) {
|
||||
static HourFromUnixtimeBench suite;
|
||||
suite.bench_from_unixtime_extract_hour(state);
|
||||
}
|
||||
|
||||
// Run on (104 X 3200 MHz CPU s)
|
||||
// CPU Caches:
|
||||
// L1 Data 32 KiB (x52)
|
||||
// L1 Instruction 32 KiB (x52)
|
||||
// L2 Unified 1024 KiB (x52)
|
||||
// L3 Unified 36608 KiB (x2)
|
||||
// Load Average: 36.03, 17.40, 21.87
|
||||
// ----------------------------------------------------------------------
|
||||
// Benchmark Time CPU Iterations
|
||||
// ----------------------------------------------------------------------
|
||||
// BM_HourFromUnixtime 147895 ns 147841 ns 4147
|
||||
// BM_FromUnixtime_HourExtract 656650 ns 651969 ns 1445
|
||||
BENCHMARK(BM_HourFromUnixtime);
|
||||
BENCHMARK(BM_FromUnixtime_HourExtract);
|
||||
|
||||
} // namespace starrocks
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
|
@ -14,7 +14,11 @@
|
|||
|
||||
#include "exprs/time_functions.h"
|
||||
|
||||
#include <cctz/time_zone.h>
|
||||
#include <libdivide.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
|
|
@ -22,7 +26,6 @@
|
|||
#include "column/column_viewer.h"
|
||||
#include "exprs/binary_function.h"
|
||||
#include "exprs/unary_function.h"
|
||||
#include "gen_cpp/InternalService_types.h"
|
||||
#include "runtime/datetime_value.h"
|
||||
#include "runtime/runtime_state.h"
|
||||
#include "types/date_value.h"
|
||||
|
|
@ -1489,7 +1492,6 @@ StatusOr<ColumnPtr> TimeFunctions::_t_from_unix_to_datetime(FunctionContext* con
|
|||
DCHECK_EQ(columns.size(), 1);
|
||||
|
||||
RETURN_IF_COLUMNS_ONLY_NULL(columns);
|
||||
|
||||
ColumnViewer<TIMESTAMP_TYPE> data_column(columns[0]);
|
||||
|
||||
auto size = columns[0]->size();
|
||||
|
|
@ -1566,6 +1568,55 @@ StatusOr<ColumnPtr> TimeFunctions::from_unix_to_datetime_ms_64(FunctionContext*
|
|||
return _t_from_unix_to_datetime_ms<TYPE_BIGINT>(context, columns);
|
||||
}
|
||||
|
||||
static inline int64_t impl_hour_from_unixtime(int64_t unixtime) {
|
||||
// return (unixtime % 86400) / 3600;
|
||||
static const libdivide::divider<int64_t> fast_div_3600(3600);
|
||||
static const libdivide::divider<int64_t> fast_div_86400(86400);
|
||||
int64_t hour = (unixtime - unixtime / fast_div_86400 * 86400) / fast_div_3600;
|
||||
return hour;
|
||||
}
|
||||
|
||||
StatusOr<ColumnPtr> TimeFunctions::hour_from_unixtime(FunctionContext* context, const Columns& columns) {
|
||||
DCHECK_EQ(columns.size(), 1);
|
||||
RETURN_IF_COLUMNS_ONLY_NULL(columns);
|
||||
|
||||
static const auto epoch =
|
||||
std::chrono::time_point_cast<cctz::sys_seconds>(std::chrono::system_clock::from_time_t(0));
|
||||
|
||||
auto ctz = context->state()->timezone_obj();
|
||||
auto size = columns[0]->size();
|
||||
ColumnViewer<TYPE_BIGINT> data_column(columns[0]);
|
||||
ColumnBuilder<TYPE_INT> result(size);
|
||||
std::vector<int64_t> batch;
|
||||
|
||||
for (int row = 0; row < size; ++row) {
|
||||
if (data_column.is_null(row)) {
|
||||
result.append_null();
|
||||
continue;
|
||||
}
|
||||
|
||||
auto date = data_column.value(row);
|
||||
if (date < 0 || date > MAX_UNIX_TIMESTAMP) {
|
||||
result.append_null();
|
||||
continue;
|
||||
}
|
||||
|
||||
batch.push_back(date);
|
||||
|
||||
if (batch.size() == 16 || row == size - 1) {
|
||||
for (int i = 0; i < batch.size(); i++) {
|
||||
int64_t dt = batch[i];
|
||||
cctz::time_point<cctz::sys_seconds> t = epoch + cctz::seconds(dt);
|
||||
int offset = ctz.lookup_offset(t).offset;
|
||||
int hour = impl_hour_from_unixtime(dt + offset);
|
||||
result.append(hour);
|
||||
}
|
||||
batch.clear();
|
||||
}
|
||||
}
|
||||
return result.build(ColumnHelper::is_all_const(columns));
|
||||
}
|
||||
|
||||
std::string TimeFunctions::convert_format(const Slice& format) {
|
||||
switch (format.get_size()) {
|
||||
case 8:
|
||||
|
|
|
|||
|
|
@ -705,6 +705,14 @@ public:
|
|||
DEFINE_VECTORIZED_FN(from_unix_to_datetime_32);
|
||||
DEFINE_VECTORIZED_FN(from_unix_to_datetime_ms_64);
|
||||
|
||||
// TODO
|
||||
// DEFINE_VECTORIZED_FN(year_from_unixtime);
|
||||
// DEFINE_VECTORIZED_FN(month_from_unixtime);
|
||||
// DEFINE_VECTORIZED_FN(day_from_unixtime);
|
||||
DEFINE_VECTORIZED_FN(hour_from_unixtime);
|
||||
// DEFINE_VECTORIZED_FN(minute_from_unixtime);
|
||||
// DEFINE_VECTORIZED_FN(second_from_unixtime);
|
||||
|
||||
// from_unix_datetime with format's auxiliary method
|
||||
static Status from_unix_prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope);
|
||||
|
||||
|
|
|
|||
|
|
@ -201,6 +201,15 @@ void RuntimeState::_init(const TUniqueId& fragment_instance_id, const TQueryOpti
|
|||
_runtime_filter_port = _obj_pool->add(new RuntimeFilterPort(this));
|
||||
}
|
||||
|
||||
bool RuntimeState::set_timezone(const std::string& tz) {
|
||||
if (TimezoneUtils::find_cctz_time_zone(tz, _timezone_obj)) {
|
||||
_timezone = tz;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeState::init_mem_trackers(const TUniqueId& query_id, MemTracker* parent) {
|
||||
bool has_query_mem_tracker = _query_options.__isset.mem_limit && (_query_options.mem_limit > 0);
|
||||
int64_t bytes_limit = has_query_mem_tracker ? _query_options.mem_limit : -1;
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ public:
|
|||
int64_t timestamp_us() const { return _timestamp_us; }
|
||||
const std::string& timezone() const { return _timezone; }
|
||||
const cctz::time_zone& timezone_obj() const { return _timezone_obj; }
|
||||
bool set_timezone(const std::string& tz);
|
||||
const std::string& user() const { return _user; }
|
||||
const std::string& last_query_id() const { return _last_query_id; }
|
||||
const TUniqueId& query_id() const { return _query_id; }
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "testutil/function_utils.h"
|
||||
#include "types/date_value.h"
|
||||
#include "types/logical_type.h"
|
||||
#include "util/defer_op.h"
|
||||
|
||||
namespace starrocks {
|
||||
|
||||
|
|
@ -4103,4 +4104,40 @@ TEST_F(TimeFunctionsTest, IcbergTransTest) {
|
|||
ASSERT_EQ(1, v->get_data()[0]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TimeFunctionsTest, hourFromUnixtimeTest) {
|
||||
Int64Column::Ptr tc = Int64Column::create();
|
||||
// 1970-01-01 00:00:00 UTC
|
||||
tc->append(0); // hour = 0
|
||||
// 1970-01-01 01:00:00 UTC
|
||||
tc->append(3600); // hour = 1
|
||||
// 1970-01-01 12:34:56 UTC
|
||||
tc->append(45296); // hour = 12
|
||||
// 1970-01-01 23:59:59 UTC
|
||||
tc->append(86399); // hour = 23
|
||||
// 1970-01-02 00:00:00 UTC
|
||||
tc->append(86400); // hour = 0
|
||||
// 2000-01-01 08:00:00 UTC (946713600)
|
||||
tc->append(946713600); // hour = 8
|
||||
|
||||
int expected[] = {0, 1, 12, 23, 0, 8};
|
||||
|
||||
// Change timezone to UTC
|
||||
RuntimeState* state = _utils->get_fn_ctx()->state();
|
||||
std::string prev_timezone = state->timezone();
|
||||
ASSERT_TRUE(state->set_timezone("UTC"));
|
||||
DeferOp defer([&]() { state->set_timezone(prev_timezone); });
|
||||
|
||||
Columns columns;
|
||||
columns.emplace_back(tc);
|
||||
ColumnPtr result = TimeFunctions::hour_from_unixtime(_utils->get_fn_ctx(), columns).value();
|
||||
ASSERT_TRUE(result->is_numeric());
|
||||
ASSERT_FALSE(result->is_nullable());
|
||||
|
||||
auto hours = ColumnHelper::cast_to<TYPE_INT>(result);
|
||||
for (size_t i = 0; i < sizeof(expected) / sizeof(expected[0]); ++i) {
|
||||
EXPECT_EQ(expected[i], hours->get_data()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace starrocks
|
||||
|
|
|
|||
|
|
@ -586,6 +586,14 @@ vectorized_functions = [
|
|||
'TimeFunctions::from_unix_to_datetime_with_format_32',
|
||||
'TimeFunctions::from_unix_prepare', 'TimeFunctions::from_unix_close'],
|
||||
|
||||
# specialized version of from_unixtime to reduce the cost of datetime conversion
|
||||
# TODO: 50380 year_from_unixtime
|
||||
# TODO: 50381 month_from_unixtime
|
||||
# TODO: 50382 day_from_unixtime
|
||||
[50383, 'hour_from_unixtime', True, False, 'INT', ['BIGINT'], 'TimeFunctions::hour_from_unixtime'],
|
||||
# TODO: 50384 minute_from_unixtime
|
||||
# TODO: 50385 second_from_unixtime
|
||||
|
||||
[50310, 'dayname', True, False, 'VARCHAR', ['DATETIME'], 'TimeFunctions::day_name'],
|
||||
[50311, 'monthname', True, False, 'VARCHAR', ['DATETIME'], 'TimeFunctions::month_name'],
|
||||
[50320, 'convert_tz', True, False, 'DATETIME', ['DATETIME', 'VARCHAR', 'VARCHAR'], 'TimeFunctions::convert_tz',
|
||||
|
|
|
|||
|
|
@ -1614,6 +1614,16 @@ build_azure() {
|
|||
unset PKG_CONFIG_LIBDIR
|
||||
}
|
||||
|
||||
build_libdivide() {
|
||||
check_if_source_exist $LIBDIVIDE_SOURCE
|
||||
cd $TP_SOURCE_DIR/$LIBDIVIDE_SOURCE
|
||||
|
||||
$CMAKE_CMD . -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=$TP_INSTALL_DIR/
|
||||
|
||||
${BUILD_SYSTEM} -j "${PARALLEL}"
|
||||
${BUILD_SYSTEM} install
|
||||
}
|
||||
|
||||
# restore cxxflags/cppflags/cflags to default one
|
||||
restore_compile_flags() {
|
||||
# c preprocessor flags
|
||||
|
|
@ -1715,6 +1725,7 @@ declare -a all_packages=(
|
|||
xsimd
|
||||
libxml2
|
||||
azure
|
||||
libdivide
|
||||
)
|
||||
|
||||
# Machine specific packages
|
||||
|
|
|
|||
|
|
@ -620,6 +620,7 @@ if [[ -d $TP_SOURCE_DIR/$CCTZ_SOURCE ]] ; then
|
|||
cd $TP_SOURCE_DIR/$CCTZ_SOURCE
|
||||
if [ ! -f "$PATCHED_MARK" ] && [[ $CCTZ_SOURCE == "cctz-2.3" ]] ; then
|
||||
patch -p1 < "$TP_PATCH_DIR/cctz_civil_cache.patch"
|
||||
patch -p1 < "$TP_PATCH_DIR/cctz_02_lookup_offset.patch"
|
||||
touch "$PATCHED_MARK"
|
||||
fi
|
||||
cd -
|
||||
|
|
|
|||
|
|
@ -0,0 +1,223 @@
|
|||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index e8b2f34..97b34ac 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -178,3 +178,5 @@ install(FILES cmake/${PROJECT_NAME}-config.cmake
|
||||
)
|
||||
|
||||
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||
+
|
||||
+SET(CMAKE_CXX_FLAGS "-fno-omit-frame-pointer -O3 -g -gdwarf-4 ${CMAKE_CXX_FLAGS}")
|
||||
diff --git a/include/cctz/civil_time_detail.h b/include/cctz/civil_time_detail.h
|
||||
index decc5f2..3f7d6c8 100644
|
||||
--- a/include/cctz/civil_time_detail.h
|
||||
+++ b/include/cctz/civil_time_detail.h
|
||||
@@ -186,13 +186,13 @@ CONSTEXPR_F fields n_min(year_t y, diff_t m, diff_t d, diff_t hh, diff_t ch,
|
||||
CONSTEXPR_F fields n_sec(year_t y, diff_t m, diff_t d, diff_t hh, diff_t mm,
|
||||
diff_t ss) noexcept {
|
||||
// Optimization for when (non-constexpr) fields are already normalized.
|
||||
- if (0 <= ss && ss < 60) {
|
||||
+ if (__builtin_expect(0 <= ss && ss < 60, 1)) {
|
||||
const second_t nss = static_cast<second_t>(ss);
|
||||
- if (0 <= mm && mm < 60) {
|
||||
+ if (__builtin_expect(0 <= mm && mm < 60, 1)) {
|
||||
const minute_t nmm = static_cast<minute_t>(mm);
|
||||
- if (0 <= hh && hh < 24) {
|
||||
+ if (__builtin_expect(0 <= hh && hh < 24, 1)) {
|
||||
const hour_t nhh = static_cast<hour_t>(hh);
|
||||
- if (1 <= d && d <= 28 && 1 <= m && m <= 12) {
|
||||
+ if (__builtin_expect(1 <= d && d <= 28 && 1 <= m && m <= 12, 1)) {
|
||||
const day_t nd = static_cast<day_t>(d);
|
||||
const month_t nm = static_cast<month_t>(m);
|
||||
return fields(y, nm, nd, nhh, nmm, nss);
|
||||
diff --git a/include/cctz/time_zone.h b/include/cctz/time_zone.h
|
||||
index f97ea26..cdbd6a9 100644
|
||||
--- a/include/cctz/time_zone.h
|
||||
+++ b/include/cctz/time_zone.h
|
||||
@@ -104,6 +104,14 @@ class time_zone {
|
||||
return lookup(detail::split_seconds(tp).first);
|
||||
}
|
||||
|
||||
+ // Lookup the UTC offset for a timepoint
|
||||
+ // The returned the lookup result doesn't contain valid cs
|
||||
+ absolute_lookup lookup_offset(const time_point<seconds> &tp) const;
|
||||
+ template <typename D>
|
||||
+ absolute_lookup lookup_offset(const time_point<D> &tp) const {
|
||||
+ return lookup_offset(detail::split_seconds(tp).first);
|
||||
+ }
|
||||
+
|
||||
// A civil_lookup represents the absolute time(s) (time_point) that
|
||||
// correspond to the given civil time (cctz::civil_second) within this
|
||||
// time_zone. Usually the given civil time represents a unique instant
|
||||
diff --git a/src/cctz_benchmark.cc b/src/cctz_benchmark.cc
|
||||
index 179ae50..168cba5 100644
|
||||
--- a/src/cctz_benchmark.cc
|
||||
+++ b/src/cctz_benchmark.cc
|
||||
@@ -797,6 +797,24 @@ void BM_Time_ToCivil_CCTZ(benchmark::State& state) {
|
||||
}
|
||||
BENCHMARK(BM_Time_ToCivil_CCTZ);
|
||||
|
||||
+void BM_Time_ToCivil_LookupOffset_Batch1024(benchmark::State &state) {
|
||||
+ const cctz::time_zone tz = TestTimeZone();
|
||||
+ std::chrono::system_clock::time_point tp =
|
||||
+ std::chrono::system_clock::from_time_t(1750656243);
|
||||
+ std::chrono::system_clock::time_point tp2 =
|
||||
+ std::chrono::system_clock::from_time_t(1750656245);
|
||||
+ while (state.KeepRunning()) {
|
||||
+ std::swap(tp, tp2);
|
||||
+ // benchmark::DoNotOptimize(tz.lookup(tp).cs);
|
||||
+
|
||||
+ for (int i = 0; i < 1024; i++) {
|
||||
+ tp += std::chrono::seconds(1);
|
||||
+ benchmark::DoNotOptimize(tz.lookup_offset(tp).cs);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+BENCHMARK(BM_Time_ToCivil_LookupOffset_Batch1024);
|
||||
+
|
||||
void BM_Time_ToCivil_Libc(benchmark::State& state) {
|
||||
// No timezone support, so just use localtime.
|
||||
time_t t = 1384569027;
|
||||
diff --git a/src/time_zone_if.h b/src/time_zone_if.h
|
||||
index f925c6c..01af988 100644
|
||||
--- a/src/time_zone_if.h
|
||||
+++ b/src/time_zone_if.h
|
||||
@@ -36,6 +36,10 @@ class TimeZoneIf {
|
||||
|
||||
virtual time_zone::absolute_lookup BreakTime(
|
||||
const time_point<seconds>& tp) const = 0;
|
||||
+ virtual time_zone::absolute_lookup
|
||||
+ LookupOffset(const time_point<seconds> &tp) const {
|
||||
+ return BreakTime(tp);
|
||||
+ }
|
||||
virtual time_zone::civil_lookup MakeTime(
|
||||
const civil_second& cs) const = 0;
|
||||
|
||||
diff --git a/src/time_zone_impl.h b/src/time_zone_impl.h
|
||||
index 23fcddb..16f26ec 100644
|
||||
--- a/src/time_zone_impl.h
|
||||
+++ b/src/time_zone_impl.h
|
||||
@@ -50,6 +50,10 @@ class time_zone::Impl {
|
||||
return zone_->BreakTime(tp);
|
||||
}
|
||||
|
||||
+ time_zone::absolute_lookup LookupOffset(const time_point<seconds> &tp) const {
|
||||
+ return zone_->LookupOffset(tp);
|
||||
+ }
|
||||
+
|
||||
// Converts the civil-time components in this time zone into a time_point.
|
||||
// That is, the opposite of BreakTime(). The requested civil time may be
|
||||
// ambiguous or illegal due to a change of UTC offset.
|
||||
diff --git a/src/time_zone_info.cc b/src/time_zone_info.cc
|
||||
index eb1cd8a..031c8c4 100644
|
||||
--- a/src/time_zone_info.cc
|
||||
+++ b/src/time_zone_info.cc
|
||||
@@ -751,6 +751,64 @@ time_zone::absolute_lookup TimeZoneInfo::LocalTime(
|
||||
tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
|
||||
}
|
||||
|
||||
+time_zone::absolute_lookup
|
||||
+TimeZoneInfo::Offset(std::int_fast64_t unix_time,
|
||||
+ const TransitionType &tt) const {
|
||||
+ return {{}, tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
|
||||
+}
|
||||
+
|
||||
+time_zone::absolute_lookup TimeZoneInfo::Offset(std::int_fast64_t unix_time,
|
||||
+ const Transition &tr) const {
|
||||
+ const TransitionType &tt = transition_types_[tr.type_index];
|
||||
+ // std::int_fast64_t local_unix = unix_time + tt.utc_offset;
|
||||
+ return {{}, tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
|
||||
+}
|
||||
+
|
||||
+time_zone::absolute_lookup
|
||||
+TimeZoneInfo::LookupOffset(const time_point<seconds> &tp) const {
|
||||
+ std::int_fast64_t unix_time = ToUnixSeconds(tp);
|
||||
+ const std::size_t timecnt = transitions_.size();
|
||||
+ assert(timecnt != 0); // We always add a transition.
|
||||
+
|
||||
+ const std::size_t hint = local_time_hint_.load(std::memory_order_relaxed);
|
||||
+ // This branch is likely to be taken if the hint is valid and the unix_time
|
||||
+ // falls within the hinted transition range.
|
||||
+ if (0 < hint && hint < timecnt) [[likely]] {
|
||||
+ if (transitions_[hint - 1].unix_time <= unix_time) [[likely]] {
|
||||
+ if (unix_time < transitions_[hint].unix_time) [[likely]] {
|
||||
+ return Offset(unix_time, transitions_[hint - 1]);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((unix_time < transitions_[0].unix_time)) {
|
||||
+ return Offset(unix_time, transition_types_[default_transition_type_]);
|
||||
+ }
|
||||
+ if (unix_time >= transitions_.back().unix_time) {
|
||||
+ // After the last transition. If we extended the transitions using
|
||||
+ // future_spec_, shift back to a supported year using the 400-year
|
||||
+ // cycle of calendaric equivalence and then compensate accordingly.
|
||||
+ if (extended_) {
|
||||
+ const std::int_fast64_t diff =
|
||||
+ unix_time - transitions_[timecnt - 1].unix_time;
|
||||
+ const year_t shift = diff / kSecsPer400Years + 1;
|
||||
+ const auto d = seconds(shift * kSecsPer400Years);
|
||||
+ time_zone::absolute_lookup al = BreakTime(tp - d);
|
||||
+ al.cs = YearShift(al.cs, shift * 400);
|
||||
+ return al;
|
||||
+ }
|
||||
+ return Offset(unix_time, transitions_[timecnt - 1]);
|
||||
+ }
|
||||
+
|
||||
+ const Transition target = {unix_time, 0, civil_second(), civil_second()};
|
||||
+ const Transition *begin = &transitions_[0];
|
||||
+ const Transition *tr = std::upper_bound(begin, begin + timecnt, target,
|
||||
+ Transition::ByUnixTime());
|
||||
+ local_time_hint_.store(static_cast<std::size_t>(tr - begin),
|
||||
+ std::memory_order_relaxed);
|
||||
+ return Offset(unix_time, *--tr);
|
||||
+}
|
||||
+
|
||||
// BreakTime() translation for a particular transition.
|
||||
time_zone::absolute_lookup TimeZoneInfo::LocalTime(
|
||||
std::int_fast64_t unix_time, const Transition& tr) const {
|
||||
diff --git a/src/time_zone_info.h b/src/time_zone_info.h
|
||||
index 4657a2d..dea4431 100644
|
||||
--- a/src/time_zone_info.h
|
||||
+++ b/src/time_zone_info.h
|
||||
@@ -70,6 +70,8 @@ class TimeZoneInfo : public TimeZoneIf {
|
||||
// TimeZoneIf implementations.
|
||||
time_zone::absolute_lookup BreakTime(
|
||||
const time_point<seconds>& tp) const override;
|
||||
+ time_zone::absolute_lookup
|
||||
+ LookupOffset(const time_point<seconds> &tp) const override;
|
||||
time_zone::civil_lookup MakeTime(
|
||||
const civil_second& cs) const override;
|
||||
bool NextTransition(const time_point<seconds>& tp,
|
||||
@@ -103,8 +105,13 @@ class TimeZoneInfo : public TimeZoneIf {
|
||||
bool Load(const std::string& name, ZoneInfoSource* zip);
|
||||
|
||||
// Helpers for BreakTime() and MakeTime().
|
||||
+ time_zone::absolute_lookup Offset(std::int_fast64_t unix_time,
|
||||
+ const Transition &tr) const;
|
||||
+ time_zone::absolute_lookup Offset(std::int_fast64_t unix_time,
|
||||
+ const TransitionType &tt) const;
|
||||
+
|
||||
time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time,
|
||||
- const TransitionType& tt) const;
|
||||
+ const TransitionType &tt) const;
|
||||
time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time,
|
||||
const Transition& tr) const;
|
||||
time_zone::civil_lookup TimeLocal(const civil_second& cs,
|
||||
diff --git a/src/time_zone_lookup.cc b/src/time_zone_lookup.cc
|
||||
index 2a38a9b..a97ac2f 100644
|
||||
--- a/src/time_zone_lookup.cc
|
||||
+++ b/src/time_zone_lookup.cc
|
||||
@@ -73,6 +73,11 @@ time_zone::absolute_lookup time_zone::lookup(
|
||||
return effective_impl().BreakTime(tp);
|
||||
}
|
||||
|
||||
+time_zone::absolute_lookup
|
||||
+time_zone::lookup_offset(const time_point<seconds> &tp) const {
|
||||
+ return effective_impl().LookupOffset(tp);
|
||||
+}
|
||||
+
|
||||
time_zone::civil_lookup time_zone::lookup(const civil_second& cs) const {
|
||||
return effective_impl().MakeTime(cs);
|
||||
}
|
||||
|
|
@ -470,9 +470,15 @@ AZURE_NAME="azure-storage-files-shares_12.12.0.tar.gz"
|
|||
AZURE_SOURCE="azure-storage-files-shares_12.12.0"
|
||||
AZURE_MD5SUM="cb38786198aa103295d4d670604a9a60"
|
||||
|
||||
# libdivide
|
||||
LIBDIVIDE_DOWNLOAD="https://github.com/ridiculousfish/libdivide/archive/refs/tags/v5.2.0.tar.gz"
|
||||
LIBDIVIDE_NAME="libdivide-v5.2.0.tar.gz"
|
||||
LIBDIVIDE_SOURCE="libdivide-v5.2.0"
|
||||
LIBDIVIDE_MD5SUM="4ba77777192c295d6de2b86d88f3239a"
|
||||
|
||||
# all thirdparties which need to be downloaded is set in array TP_ARCHIVES
|
||||
TP_ARCHIVES="CLUCENE LIBEVENT OPENSSL THRIFT PROTOBUF GFLAGS GLOG GTEST RAPIDJSON SIMDJSON SNAPPY GPERFTOOLS ZLIB LZ4 BZIP CURL \
|
||||
RE2 BOOST LEVELDB BRPC ROCKSDB KRB5 SASL LIBRDKAFKA PULSAR FLATBUFFERS ARROW BROTLI ZSTD S2 BITSHUFFLE CROARINGBITMAP \
|
||||
JEMALLOC CCTZ FMT RYU BREAK_PAD HADOOP JDK RAGEL HYPERSCAN MARIADB JINDOSDK AWS_SDK_CPP VPACK OPENTELEMETRY \
|
||||
BENCHMARK FAST_FLOAT STARCACHE STREAMVBYTE JANSSON AVRO SERDES GCS_CONNECTOR LZO2 DATASKETCHES \
|
||||
ASYNC_PROFILER FIU LIBDEFLATE LLVM ABSL CARES GRPC SIMDUTF TENANN POCO ICU XSIMD LIBXML2 AZURE"
|
||||
ASYNC_PROFILER FIU LIBDEFLATE LLVM ABSL CARES GRPC SIMDUTF TENANN POCO ICU XSIMD LIBXML2 AZURE LIBDIVIDE"
|
||||
|
|
|
|||
Loading…
Reference in New Issue