feat(time): use tm::tm_gmtoff if present (#1040)
This greatly simplifies time computations.
This commit is contained in:
parent
eb72e4c181
commit
25a349f7ae
@ -108,10 +108,6 @@ struct GLOG_EXPORT LogMessageTime {
|
|||||||
const std::tm& tm() const noexcept { return tm_; }
|
const std::tm& tm() const noexcept { return tm_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init(const std::tm& t, std::time_t timestamp,
|
|
||||||
std::chrono::system_clock::time_point now);
|
|
||||||
void CalcGmtOffset(std::time_t t);
|
|
||||||
|
|
||||||
std::tm tm_{}; // Time of creation of LogMessage
|
std::tm tm_{}; // Time of creation of LogMessage
|
||||||
std::chrono::system_clock::time_point
|
std::chrono::system_clock::time_point
|
||||||
timestamp_; // Time of creation of LogMessage in seconds
|
timestamp_; // Time of creation of LogMessage in seconds
|
||||||
|
|||||||
@ -42,6 +42,7 @@
|
|||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -2679,39 +2680,82 @@ void DisableLogCleaner() { log_cleaner.Disable(); }
|
|||||||
|
|
||||||
LogMessageTime::LogMessageTime() = default;
|
LogMessageTime::LogMessageTime() = default;
|
||||||
|
|
||||||
LogMessageTime::LogMessageTime(std::chrono::system_clock::time_point now)
|
namespace {
|
||||||
: timestamp_{now} {
|
|
||||||
|
template <class... Args>
|
||||||
|
struct void_impl {
|
||||||
|
using type = void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class... Args>
|
||||||
|
using void_t = typename void_impl<Args...>::type;
|
||||||
|
|
||||||
|
template <class T, class E = void>
|
||||||
|
struct has_member_tm_gmtoff : std::false_type {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct has_member_tm_gmtoff<T, void_t<decltype(&T::tm_gmtoff)>>
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
|
template <class T = std::tm>
|
||||||
|
auto Breakdown(const std::chrono::system_clock::time_point& now)
|
||||||
|
-> std::enable_if_t<!has_member_tm_gmtoff<T>::value,
|
||||||
|
std::tuple<std::tm, std::time_t, std::chrono::hours>> {
|
||||||
std::time_t timestamp = std::chrono::system_clock::to_time_t(now);
|
std::time_t timestamp = std::chrono::system_clock::to_time_t(now);
|
||||||
if (FLAGS_log_utc_time) {
|
std::tm tm_local;
|
||||||
gmtime_r(×tamp, &tm_);
|
std::tm tm_utc;
|
||||||
} else {
|
int isdst = 0;
|
||||||
localtime_r(×tamp, &tm_);
|
|
||||||
}
|
|
||||||
usecs_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
|
||||||
now - std::chrono::system_clock::from_time_t(timestamp));
|
|
||||||
CalcGmtOffset(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LogMessageTime::CalcGmtOffset(std::time_t t) {
|
|
||||||
std::tm gmt_struct;
|
|
||||||
int isDst = 0;
|
|
||||||
if (FLAGS_log_utc_time) {
|
if (FLAGS_log_utc_time) {
|
||||||
localtime_r(&t, &gmt_struct);
|
gmtime_r(×tamp, &tm_local);
|
||||||
isDst = gmt_struct.tm_isdst;
|
localtime_r(×tamp, &tm_utc);
|
||||||
gmt_struct = tm_;
|
isdst = tm_utc.tm_isdst;
|
||||||
|
tm_utc = tm_local;
|
||||||
} else {
|
} else {
|
||||||
isDst = tm_.tm_isdst;
|
localtime_r(×tamp, &tm_local);
|
||||||
gmtime_r(&t, &gmt_struct);
|
isdst = tm_local.tm_isdst;
|
||||||
|
gmtime_r(×tamp, &tm_utc);
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t gmt_sec = mktime(&gmt_struct);
|
std::time_t gmt_sec = std::mktime(&tm_utc);
|
||||||
|
|
||||||
// If the Daylight Saving Time(isDst) is active subtract an hour from the
|
// If the Daylight Saving Time(isDst) is active subtract an hour from the
|
||||||
// current timestamp.
|
// current timestamp.
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
gmtoffset_ = std::chrono::duration_cast<std::chrono::seconds>(
|
const auto gmtoffset = std::chrono::duration_cast<std::chrono::hours>(
|
||||||
timestamp_ - std::chrono::system_clock::from_time_t(gmt_sec) +
|
now - std::chrono::system_clock::from_time_t(gmt_sec) +
|
||||||
(isDst ? 1h : 0h));
|
(isdst ? 1h : 0h));
|
||||||
|
|
||||||
|
return std::make_tuple(tm_local, timestamp, gmtoffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T = std::tm>
|
||||||
|
auto Breakdown(const std::chrono::system_clock::time_point& now)
|
||||||
|
-> std::enable_if_t<has_member_tm_gmtoff<T>::value,
|
||||||
|
std::tuple<std::tm, std::time_t, std::chrono::hours>> {
|
||||||
|
std::time_t timestamp = std::chrono::system_clock::to_time_t(now);
|
||||||
|
T tm;
|
||||||
|
|
||||||
|
if (FLAGS_log_utc_time) {
|
||||||
|
gmtime_r(×tamp, &tm);
|
||||||
|
} else {
|
||||||
|
localtime_r(×tamp, &tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto gmtoffset = std::chrono::duration_cast<std::chrono::hours>(
|
||||||
|
std::chrono::seconds{tm.tm_gmtoff});
|
||||||
|
|
||||||
|
return std::make_tuple(tm, timestamp, gmtoffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
LogMessageTime::LogMessageTime(std::chrono::system_clock::time_point now)
|
||||||
|
: timestamp_{now} {
|
||||||
|
std::time_t timestamp;
|
||||||
|
std::tie(tm_, timestamp, gmtoffset_) = Breakdown(now);
|
||||||
|
usecs_ = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||||
|
now - std::chrono::system_clock::from_time_t(timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace google
|
} // namespace google
|
||||||
|
|||||||
@ -1537,12 +1537,12 @@ TEST(LogMsgTime, gmtoff) {
|
|||||||
* */
|
* */
|
||||||
google::LogMessage log_obj(__FILE__, __LINE__);
|
google::LogMessage log_obj(__FILE__, __LINE__);
|
||||||
|
|
||||||
std::chrono::seconds nGmtOff = log_obj.time().gmtoffset();
|
std::chrono::seconds gmtoff = log_obj.time().gmtoffset();
|
||||||
// GMT offset ranges from UTC-12:00 to UTC+14:00
|
// GMT offset ranges from UTC-12:00 to UTC+14:00
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
const std::chrono::hours utc_min_offset = -12h;
|
constexpr std::chrono::hours utc_min_offset = -12h;
|
||||||
const std::chrono::hours utc_max_offset = 14h;
|
constexpr std::chrono::hours utc_max_offset = +14h;
|
||||||
EXPECT_TRUE((nGmtOff >= utc_min_offset) && (nGmtOff <= utc_max_offset));
|
EXPECT_TRUE((gmtoff >= utc_min_offset) && (gmtoff <= utc_max_offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(EmailLogging, ValidAddress) {
|
TEST(EmailLogging, ValidAddress) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user