15 #if defined(_WIN32) || defined(_WIN64) 16 #define _CRT_SECURE_NO_WARNINGS 1 31 namespace time_internal {
37 using OffsetAbbr = std::pair<int, const char*>;
44 #if defined(_WIN32) || defined(_WIN64) 46 OffsetAbbr get_offset_abbr(
const std::tm& tm) {
47 const bool is_dst = tm.tm_isdst > 0;
48 const int off = _timezone + (is_dst ? _dstbias : 0);
49 const char*
abbr = _tzname[is_dst];
54 OffsetAbbr get_offset_abbr(
const std::tm& tm) {
55 const bool is_dst = tm.tm_isdst > 0;
56 const int off = is_dst ? altzone : timezone;
57 const char*
abbr = tzname[is_dst];
60 #elif defined(__native_client__) || defined(__myriad2__) || \ 61 defined(__EMSCRIPTEN__) 63 OffsetAbbr get_offset_abbr(
const std::tm& tm) {
64 const bool is_dst = tm.tm_isdst > 0;
65 const int off = _timezone + (is_dst ? 60 * 60 : 0);
66 const char*
abbr = tzname[is_dst];
73 #if !defined(tm_gmtoff) && !defined(tm_zone) 75 OffsetAbbr get_offset_abbr(
const T& tm, decltype(&T::tm_gmtoff) =
nullptr,
76 decltype(&T::tm_zone) =
nullptr) {
77 return {tm.tm_gmtoff, tm.tm_zone};
79 #endif // !defined(tm_gmtoff) && !defined(tm_zone) 80 #if !defined(__tm_gmtoff) && !defined(__tm_zone) 82 OffsetAbbr get_offset_abbr(
const T& tm, decltype(&T::__tm_gmtoff) =
nullptr,
83 decltype(&T::__tm_zone) =
nullptr) {
84 return {tm.__tm_gmtoff, tm.__tm_zone};
86 #endif // !defined(__tm_gmtoff) && !defined(__tm_zone) 89 inline std::tm* gm_time(
const std::time_t *timep, std::tm *result) {
90 #if defined(_WIN32) || defined(_WIN64) 91 return gmtime_s(result, timep) ?
nullptr : result;
93 return gmtime_r(timep, result);
97 inline std::tm* local_time(
const std::time_t *timep, std::tm *result) {
98 #if defined(_WIN32) || defined(_WIN64) 99 return localtime_s(result, timep) ?
nullptr : result;
101 return localtime_r(timep, result);
108 bool make_time(
const civil_second& cs,
int is_dst, std::time_t* t,
int* off) {
110 tm.tm_year =
static_cast<int>(cs.year() -
year_t{1900});
111 tm.tm_mon = cs.month() - 1;
112 tm.tm_mday = cs.day();
113 tm.tm_hour = cs.hour();
114 tm.tm_min = cs.minute();
115 tm.tm_sec = cs.second();
116 tm.tm_isdst = is_dst;
117 *t = std::mktime(&tm);
118 if (*t == std::time_t{-1}) {
120 const std::tm* tmp = local_time(t, &tm2);
121 if (tmp ==
nullptr || tmp->tm_year != tm.tm_year ||
122 tmp->tm_mon != tm.tm_mon || tmp->tm_mday != tm.tm_mday ||
123 tmp->tm_hour != tm.tm_hour || tmp->tm_min != tm.tm_min ||
124 tmp->tm_sec != tm.tm_sec) {
129 *off = get_offset_abbr(tm).first;
135 std::time_t find_trans(std::time_t lo, std::time_t hi,
int offset) {
137 while (lo + 1 != hi) {
138 const std::time_t mid = lo + (hi - lo) / 2;
139 if (std::tm* tmp = local_time(&mid, &tm)) {
140 if (get_offset_abbr(*tmp).first == offset) {
149 if (std::tm* tmp = local_time(&lo, &tm)) {
150 if (get_offset_abbr(*tmp).first == offset)
break;
162 : local_(name ==
"localtime") {}
174 if (s < std::numeric_limits<std::time_t>::min()) {
178 if (s > std::numeric_limits<std::time_t>::max()) {
183 const std::time_t t =
static_cast<std::time_t
>(s);
185 std::tm* tmp =
local_ ? local_time(&t, &tm) : gm_time(&t, &tm);
188 if (tmp ==
nullptr) {
195 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
196 std::tie(al.
offset, al.
abbr) = get_offset_abbr(*tmp);
198 al.
is_dst = tmp->tm_isdst > 0;
219 if (cs.
year() < std::numeric_limits<int>::min() +
year_t{1900}) {
224 if (cs.
year() -
year_t{1900} > std::numeric_limits<int>::max()) {
235 int offset0, offset1;
236 if (make_time(cs, 0, &t0, &offset0) && make_time(cs, 1, &t1, &offset1)) {
247 const std::time_t tt = find_trans(t0, t1, offset1);
250 if (offset0 < offset1) {
281 return std::string();
285 return local_ ?
"localtime" :
"UTC";
time_point< seconds > FromUnixSeconds(std::int_fast64_t t)
TimeZoneLibC(const std::string &name)
static CONSTEXPR_F civil_time() max()
static CONSTEXPR_F civil_time() min()
time_zone::absolute_lookup BreakTime(const time_point< seconds > &tp) const override
CONSTEXPR_M year_t year() const noexcept
bool NextTransition(const time_point< seconds > &tp, time_zone::civil_transition *trans) const override
void swap(absl::InlinedVector< T, N, A > &a, absl::InlinedVector< T, N, A > &b) noexcept(noexcept(a.swap(b)))
std::chrono::time_point< std::chrono::system_clock, D > time_point
time_zone::civil_lookup MakeTime(const civil_second &cs) const override
std::string Description() const override
std::string Version() const override
std::int_fast64_t ToUnixSeconds(const time_point< seconds > &tp)
bool PrevTransition(const time_point< seconds > &tp, time_zone::civil_transition *trans) const override
detail::civil_second civil_second