summaryrefslogtreecommitdiff
path: root/absl/time/internal/cctz/src
diff options
context:
space:
mode:
Diffstat (limited to 'absl/time/internal/cctz/src')
-rw-r--r--absl/time/internal/cctz/src/cctz_benchmark.cc53
-rw-r--r--absl/time/internal/cctz/src/civil_time_detail.cc6
-rw-r--r--absl/time/internal/cctz/src/civil_time_test.cc22
-rw-r--r--absl/time/internal/cctz/src/time_zone_fixed.cc22
-rw-r--r--absl/time/internal/cctz/src/time_zone_fixed.h6
-rw-r--r--absl/time/internal/cctz/src/time_zone_format.cc104
-rw-r--r--absl/time/internal/cctz/src/time_zone_format_test.cc367
-rw-r--r--absl/time/internal/cctz/src/time_zone_if.cc6
-rw-r--r--absl/time/internal/cctz/src/time_zone_if.h6
-rw-r--r--absl/time/internal/cctz/src/time_zone_impl.cc6
-rw-r--r--absl/time/internal/cctz/src/time_zone_impl.h6
-rw-r--r--absl/time/internal/cctz/src/time_zone_info.cc29
-rw-r--r--absl/time/internal/cctz/src/time_zone_info.h8
-rw-r--r--absl/time/internal/cctz/src/time_zone_libc.cc109
-rw-r--r--absl/time/internal/cctz/src/time_zone_libc.h6
-rw-r--r--absl/time/internal/cctz/src/time_zone_lookup.cc41
-rw-r--r--absl/time/internal/cctz/src/time_zone_lookup_test.cc33
-rw-r--r--absl/time/internal/cctz/src/time_zone_posix.cc16
-rw-r--r--absl/time/internal/cctz/src/time_zone_posix.h6
-rw-r--r--absl/time/internal/cctz/src/tzfile.h20
-rw-r--r--absl/time/internal/cctz/src/zone_info_source.cc34
21 files changed, 572 insertions, 334 deletions
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc
index 4498d7d0..a40f504e 100644
--- a/absl/time/internal/cctz/src/cctz_benchmark.cc
+++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -47,6 +47,56 @@ void BM_Step_Days(benchmark::State& state) {
}
BENCHMARK(BM_Step_Days);
+void BM_GetWeekday(benchmark::State& state) {
+ const cctz::civil_day c(2014, 8, 22);
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(cctz::get_weekday(c));
+ }
+}
+BENCHMARK(BM_GetWeekday);
+
+void BM_NextWeekday(benchmark::State& state) {
+ const cctz::civil_day kStart(2014, 8, 22);
+ const cctz::civil_day kDays[7] = {
+ kStart + 0, kStart + 1, kStart + 2, kStart + 3,
+ kStart + 4, kStart + 5, kStart + 6,
+ };
+ const cctz::weekday kWeekdays[7] = {
+ cctz::weekday::monday, cctz::weekday::tuesday, cctz::weekday::wednesday,
+ cctz::weekday::thursday, cctz::weekday::friday, cctz::weekday::saturday,
+ cctz::weekday::sunday,
+ };
+ while (state.KeepRunningBatch(7 * 7)) {
+ for (const auto from : kDays) {
+ for (const auto to : kWeekdays) {
+ benchmark::DoNotOptimize(cctz::next_weekday(from, to));
+ }
+ }
+ }
+}
+BENCHMARK(BM_NextWeekday);
+
+void BM_PrevWeekday(benchmark::State& state) {
+ const cctz::civil_day kStart(2014, 8, 22);
+ const cctz::civil_day kDays[7] = {
+ kStart + 0, kStart + 1, kStart + 2, kStart + 3,
+ kStart + 4, kStart + 5, kStart + 6,
+ };
+ const cctz::weekday kWeekdays[7] = {
+ cctz::weekday::monday, cctz::weekday::tuesday, cctz::weekday::wednesday,
+ cctz::weekday::thursday, cctz::weekday::friday, cctz::weekday::saturday,
+ cctz::weekday::sunday,
+ };
+ while (state.KeepRunningBatch(7 * 7)) {
+ for (const auto from : kDays) {
+ for (const auto to : kWeekdays) {
+ benchmark::DoNotOptimize(cctz::prev_weekday(from, to));
+ }
+ }
+ }
+}
+BENCHMARK(BM_PrevWeekday);
+
const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
@@ -357,6 +407,7 @@ const char* const kTimeZoneNames[] = {
"Asia/Pontianak",
"Asia/Pyongyang",
"Asia/Qatar",
+ "Asia/Qostanay",
"Asia/Qyzylorda",
"Asia/Rangoon",
"Asia/Riyadh",
diff --git a/absl/time/internal/cctz/src/civil_time_detail.cc b/absl/time/internal/cctz/src/civil_time_detail.cc
index e888066d..4df15d55 100644
--- a/absl/time/internal/cctz/src/civil_time_detail.cc
+++ b/absl/time/internal/cctz/src/civil_time_detail.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -19,7 +19,7 @@
#include <sstream>
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
namespace detail {
@@ -88,5 +88,5 @@ std::ostream& operator<<(std::ostream& os, weekday wd) {
} // namespace detail
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc
index 2417a2a9..7d9a1834 100644
--- a/absl/time/internal/cctz/src/civil_time_test.cc
+++ b/absl/time/internal/cctz/src/civil_time_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,7 +23,7 @@
#include "gtest/gtest.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -38,7 +38,7 @@ std::string Format(const T& t) {
} // namespace
-#if __cpp_constexpr >= 201304 || _MSC_VER >= 1910
+#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)
// Construction constexpr tests
TEST(CivilTime, Normal) {
@@ -320,7 +320,7 @@ TEST(CivilTime, YearDay) {
constexpr int yd = get_yearday(cd);
static_assert(yd == 28, "YearDay");
}
-#endif // __cpp_constexpr >= 201304 || _MSC_VER >= 1910
+#endif // __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)
// The remaining tests do not use constexpr.
@@ -822,6 +822,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(4, ss.hour());
EXPECT_EQ(5, ss.minute());
EXPECT_EQ(6, ss.second());
+ EXPECT_EQ(weekday::tuesday, get_weekday(ss));
+ EXPECT_EQ(34, get_yearday(ss));
civil_minute mm(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, mm.year());
@@ -830,6 +832,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(4, mm.hour());
EXPECT_EQ(5, mm.minute());
EXPECT_EQ(0, mm.second());
+ EXPECT_EQ(weekday::tuesday, get_weekday(mm));
+ EXPECT_EQ(34, get_yearday(mm));
civil_hour hh(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, hh.year());
@@ -838,6 +842,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(4, hh.hour());
EXPECT_EQ(0, hh.minute());
EXPECT_EQ(0, hh.second());
+ EXPECT_EQ(weekday::tuesday, get_weekday(hh));
+ EXPECT_EQ(34, get_yearday(hh));
civil_day d(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, d.year());
@@ -856,6 +862,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(0, m.hour());
EXPECT_EQ(0, m.minute());
EXPECT_EQ(0, m.second());
+ EXPECT_EQ(weekday::sunday, get_weekday(m));
+ EXPECT_EQ(32, get_yearday(m));
civil_year y(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, y.year());
@@ -864,6 +872,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(0, y.hour());
EXPECT_EQ(0, y.minute());
EXPECT_EQ(0, y.second());
+ EXPECT_EQ(weekday::thursday, get_weekday(y));
+ EXPECT_EQ(1, get_yearday(y));
}
TEST(CivilTime, OutputStream) {
@@ -1036,7 +1046,7 @@ TEST(CivilTime, LeapYears) {
TEST(CivilTime, FirstThursdayInMonth) {
const civil_day nov1(2014, 11, 1);
- const civil_day thursday = prev_weekday(nov1, weekday::thursday) + 7;
+ const civil_day thursday = next_weekday(nov1 - 1, weekday::thursday);
EXPECT_EQ("2014-11-06", Format(thursday));
// Bonus: Date of Thanksgiving in the United States
@@ -1047,5 +1057,5 @@ TEST(CivilTime, FirstThursdayInMonth) {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc
index 070abd26..aa5af020 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.cc
+++ b/absl/time/internal/cctz/src/time_zone_fixed.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,14 +21,14 @@
#include <string>
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
namespace {
// The prefix used for the internal names of fixed-offset zones.
-const char kFixedOffsetPrefix[] = "Fixed/UTC";
+const char kFixedZonePrefix[] = "Fixed/UTC";
const char kDigits[] = "0123456789";
@@ -56,11 +56,11 @@ bool FixedOffsetFromName(const std::string& name, seconds* offset) {
return true;
}
- const std::size_t prefix_len = sizeof(kFixedOffsetPrefix) - 1;
- const char* const ep = kFixedOffsetPrefix + prefix_len;
+ const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
+ const char* const ep = kFixedZonePrefix + prefix_len;
if (name.size() != prefix_len + 9) // <prefix>+99:99:99
return false;
- if (!std::equal(kFixedOffsetPrefix, ep, name.begin()))
+ if (!std::equal(kFixedZonePrefix, ep, name.begin()))
return false;
const char* np = name.data() + prefix_len;
if (np[0] != '+' && np[0] != '-')
@@ -103,9 +103,9 @@ std::string FixedOffsetToName(const seconds& offset) {
}
int hours = minutes / 60;
minutes %= 60;
- char buf[sizeof(kFixedOffsetPrefix) - 1 + sizeof("-24:00:00")];
- std::strcpy(buf, kFixedOffsetPrefix);
- char* ep = buf + sizeof(kFixedOffsetPrefix) - 1;
+ const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
+ char buf[prefix_len + sizeof("-24:00:00")];
+ char* ep = std::copy(kFixedZonePrefix, kFixedZonePrefix + prefix_len, buf);
*ep++ = sign;
ep = Format02d(ep, hours);
*ep++ = ':';
@@ -119,7 +119,7 @@ std::string FixedOffsetToName(const seconds& offset) {
std::string FixedOffsetToAbbr(const seconds& offset) {
std::string abbr = FixedOffsetToName(offset);
- const std::size_t prefix_len = sizeof(kFixedOffsetPrefix) - 1;
+ const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
if (abbr.size() == prefix_len + 9) { // <prefix>+99:99:99
abbr.erase(0, prefix_len); // +99:99:99
abbr.erase(6, 1); // +99:9999
@@ -136,5 +136,5 @@ std::string FixedOffsetToAbbr(const seconds& offset) {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.h b/absl/time/internal/cctz/src/time_zone_fixed.h
index dbb2958e..15ea3bdf 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.h
+++ b/absl/time/internal/cctz/src/time_zone_fixed.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -20,7 +20,7 @@
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -45,7 +45,7 @@ std::string FixedOffsetToAbbr(const seconds& offset);
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_
diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc
index 02ecb2cf..ee2ffac0 100644
--- a/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/absl/time/internal/cctz/src/time_zone_format.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,13 +13,23 @@
// limitations under the License.
#if !defined(HAS_STRPTIME)
-# if !defined(_MSC_VER)
+# if !defined(_MSC_VER) && !defined(__MINGW32__)
# define HAS_STRPTIME 1 // assume everyone has strptime() except windows
# endif
#endif
+#if defined(HAS_STRPTIME) && HAS_STRPTIME
+# if !defined(_XOPEN_SOURCE)
+# define _XOPEN_SOURCE // Definedness suffices for strptime.
+# endif
+#endif
+
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
+// Include time.h directly since, by C++ standards, ctime doesn't have to
+// declare strptime.
+#include <time.h>
+
#include <cctype>
#include <chrono>
#include <cstddef>
@@ -38,7 +48,7 @@
#include "time_zone_if.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
namespace detail {
@@ -73,7 +83,7 @@ std::tm ToTM(const time_zone::absolute_lookup& al) {
tm.tm_year = static_cast<int>(al.cs.year() - 1900);
}
- switch (get_weekday(civil_day(al.cs))) {
+ switch (get_weekday(al.cs)) {
case weekday::sunday:
tm.tm_wday = 0;
break;
@@ -96,7 +106,7 @@ std::tm ToTM(const time_zone::absolute_lookup& al) {
tm.tm_wday = 6;
break;
}
- tm.tm_yday = get_yearday(civil_day(al.cs)) - 1;
+ tm.tm_yday = get_yearday(al.cs) - 1;
tm.tm_isdst = al.is_dst ? 1 : 0;
return tm;
}
@@ -150,15 +160,25 @@ char* FormatOffset(char* ep, int offset, const char* mode) {
offset = -offset; // bounded by 24h so no overflow
sign = '-';
}
- char sep = mode[0];
- if (sep != '\0' && mode[1] == '*') {
- ep = Format02d(ep, offset % 60);
+ const int seconds = offset % 60;
+ const int minutes = (offset /= 60) % 60;
+ const int hours = offset /= 60;
+ const char sep = mode[0];
+ const bool ext = (sep != '\0' && mode[1] == '*');
+ const bool ccc = (ext && mode[2] == ':');
+ if (ext && (!ccc || seconds != 0)) {
+ ep = Format02d(ep, seconds);
*--ep = sep;
+ } else {
+ // If we're not rendering seconds, sub-minute negative offsets
+ // should get a positive sign (e.g., offset=-10s => "+00:00").
+ if (hours == 0 && minutes == 0) sign = '+';
+ }
+ if (!ccc || minutes != 0 || seconds != 0) {
+ ep = Format02d(ep, minutes);
+ if (sep != '\0') *--ep = sep;
}
- int minutes = offset / 60;
- ep = Format02d(ep, minutes % 60);
- if (sep != '\0') *--ep = sep;
- ep = Format02d(ep, minutes / 60);
+ ep = Format02d(ep, hours);
*--ep = sign;
return ep;
}
@@ -385,6 +405,44 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
continue;
}
+ // More complex specifiers that we handle ourselves.
+ if (*cur == ':' && cur + 1 != end) {
+ if (*(cur + 1) == 'z') {
+ // Formats %:z.
+ if (cur - 1 != pending) {
+ FormatTM(&result, std::string(pending, cur - 1), tm);
+ }
+ bp = FormatOffset(ep, al.offset, ":");
+ result.append(bp, static_cast<std::size_t>(ep - bp));
+ pending = cur += 2;
+ continue;
+ }
+ if (*(cur + 1) == ':' && cur + 2 != end) {
+ if (*(cur + 2) == 'z') {
+ // Formats %::z.
+ if (cur - 1 != pending) {
+ FormatTM(&result, std::string(pending, cur - 1), tm);
+ }
+ bp = FormatOffset(ep, al.offset, ":*");
+ result.append(bp, static_cast<std::size_t>(ep - bp));
+ pending = cur += 3;
+ continue;
+ }
+ if (*(cur + 2) == ':' && cur + 3 != end) {
+ if (*(cur + 3) == 'z') {
+ // Formats %:::z.
+ if (cur - 1 != pending) {
+ FormatTM(&result, std::string(pending, cur - 1), tm);
+ }
+ bp = FormatOffset(ep, al.offset, ":*:");
+ result.append(bp, static_cast<std::size_t>(ep - bp));
+ pending = cur += 4;
+ continue;
+ }
+ }
+ }
+ }
+
// Loop if there is no E modifier.
if (*cur != 'E' || ++cur == end) continue;
@@ -669,17 +727,27 @@ bool parse(const std::string& format, const std::string& input,
&percent_s);
if (data != nullptr) saw_percent_s = true;
continue;
+ case ':':
+ if (fmt[0] == 'z' ||
+ (fmt[0] == ':' &&
+ (fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) {
+ data = ParseOffset(data, ":", &offset);
+ if (data != nullptr) saw_offset = true;
+ fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3;
+ continue;
+ }
+ break;
case '%':
data = (*data == '%' ? data + 1 : nullptr);
continue;
case 'E':
- if (*fmt == 'z' || (*fmt == '*' && *(fmt + 1) == 'z')) {
+ if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) {
data = ParseOffset(data, ":", &offset);
if (data != nullptr) saw_offset = true;
- fmt += (*fmt == 'z') ? 1 : 2;
+ fmt += (fmt[0] == 'z') ? 1 : 2;
continue;
}
- if (*fmt == '*' && *(fmt + 1) == 'S') {
+ if (fmt[0] == '*' && fmt[1] == 'S') {
data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
if (data != nullptr && *data == '.') {
data = ParseSubSeconds(data + 1, &subseconds);
@@ -687,14 +755,14 @@ bool parse(const std::string& format, const std::string& input,
fmt += 2;
continue;
}
- if (*fmt == '*' && *(fmt + 1) == 'f') {
+ if (fmt[0] == '*' && fmt[1] == 'f') {
if (data != nullptr && std::isdigit(*data)) {
data = ParseSubSeconds(data, &subseconds);
}
fmt += 2;
continue;
}
- if (*fmt == '4' && *(fmt + 1) == 'Y') {
+ if (fmt[0] == '4' && fmt[1] == 'Y') {
const char* bp = data;
data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year);
if (data != nullptr) {
@@ -849,5 +917,5 @@ bool parse(const std::string& format, const std::string& input,
} // namespace detail
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc
index 260c56ad..49737445 100644
--- a/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,7 +26,7 @@
namespace chrono = std::chrono;
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -65,17 +65,6 @@ void TestFormatSpecifier(time_point<D> tp, time_zone tz, const std::string& fmt,
EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz));
}
-// These tests sometimes run on platforms that have zoneinfo data so old
-// that the transition we are attempting to check does not exist, most
-// notably Android emulators. Fortunately, AndroidZoneInfoSource supports
-// time_zone::version() so, in cases where we've learned that it matters,
-// we can make the check conditionally.
-int VersionCmp(time_zone tz, const std::string& target) {
- std::string version = tz.version();
- if (version.empty() && !target.empty()) return 1; // unknown > known
- return version.compare(target);
-}
-
} // namespace
//
@@ -175,7 +164,9 @@ TEST(Format, PosixConversions) {
TestFormatSpecifier(tp, tz, "%M", "00");
TestFormatSpecifier(tp, tz, "%S", "00");
TestFormatSpecifier(tp, tz, "%U", "00");
+#if !defined(__EMSCRIPTEN__)
TestFormatSpecifier(tp, tz, "%w", "4"); // 4=Thursday
+#endif
TestFormatSpecifier(tp, tz, "%W", "00");
TestFormatSpecifier(tp, tz, "%y", "70");
TestFormatSpecifier(tp, tz, "%Y", "1970");
@@ -437,51 +428,165 @@ TEST(Format, CompareExtendSecondsVsSubseconds) {
}
TEST(Format, ExtendedOffset) {
- auto tp = chrono::system_clock::from_time_t(0);
+ const auto tp = chrono::system_clock::from_time_t(0);
- time_zone tz = utc_time_zone();
+ auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+ TestFormatSpecifier(tp, tz, "%z", "+0000");
+ TestFormatSpecifier(tp, tz, "%:z", "+00:00");
TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
- EXPECT_TRUE(load_time_zone("America/New_York", &tz));
- TestFormatSpecifier(tp, tz, "%Ez", "-05:00");
-
- EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
- TestFormatSpecifier(tp, tz, "%Ez", "-08:00");
+ tz = fixed_time_zone(chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "+0000");
+ TestFormatSpecifier(tp, tz, "%:z", "+00:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
- EXPECT_TRUE(load_time_zone("Australia/Sydney", &tz));
- TestFormatSpecifier(tp, tz, "%Ez", "+10:00");
+ tz = fixed_time_zone(-chrono::seconds(56)); // NOTE: +00:00
+ TestFormatSpecifier(tp, tz, "%z", "+0000");
+ TestFormatSpecifier(tp, tz, "%:z", "+00:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
- EXPECT_TRUE(load_time_zone("Africa/Monrovia", &tz));
- // The true offset is -00:44:30 but %z only gives (truncated) minutes.
- TestFormatSpecifier(tp, tz, "%z", "-0044");
- TestFormatSpecifier(tp, tz, "%Ez", "-00:44");
+ tz = fixed_time_zone(chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%z", "+0034");
+ TestFormatSpecifier(tp, tz, "%:z", "+00:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
+
+ tz = fixed_time_zone(-chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%z", "-0034");
+ TestFormatSpecifier(tp, tz, "%:z", "-00:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
+
+ tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "+0034");
+ TestFormatSpecifier(tp, tz, "%:z", "+00:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
+
+ tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "-0034");
+ TestFormatSpecifier(tp, tz, "%:z", "-00:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
+
+ tz = fixed_time_zone(chrono::hours(12));
+ TestFormatSpecifier(tp, tz, "%z", "+1200");
+ TestFormatSpecifier(tp, tz, "%:z", "+12:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
+
+ tz = fixed_time_zone(-chrono::hours(12));
+ TestFormatSpecifier(tp, tz, "%z", "-1200");
+ TestFormatSpecifier(tp, tz, "%:z", "-12:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "+1200");
+ TestFormatSpecifier(tp, tz, "%:z", "+12:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "-1200");
+ TestFormatSpecifier(tp, tz, "%:z", "-12:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%z", "+1234");
+ TestFormatSpecifier(tp, tz, "%:z", "+12:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%z", "-1234");
+ TestFormatSpecifier(tp, tz, "%:z", "-12:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
+ chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "+1234");
+ TestFormatSpecifier(tp, tz, "%:z", "+12:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
+ chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "-1234");
+ TestFormatSpecifier(tp, tz, "%:z", "-12:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
}
TEST(Format, ExtendedSecondOffset) {
- const time_zone utc = utc_time_zone();
- time_point<chrono::seconds> tp;
- time_zone tz;
-
- EXPECT_TRUE(load_time_zone("America/New_York", &tz));
- tp = convert(civil_second(1883, 11, 18, 16, 59, 59), utc);
- if (tz.lookup(tp).offset == -5 * 60 * 60) {
- // It looks like the tzdata is only 32 bit (probably macOS),
- // which bottoms out at 1901-12-13T20:45:52+00:00.
- } else {
- TestFormatSpecifier(tp, tz, "%E*z", "-04:56:02");
- TestFormatSpecifier(tp, tz, "%Ez", "-04:56");
- }
- tp += chrono::seconds(1);
- TestFormatSpecifier(tp, tz, "%E*z", "-05:00:00");
-
- EXPECT_TRUE(load_time_zone("Europe/Moscow", &tz));
- tp = convert(civil_second(1919, 6, 30, 23, 59, 59), utc);
- if (VersionCmp(tz, "2016g") >= 0) {
- TestFormatSpecifier(tp, tz, "%E*z", "+04:31:19");
- TestFormatSpecifier(tp, tz, "%Ez", "+04:31");
- }
- tp += chrono::seconds(1);
- TestFormatSpecifier(tp, tz, "%E*z", "+04:00:00");
+ const auto tp = chrono::system_clock::from_time_t(0);
+
+ auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+ TestFormatSpecifier(tp, tz, "%E*z", "+00:00:00");
+ TestFormatSpecifier(tp, tz, "%::z", "+00:00:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "+00");
+
+ tz = fixed_time_zone(chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "+00:00:56");
+ TestFormatSpecifier(tp, tz, "%::z", "+00:00:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "+00:00:56");
+
+ tz = fixed_time_zone(-chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "-00:00:56");
+ TestFormatSpecifier(tp, tz, "%::z", "-00:00:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "-00:00:56");
+
+ tz = fixed_time_zone(chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%E*z", "+00:34:00");
+ TestFormatSpecifier(tp, tz, "%::z", "+00:34:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "+00:34");
+
+ tz = fixed_time_zone(-chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%E*z", "-00:34:00");
+ TestFormatSpecifier(tp, tz, "%::z", "-00:34:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "-00:34");
+
+ tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "+00:34:56");
+ TestFormatSpecifier(tp, tz, "%::z", "+00:34:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "+00:34:56");
+
+ tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "-00:34:56");
+ TestFormatSpecifier(tp, tz, "%::z", "-00:34:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "-00:34:56");
+
+ tz = fixed_time_zone(chrono::hours(12));
+ TestFormatSpecifier(tp, tz, "%E*z", "+12:00:00");
+ TestFormatSpecifier(tp, tz, "%::z", "+12:00:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "+12");
+
+ tz = fixed_time_zone(-chrono::hours(12));
+ TestFormatSpecifier(tp, tz, "%E*z", "-12:00:00");
+ TestFormatSpecifier(tp, tz, "%::z", "-12:00:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "-12");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "+12:00:56");
+ TestFormatSpecifier(tp, tz, "%::z", "+12:00:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "+12:00:56");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "-12:00:56");
+ TestFormatSpecifier(tp, tz, "%::z", "-12:00:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "-12:00:56");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%E*z", "+12:34:00");
+ TestFormatSpecifier(tp, tz, "%::z", "+12:34:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "+12:34");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%E*z", "-12:34:00");
+ TestFormatSpecifier(tp, tz, "%::z", "-12:34:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "-12:34");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
+ chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "+12:34:56");
+ TestFormatSpecifier(tp, tz, "%::z", "+12:34:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "+12:34:56");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
+ chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "-12:34:56");
+ TestFormatSpecifier(tp, tz, "%::z", "-12:34:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "-12:34:56");
}
TEST(Format, ExtendedYears) {
@@ -1161,25 +1266,6 @@ TEST(Parse, ExtendedOffset) {
const time_zone utc = utc_time_zone();
time_point<absl::time_internal::cctz::seconds> tp;
- // %z against +-HHMM.
- EXPECT_TRUE(parse("%z", "+0000", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%z", "-1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
- EXPECT_TRUE(parse("%z", "+1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
- EXPECT_FALSE(parse("%z", "-123", utc, &tp));
-
- // %z against +-HH.
- EXPECT_TRUE(parse("%z", "+00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%z", "-12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%z", "+12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
- EXPECT_FALSE(parse("%z", "-1", utc, &tp));
-
- // %Ez against +-HH:MM.
EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp));
EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp));
@@ -1188,91 +1274,70 @@ TEST(Parse, ExtendedOffset) {
EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp));
- // %Ez against +-HHMM.
- EXPECT_TRUE(parse("%Ez", "+0000", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "-1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "+1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
- EXPECT_FALSE(parse("%Ez", "-123", utc, &tp));
-
- // %Ez against +-HH.
- EXPECT_TRUE(parse("%Ez", "+00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "-12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "+12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
- EXPECT_FALSE(parse("%Ez", "-1", utc, &tp));
+ for (auto fmt : {"%Ez", "%z"}) {
+ EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
+
+ EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
+ }
}
TEST(Parse, ExtendedSecondOffset) {
const time_zone utc = utc_time_zone();
time_point<absl::time_internal::cctz::seconds> tp;
- // %Ez against +-HH:MM:SS.
- EXPECT_TRUE(parse("%Ez", "+00:00:00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "-12:34:56", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
- EXPECT_TRUE(parse("%Ez", "+12:34:56", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
- EXPECT_FALSE(parse("%Ez", "-12:34:5", utc, &tp));
-
- // %Ez against +-HHMMSS.
- EXPECT_TRUE(parse("%Ez", "+000000", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "-123456", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
- EXPECT_TRUE(parse("%Ez", "+123456", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
- EXPECT_FALSE(parse("%Ez", "-12345", utc, &tp));
-
- // %E*z against +-HH:MM:SS.
- EXPECT_TRUE(parse("%E*z", "+00:00:00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "-12:34:56", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
- EXPECT_TRUE(parse("%E*z", "+12:34:56", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
- EXPECT_FALSE(parse("%E*z", "-12:34:5", utc, &tp));
-
- // %E*z against +-HHMMSS.
- EXPECT_TRUE(parse("%E*z", "+000000", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "-123456", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
- EXPECT_TRUE(parse("%E*z", "+123456", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
- EXPECT_FALSE(parse("%E*z", "-12345", utc, &tp));
-
- // %E*z against +-HH:MM.
- EXPECT_TRUE(parse("%E*z", "+00:00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "-12:34", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "+12:34", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
- EXPECT_FALSE(parse("%E*z", "-12:3", utc, &tp));
-
- // %E*z against +-HHMM.
- EXPECT_TRUE(parse("%E*z", "+0000", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "-1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "+1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
- EXPECT_FALSE(parse("%E*z", "-123", utc, &tp));
-
- // %E*z against +-HH.
- EXPECT_TRUE(parse("%E*z", "+00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "-12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "+12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
- EXPECT_FALSE(parse("%E*z", "-1", utc, &tp));
+ for (auto fmt : {"%Ez", "%E*z", "%:z", "%::z", "%:::z"}) {
+ EXPECT_TRUE(parse(fmt, "+00:00:00", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-12:34:56", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+12:34:56", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-12:34:5", utc, &tp));
+
+ EXPECT_TRUE(parse(fmt, "+000000", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-123456", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+123456", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-12345", utc, &tp));
+
+ EXPECT_TRUE(parse(fmt, "+00:00", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-12:34", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+12:34", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-12:3", utc, &tp));
+
+ EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
+
+ EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
+ }
}
TEST(Parse, ExtendedYears) {
@@ -1391,6 +1456,10 @@ TEST(FormatParse, RoundTrip) {
#if defined(_WIN32) || defined(_WIN64)
// Initial investigations indicate the %c does not roundtrip on Windows.
// TODO: Figure out what is going on here (perhaps a locale problem).
+#elif defined(__EMSCRIPTEN__)
+ // strftime() and strptime() use different defintions for "%c" under
+ // emscripten (see https://github.com/kripken/emscripten/pull/7491),
+ // causing its round-trip test to fail.
#else
// Even though we don't know what %c will produce, it should roundtrip,
// but only in the 0-offset timezone.
@@ -1424,5 +1493,5 @@ TEST(FormatParse, RoundTripDistantPast) {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_if.cc b/absl/time/internal/cctz/src/time_zone_if.cc
index f7c36b2b..75d23da5 100644
--- a/absl/time/internal/cctz/src/time_zone_if.cc
+++ b/absl/time/internal/cctz/src/time_zone_if.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -17,7 +17,7 @@
#include "time_zone_libc.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -39,5 +39,5 @@ TimeZoneIf::~TimeZoneIf() {}
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_if.h b/absl/time/internal/cctz/src/time_zone_if.h
index 9886f2c5..0081d990 100644
--- a/absl/time/internal/cctz/src/time_zone_if.h
+++ b/absl/time/internal/cctz/src/time_zone_if.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,7 +24,7 @@
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -68,7 +68,7 @@ inline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_
diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc
index a4e42916..60911f0b 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.cc
+++ b/absl/time/internal/cctz/src/time_zone_impl.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -22,7 +22,7 @@
#include "time_zone_fixed.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -106,5 +106,5 @@ const time_zone::Impl* time_zone::Impl::UTCImpl() {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_impl.h b/absl/time/internal/cctz/src/time_zone_impl.h
index 7da2e99d..33d3f6bd 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.h
+++ b/absl/time/internal/cctz/src/time_zone_impl.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,7 +24,7 @@
#include "time_zone_info.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -86,7 +86,7 @@ class time_zone::Impl {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_
diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc
index e19d1d2d..b45d82fa 100644
--- a/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/absl/time/internal/cctz/src/time_zone_info.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -25,7 +25,7 @@
// a grain of salt.
//
// For more information see tzfile(5), http://www.iana.org/time-zones, or
-// http://en.wikipedia.org/wiki/Zoneinfo.
+// https://en.wikipedia.org/wiki/Zoneinfo.
//
// Note that we assume the proleptic Gregorian calendar and 60-second
// minutes throughout.
@@ -50,7 +50,7 @@
#include "time_zone_posix.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -240,8 +240,8 @@ bool TimeZoneInfo::Header::Build(const tzhead& tzh) {
leapcnt = static_cast<std::size_t>(v);
if ((v = Decode32(tzh.tzh_ttisstdcnt)) < 0) return false;
ttisstdcnt = static_cast<std::size_t>(v);
- if ((v = Decode32(tzh.tzh_ttisgmtcnt)) < 0) return false;
- ttisgmtcnt = static_cast<std::size_t>(v);
+ if ((v = Decode32(tzh.tzh_ttisutcnt)) < 0) return false;
+ ttisutcnt = static_cast<std::size_t>(v);
return true;
}
@@ -254,7 +254,7 @@ std::size_t TimeZoneInfo::Header::DataLength(std::size_t time_len) const {
len += 1 * charcnt; // abbreviations
len += (time_len + 4) * leapcnt; // leap-time + TAI-UTC
len += 1 * ttisstdcnt; // UTC/local indicators
- len += 1 * ttisgmtcnt; // standard/wall indicators
+ len += 1 * ttisutcnt; // standard/wall indicators
return len;
}
@@ -428,7 +428,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
}
if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt)
return false;
- if (hdr.ttisgmtcnt != 0 && hdr.ttisgmtcnt != hdr.typecnt)
+ if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt)
return false;
// Read the data into a local buffer.
@@ -499,16 +499,16 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
// that isn't the case here (see "zic -p").
bp += (8 + 4) * hdr.leapcnt; // leap-time + TAI-UTC
bp += 1 * hdr.ttisstdcnt; // UTC/local indicators
- bp += 1 * hdr.ttisgmtcnt; // standard/wall indicators
+ bp += 1 * hdr.ttisutcnt; // standard/wall indicators
assert(bp == tbuf.data() + tbuf.size());
future_spec_.clear();
if (tzh.tzh_version[0] != '\0') {
// Snarf up the NL-enclosed future POSIX spec. Note
// that version '3' files utilize an extended format.
- auto get_char = [](ZoneInfoSource* zip) -> int {
+ auto get_char = [](ZoneInfoSource* azip) -> int {
unsigned char ch; // all non-EOF results are positive
- return (zip->Read(&ch, 1) == 1) ? ch : EOF;
+ return (azip->Read(&ch, 1) == 1) ? ch : EOF;
};
if (get_char(zip) != '\n')
return false;
@@ -683,7 +683,6 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
// Use of the "file:" prefix is intended for testing purposes only.
if (name.compare(0, 5, "file:") == 0) return Open(name.substr(5));
-#if defined(__ANDROID__)
// See Android's libc/tzcode/bionic.cpp for additional information.
for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata",
"/system/usr/share/zoneinfo/tzdata"}) {
@@ -718,7 +717,7 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
}
}
}
-#endif // __ANDROID__
+
return nullptr;
}
@@ -922,7 +921,7 @@ bool TimeZoneInfo::NextTransition(const time_point<seconds>& tp,
++begin;
}
std::int_fast64_t unix_time = ToUnixSeconds(tp);
- const Transition target = { unix_time };
+ const Transition target = {unix_time, 0, civil_second(), civil_second()};
const Transition* tr = std::upper_bound(begin, end, target,
Transition::ByUnixTime());
for (; tr != end; ++tr) { // skip no-op transitions
@@ -957,7 +956,7 @@ bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp,
}
unix_time += 1; // ceils
}
- const Transition target = { unix_time };
+ const Transition target = {unix_time, 0, civil_second(), civil_second()};
const Transition* tr = std::lower_bound(begin, end, target,
Transition::ByUnixTime());
for (; tr != begin; --tr) { // skip no-op transitions
@@ -974,5 +973,5 @@ bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp,
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_info.h b/absl/time/internal/cctz/src/time_zone_info.h
index e7a7d02f..c724fa8f 100644
--- a/absl/time/internal/cctz/src/time_zone_info.h
+++ b/absl/time/internal/cctz/src/time_zone_info.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -28,7 +28,7 @@
#include "tzfile.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -89,7 +89,7 @@ class TimeZoneInfo : public TimeZoneIf {
std::size_t charcnt; // zone abbreviation characters
std::size_t leapcnt; // leap seconds (we expect none)
std::size_t ttisstdcnt; // UTC/local indicators (unused)
- std::size_t ttisgmtcnt; // standard/wall indicators (unused)
+ std::size_t ttisutcnt; // standard/wall indicators (unused)
bool Build(const tzhead& tzh);
std::size_t DataLength(std::size_t time_len) const;
@@ -132,7 +132,7 @@ class TimeZoneInfo : public TimeZoneIf {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_
diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc
index 3dd75b50..cfe7d55c 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,70 +21,87 @@
#include <chrono>
#include <ctime>
#include <limits>
-#include <tuple>
#include <utility>
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
namespace {
-// .first is seconds east of UTC; .second is the time-zone abbreviation.
-using OffsetAbbr = std::pair<int, const char*>;
-
-// Defines a function that can be called as follows:
-//
-// std::tm tm = ...;
-// OffsetAbbr off_abbr = get_offset_abbr(tm);
-//
#if defined(_WIN32) || defined(_WIN64)
// Uses the globals: '_timezone', '_dstbias' and '_tzname'.
-OffsetAbbr get_offset_abbr(const std::tm& tm) {
+auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + _dstbias) {
const bool is_dst = tm.tm_isdst > 0;
- const int off = _timezone + (is_dst ? _dstbias : 0);
- const char* abbr = _tzname[is_dst];
- return {off, abbr};
+ return _timezone + (is_dst ? _dstbias : 0);
+}
+auto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) {
+ const bool is_dst = tm.tm_isdst > 0;
+ return _tzname[is_dst];
}
#elif defined(__sun)
// Uses the globals: 'timezone', 'altzone' and 'tzname'.
-OffsetAbbr get_offset_abbr(const std::tm& tm) {
+auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) {
const bool is_dst = tm.tm_isdst > 0;
- const int off = is_dst ? altzone : timezone;
- const char* abbr = tzname[is_dst];
- return {off, abbr};
+ return is_dst ? altzone : timezone;
+}
+auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) {
+ const bool is_dst = tm.tm_isdst > 0;
+ return tzname[is_dst];
}
#elif defined(__native_client__) || defined(__myriad2__) || \
defined(__EMSCRIPTEN__)
// Uses the globals: 'timezone' and 'tzname'.
-OffsetAbbr get_offset_abbr(const std::tm& tm) {
+auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) {
+ const bool is_dst = tm.tm_isdst > 0;
+ return _timezone + (is_dst ? 60 * 60 : 0);
+}
+auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) {
const bool is_dst = tm.tm_isdst > 0;
- const int off = _timezone + (is_dst ? 60 * 60 : 0);
- const char* abbr = tzname[is_dst];
- return {off, abbr};
+ return tzname[is_dst];
+}
+#else
+// Adapt to different spellings of the struct std::tm extension fields.
+#if defined(tm_gmtoff)
+auto tm_gmtoff(const std::tm& tm) -> decltype(tm.tm_gmtoff) {
+ return tm.tm_gmtoff;
+}
+#elif defined(__tm_gmtoff)
+auto tm_gmtoff(const std::tm& tm) -> decltype(tm.__tm_gmtoff) {
+ return tm.__tm_gmtoff;
+}
+#else
+template <typename T>
+auto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) {
+ return tm.tm_gmtoff;
+}
+template <typename T>
+auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) {
+ return tm.__tm_gmtoff;
+}
+#endif // tm_gmtoff
+#if defined(tm_zone)
+auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) {
+ return tm.tm_zone;
+}
+#elif defined(__tm_zone)
+auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) {
+ return tm.__tm_zone;
}
#else
-//
-// Returns an OffsetAbbr using std::tm fields with various spellings.
-//
-#if !defined(tm_gmtoff) && !defined(tm_zone)
template <typename T>
-OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::tm_gmtoff) = nullptr,
- decltype(&T::tm_zone) = nullptr) {
- return {tm.tm_gmtoff, tm.tm_zone};
+auto tm_zone(const T& tm) -> decltype(tm.tm_zone) {
+ return tm.tm_zone;
}
-#endif // !defined(tm_gmtoff) && !defined(tm_zone)
-#if !defined(__tm_gmtoff) && !defined(__tm_zone)
template <typename T>
-OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::__tm_gmtoff) = nullptr,
- decltype(&T::__tm_zone) = nullptr) {
- return {tm.__tm_gmtoff, tm.__tm_zone};
+auto tm_zone(const T& tm) -> decltype(tm.__tm_zone) {
+ return tm.__tm_zone;
}
-#endif // !defined(__tm_gmtoff) && !defined(__tm_zone)
+#endif // tm_zone
#endif
inline std::tm* gm_time(const std::time_t *timep, std::tm *result) {
@@ -127,7 +144,7 @@ bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) {
return false;
}
}
- *off = get_offset_abbr(tm).first;
+ *off = static_cast<int>(tm_gmtoff(tm));
return true;
}
@@ -138,7 +155,7 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) {
while (lo + 1 != hi) {
const std::time_t mid = lo + (hi - lo) / 2;
if (std::tm* tmp = local_time(&mid, &tm)) {
- if (get_offset_abbr(*tmp).first == offset) {
+ if (tm_gmtoff(*tmp) == offset) {
hi = mid;
} else {
lo = mid;
@@ -148,7 +165,7 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) {
// ignoring all failed conversions. Slow, but never really happens.
while (++lo != hi) {
if (std::tm* tmp = local_time(&lo, &tm)) {
- if (get_offset_abbr(*tmp).first == offset) break;
+ if (tm_gmtoff(*tmp) == offset) break;
}
}
return lo;
@@ -194,8 +211,8 @@ time_zone::absolute_lookup TimeZoneLibC::BreakTime(
const year_t year = tmp->tm_year + year_t{1900};
al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
- std::tie(al.offset, al.abbr) = get_offset_abbr(*tmp);
- if (!local_) al.abbr = "UTC"; // as expected by cctz
+ al.offset = static_cast<int>(tm_gmtoff(*tmp));
+ al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz
al.is_dst = tmp->tm_isdst > 0;
return al;
}
@@ -268,13 +285,13 @@ time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const {
return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
}
-bool TimeZoneLibC::NextTransition(const time_point<seconds>& tp,
- time_zone::civil_transition* trans) const {
+bool TimeZoneLibC::NextTransition(const time_point<seconds>&,
+ time_zone::civil_transition*) const {
return false;
}
-bool TimeZoneLibC::PrevTransition(const time_point<seconds>& tp,
- time_zone::civil_transition* trans) const {
+bool TimeZoneLibC::PrevTransition(const time_point<seconds>&,
+ time_zone::civil_transition*) const {
return false;
}
@@ -288,5 +305,5 @@ std::string TimeZoneLibC::Description() const {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_libc.h b/absl/time/internal/cctz/src/time_zone_libc.h
index 67372d45..4b1ccb06 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.h
+++ b/absl/time/internal/cctz/src/time_zone_libc.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -20,7 +20,7 @@
#include "time_zone_if.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -49,7 +49,7 @@ class TimeZoneLibC : public TimeZoneIf {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_
diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc
index 711d705a..772a9375 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -16,10 +16,16 @@
#if defined(__ANDROID__)
#include <sys/system_properties.h>
-#if __ANDROID_API__ >= 21
+#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21
#include <dlfcn.h>
#endif
#endif
+
+#if defined(__APPLE__)
+#include <CoreFoundation/CFTimeZone.h>
+#include <vector>
+#endif
+
#include <cstdlib>
#include <cstring>
#include <string>
@@ -28,11 +34,11 @@
#include "time_zone_impl.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
-#if defined(__ANDROID__) && __ANDROID_API__ >= 21
+#if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21
namespace {
// Android 'L' removes __system_property_get() from the NDK, however
// it is still a hidden symbol in libc so we use dlsym() to access it.
@@ -117,6 +123,25 @@ time_zone fixed_time_zone(const seconds& offset) {
time_zone local_time_zone() {
const char* zone = ":localtime";
+#if defined(__ANDROID__)
+ char sysprop[PROP_VALUE_MAX];
+ if (__system_property_get("persist.sys.timezone", sysprop) > 0) {
+ zone = sysprop;
+ }
+#endif
+#if defined(__APPLE__)
+ std::vector<char> buffer;
+ CFTimeZoneRef tz_default = CFTimeZoneCopyDefault();
+ if (CFStringRef tz_name = CFTimeZoneGetName(tz_default)) {
+ CFStringEncoding encoding = kCFStringEncodingUTF8;
+ CFIndex length = CFStringGetLength(tz_name);
+ buffer.resize(CFStringGetMaximumSizeForEncoding(length, encoding) + 1);
+ if (CFStringGetCString(tz_name, &buffer[0], buffer.size(), encoding)) {
+ zone = &buffer[0];
+ }
+ }
+ CFRelease(tz_default);
+#endif
// Allow ${TZ} to override to default zone.
char* tz_env = nullptr;
@@ -125,12 +150,6 @@ time_zone local_time_zone() {
#else
tz_env = std::getenv("TZ");
#endif
-#if defined(__ANDROID__)
- char sysprop[PROP_VALUE_MAX];
- if (tz_env == nullptr)
- if (__system_property_get("persist.sys.timezone", sysprop) > 0)
- tz_env = sysprop;
-#endif
if (tz_env) zone = tz_env;
// We only support the "[:]<zone-name>" form.
@@ -166,5 +185,5 @@ time_zone local_time_zone() {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
index e0e355ee..1bef7708 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -29,7 +29,7 @@
namespace chrono = std::chrono;
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -338,6 +338,7 @@ const char* const kTimeZoneNames[] = {
"Asia/Pontianak",
"Asia/Pyongyang",
"Asia/Qatar",
+ "Asia/Qostanay",
"Asia/Qyzylorda",
"Asia/Rangoon",
"Asia/Riyadh",
@@ -667,6 +668,7 @@ int VersionCmp(time_zone tz, const std::string& target) {
} // namespace
+#if !defined(__EMSCRIPTEN__)
TEST(TimeZones, LoadZonesConcurrently) {
std::promise<void> ready_promise;
std::shared_future<void> ready_future(ready_promise.get_future());
@@ -714,6 +716,7 @@ TEST(TimeZones, LoadZonesConcurrently) {
}
EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures);
}
+#endif
TEST(TimeZone, NamedTimeZones) {
const time_zone utc = utc_time_zone();
@@ -834,7 +837,7 @@ TEST(BreakTime, LocalTimeInUTC) {
const time_zone tz = utc_time_zone();
const auto tp = chrono::system_clock::from_time_t(0);
ExpectTime(tp, tz, 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
- EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz)));
}
TEST(BreakTime, LocalTimeInUTCUnaligned) {
@@ -842,7 +845,7 @@ TEST(BreakTime, LocalTimeInUTCUnaligned) {
const auto tp =
chrono::system_clock::from_time_t(0) - chrono::milliseconds(500);
ExpectTime(tp, tz, 1969, 12, 31, 23, 59, 59, 0, false, "UTC");
- EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));
}
TEST(BreakTime, LocalTimePosix) {
@@ -850,7 +853,7 @@ TEST(BreakTime, LocalTimePosix) {
const time_zone tz = utc_time_zone();
const auto tp = chrono::system_clock::from_time_t(536457599);
ExpectTime(tp, tz, 1986, 12, 31, 23, 59, 59, 0, false, "UTC");
- EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));
}
TEST(TimeZoneImpl, LocalTimeInFixed) {
@@ -860,28 +863,28 @@ TEST(TimeZoneImpl, LocalTimeInFixed) {
const auto tp = chrono::system_clock::from_time_t(0);
ExpectTime(tp, tz, 1969, 12, 31, 15, 26, 13, offset.count(), false,
"-083347");
- EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));
}
TEST(BreakTime, LocalTimeInNewYork) {
const time_zone tz = LoadZone("America/New_York");
const auto tp = chrono::system_clock::from_time_t(45);
ExpectTime(tp, tz, 1969, 12, 31, 19, 0, 45, -5 * 60 * 60, false, "EST");
- EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));
}
TEST(BreakTime, LocalTimeInMTV) {
const time_zone tz = LoadZone("America/Los_Angeles");
const auto tp = chrono::system_clock::from_time_t(1380855729);
ExpectTime(tp, tz, 2013, 10, 3, 20, 2, 9, -7 * 60 * 60, true, "PDT");
- EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz)));
}
TEST(BreakTime, LocalTimeInSydney) {
const time_zone tz = LoadZone("Australia/Sydney");
const auto tp = chrono::system_clock::from_time_t(90);
ExpectTime(tp, tz, 1970, 1, 1, 10, 1, 30, 10 * 60 * 60, false, "AEST");
- EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz)));
}
TEST(MakeTime, TimePointResolution) {
@@ -1019,7 +1022,7 @@ TEST(MakeTime, LocalTimeLibC) {
// 1) we know how to change the time zone used by localtime()/mktime(),
// 2) cctz and localtime()/mktime() will use similar-enough tzdata, and
// 3) we have some idea about how mktime() behaves during transitions.
-#if defined(__linux__)
+#if defined(__linux__) && !defined(__ANDROID__)
const char* const ep = getenv("TZ");
std::string tz_name = (ep != nullptr) ? ep : "";
for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) {
@@ -1272,10 +1275,10 @@ TEST(TimeZoneEdgeCase, PacificApia) {
// 1325239200 == Sat, 31 Dec 2011 00:00:00 +1400 (+14)
auto tp = convert(civil_second(2011, 12, 29, 23, 59, 59), tz);
ExpectTime(tp, tz, 2011, 12, 29, 23, 59, 59, -10 * 3600, true, "-10");
- EXPECT_EQ(363, get_yearday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(363, get_yearday(convert(tp, tz)));
tp += absl::time_internal::cctz::seconds(1);
ExpectTime(tp, tz, 2011, 12, 31, 0, 0, 0, 14 * 3600, true, "+14");
- EXPECT_EQ(365, get_yearday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(365, get_yearday(convert(tp, tz)));
}
TEST(TimeZoneEdgeCase, AfricaCairo) {
@@ -1397,10 +1400,10 @@ TEST(TimeZoneEdgeCase, NegativeYear) {
const time_zone tz = utc_time_zone();
auto tp = convert(civil_second(0, 1, 1, 0, 0, 0), tz);
ExpectTime(tp, tz, 0, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC");
- EXPECT_EQ(weekday::saturday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::saturday, get_weekday(convert(tp, tz)));
tp -= absl::time_internal::cctz::seconds(1);
ExpectTime(tp, tz, -1, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC");
- EXPECT_EQ(weekday::friday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::friday, get_weekday(convert(tp, tz)));
}
TEST(TimeZoneEdgeCase, UTC32bitLimit) {
@@ -1431,5 +1434,5 @@ TEST(TimeZoneEdgeCase, UTC5DigitYear) {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_posix.cc b/absl/time/internal/cctz/src/time_zone_posix.cc
index 960133d7..d1f8ecbe 100644
--- a/absl/time/internal/cctz/src/time_zone_posix.cc
+++ b/absl/time/internal/cctz/src/time_zone_posix.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -20,7 +20,7 @@
#include <string>
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -101,9 +101,9 @@ const char* ParseDateTime(const char* p, PosixTransition* res) {
int weekday = 0;
if ((p = ParseInt(p + 1, 0, 6, &weekday)) != nullptr) {
res->date.fmt = PosixTransition::M;
- res->date.m.month = static_cast<int_fast8_t>(month);
- res->date.m.week = static_cast<int_fast8_t>(week);
- res->date.m.weekday = static_cast<int_fast8_t>(weekday);
+ res->date.m.month = static_cast<std::int_fast8_t>(month);
+ res->date.m.week = static_cast<std::int_fast8_t>(week);
+ res->date.m.weekday = static_cast<std::int_fast8_t>(weekday);
}
}
}
@@ -111,13 +111,13 @@ const char* ParseDateTime(const char* p, PosixTransition* res) {
int day = 0;
if ((p = ParseInt(p + 1, 1, 365, &day)) != nullptr) {
res->date.fmt = PosixTransition::J;
- res->date.j.day = static_cast<int_fast16_t>(day);
+ res->date.j.day = static_cast<std::int_fast16_t>(day);
}
} else {
int day = 0;
if ((p = ParseInt(p, 0, 365, &day)) != nullptr) {
res->date.fmt = PosixTransition::N;
- res->date.j.day = static_cast<int_fast16_t>(day);
+ res->date.n.day = static_cast<std::int_fast16_t>(day);
}
}
}
@@ -153,5 +153,5 @@ bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res) {
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_posix.h b/absl/time/internal/cctz/src/time_zone_posix.h
index 84c39afb..07e3427a 100644
--- a/absl/time/internal/cctz/src/time_zone_posix.h
+++ b/absl/time/internal/cctz/src/time_zone_posix.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -56,7 +56,7 @@
#include <string>
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -124,7 +124,7 @@ bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res);
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_
diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h
index 4485ba55..51b1f1f3 100644
--- a/absl/time/internal/cctz/src/tzfile.h
+++ b/absl/time/internal/cctz/src/tzfile.h
@@ -33,6 +33,9 @@
#define TZDEFRULES "posixrules"
#endif /* !defined TZDEFRULES */
+
+/* See Internet RFC 8536 for more details about the following format. */
+
/*
** Each file begins with. . .
*/
@@ -43,7 +46,7 @@ struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
char tzh_reserved[15]; /* reserved; must be zero */
- char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
+ char tzh_ttisutcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
char tzh_timecnt[4]; /* coded number of transition times */
@@ -66,14 +69,15 @@ struct tzhead {
** one (char [4]) total correction after above
** tzh_ttisstdcnt (char)s indexed by type; if 1, transition
** time is standard time, if 0,
-** transition time is wall clock time
-** if absent, transition times are
-** assumed to be wall clock time
-** tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
-** time is UT, if 0,
-** transition time is local time
-** if absent, transition times are
+** transition time is local (wall clock)
+** time; if absent, transition times are
** assumed to be local time
+** tzh_ttisutcnt (char)s indexed by type; if 1, transition
+** time is UT, if 0, transition time is
+** local time; if absent, transition
+** times are assumed to be local time.
+** When this is 1, the corresponding
+** std/wall indicator must also be 1.
*/
/*
diff --git a/absl/time/internal/cctz/src/zone_info_source.cc b/absl/time/internal/cctz/src/zone_info_source.cc
index 61669e7a..b64950cb 100644
--- a/absl/time/internal/cctz/src/zone_info_source.cc
+++ b/absl/time/internal/cctz/src/zone_info_source.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -15,7 +15,7 @@
#include "absl/time/internal/cctz/include/cctz/zone_info_source.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz {
@@ -25,11 +25,11 @@ std::string ZoneInfoSource::Version() const { return std::string(); }
} // namespace cctz
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace time_internal {
namespace cctz_extension {
@@ -49,35 +49,33 @@ std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory(
// A "weak" definition for cctz_extension::zone_info_source_factory.
// The user may override this with their own "strong" definition (see
// zone_info_source.h).
-#if defined(_MSC_VER)
+#if !defined(__has_attribute)
+#define __has_attribute(x) 0
+#endif
+#if __has_attribute(weak) || defined(__GNUC__)
+ZoneInfoSourceFactory zone_info_source_factory
+ __attribute__((weak)) = DefaultFactory;
+#elif defined(_MSC_VER) && !defined(_LIBCPP_VERSION)
extern ZoneInfoSourceFactory zone_info_source_factory;
extern ZoneInfoSourceFactory default_factory;
ZoneInfoSourceFactory default_factory = DefaultFactory;
#if defined(_M_IX86)
#pragma comment( \
linker, \
- "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@lts_2018_12_18@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@6@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@6@@ZA=?default_factory@cctz_extension@time_internal@lts_2018_12_18@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@6@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@6@@ZA")
-#elif defined(_M_IA_64) || defined(_M_AMD64)
+ "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@lts_2019_08_08@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@6@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@6@@ZA=?default_factory@cctz_extension@time_internal@lts_2019_08_08@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@6@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@6@@ZA")
+#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM64)
#pragma comment( \
linker, \
- "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@lts_2018_12_18@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@6@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@6@@ZEA=?default_factory@cctz_extension@time_internal@lts_2018_12_18@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@6@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2018_12_18@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@6@@ZEA")
+ "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@lts_2019_08_08@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@6@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@6@@ZEA=?default_factory@cctz_extension@time_internal@lts_2019_08_08@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@6@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@lts_2019_08_08@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@6@@ZEA")
#else
#error Unsupported MSVC platform
-#endif
-#else // _MSC_VER
-#if !defined(__has_attribute)
-#define __has_attribute(x) 0
-#endif
-#if __has_attribute(weak) || defined(__GNUC__)
-ZoneInfoSourceFactory zone_info_source_factory
- __attribute__((weak)) = DefaultFactory;
+#endif // _M_<PLATFORM>
#else
// Make it a "strong" definition if we have no other choice.
ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory;
#endif
-#endif // _MSC_VER
} // namespace cctz_extension
} // namespace time_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl