diff --git a/tdutils/td/utils/port/Clocks.cpp b/tdutils/td/utils/port/Clocks.cpp index 169f77a8..abee5d68 100644 --- a/tdutils/td/utils/port/Clocks.cpp +++ b/tdutils/td/utils/port/Clocks.cpp @@ -7,6 +7,7 @@ #include "td/utils/port/Clocks.h" #include +#include namespace td { @@ -21,4 +22,40 @@ double Clocks::system() { return static_cast(std::chrono::duration_cast(duration).count()) * 1e-9; } +int Clocks::tz_offset() { + // not thread-safe on POSIX, so calculate the offset only once + static int offset = [] { + auto now = std::time(nullptr); + + auto time_ptr = std::localtime(&now); + if (time_ptr == nullptr) { + return 0; + } + auto local_time = *time_ptr; + + time_ptr = std::gmtime(&now); + if (time_ptr == nullptr) { + return 0; + } + auto utc_time = *time_ptr; + + int minute_offset = local_time.tm_min - utc_time.tm_min; + int hour_offset = local_time.tm_hour - utc_time.tm_hour; + int day_offset = local_time.tm_mday - utc_time.tm_mday; + if (day_offset >= 20) { + day_offset = -1; + } else if (day_offset <= -20) { + day_offset = 1; + } + int sec_offset = day_offset * 86400 + hour_offset * 3600 + minute_offset * 60; + if (sec_offset >= 15 * 3600 || sec_offset <= -15 * 3600) { + return 0; + } + return sec_offset / 900 * 900; // round to 900 just in case + }(); + return offset; +} + +static int init_tz_offset = Clocks::tz_offset(); + } // namespace td diff --git a/tdutils/td/utils/port/Clocks.h b/tdutils/td/utils/port/Clocks.h index f3effb83..b11322cf 100644 --- a/tdutils/td/utils/port/Clocks.h +++ b/tdutils/td/utils/port/Clocks.h @@ -12,6 +12,8 @@ struct Clocks { static double monotonic(); static double system(); + + static int tz_offset(); }; } // namespace td