diff options
Diffstat (limited to 'abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc')
-rw-r--r-- | abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc | 134 |
1 files changed, 110 insertions, 24 deletions
diff --git a/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc index 9a1a8d6..4884c32 100644 --- a/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc @@ -21,10 +21,14 @@ #include <thread> #include <vector> -#include "gtest/gtest.h" #include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" +#if defined(__linux__) +#include <features.h> +#endif + +#include "gtest/gtest.h" +#include "absl/time/internal/cctz/include/cctz/civil_time.h" namespace chrono = std::chrono; @@ -131,6 +135,7 @@ const char* const kTimeZoneNames[] = {"Africa/Abidjan", "America/Cayman", "America/Chicago", "America/Chihuahua", + "America/Ciudad_Juarez", "America/Coral_Harbour", "America/Cordoba", "America/Costa_Rica", @@ -485,6 +490,7 @@ const char* const kTimeZoneNames[] = {"Africa/Abidjan", "Europe/Kaliningrad", "Europe/Kiev", "Europe/Kirov", + "Europe/Kyiv", "Europe/Lisbon", "Europe/Ljubljana", "Europe/London", @@ -524,6 +530,7 @@ const char* const kTimeZoneNames[] = {"Africa/Abidjan", "Europe/Zagreb", "Europe/Zaporozhye", "Europe/Zurich", + "Factory", "GB", "GB-Eire", "GMT", @@ -579,6 +586,7 @@ const char* const kTimeZoneNames[] = {"Africa/Abidjan", "Pacific/Guam", "Pacific/Honolulu", "Pacific/Johnston", + "Pacific/Kanton", "Pacific/Kiritimati", "Pacific/Kosrae", "Pacific/Kwajalein", @@ -717,6 +725,22 @@ TEST(TimeZones, LoadZonesConcurrently) { } #endif +TEST(TimeZone, UTC) { + const time_zone utc = utc_time_zone(); + + time_zone loaded_utc; + EXPECT_TRUE(load_time_zone("UTC", &loaded_utc)); + EXPECT_EQ(loaded_utc, utc); + + time_zone loaded_utc0; + EXPECT_TRUE(load_time_zone("UTC0", &loaded_utc0)); + EXPECT_EQ(loaded_utc0, utc); + + time_zone loaded_bad; + EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &loaded_bad)); + EXPECT_EQ(loaded_bad, utc); +} + TEST(TimeZone, NamedTimeZones) { const time_zone utc = utc_time_zone(); EXPECT_EQ("UTC", utc.name()); @@ -892,19 +916,19 @@ TEST(MakeTime, TimePointResolution) { const time_zone utc = utc_time_zone(); const time_point<chrono::nanoseconds> tp_ns = convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_ns, utc)); + EXPECT_EQ("04:05", absl::time_internal::cctz::format("%M:%E*S", tp_ns, utc)); const time_point<chrono::microseconds> tp_us = convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_us, utc)); + EXPECT_EQ("04:05", absl::time_internal::cctz::format("%M:%E*S", tp_us, utc)); const time_point<chrono::milliseconds> tp_ms = convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_ms, utc)); + EXPECT_EQ("04:05", absl::time_internal::cctz::format("%M:%E*S", tp_ms, utc)); const time_point<chrono::seconds> tp_s = convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_s, utc)); + EXPECT_EQ("04:05", absl::time_internal::cctz::format("%M:%E*S", tp_s, utc)); const time_point<absl::time_internal::cctz::seconds> tp_s64 = convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_s64, utc)); + EXPECT_EQ("04:05", absl::time_internal::cctz::format("%M:%E*S", tp_s64, utc)); // These next two require chrono::time_point_cast because the conversion // from a resolution of seconds (the return value of convert()) to a @@ -912,10 +936,10 @@ TEST(MakeTime, TimePointResolution) { const time_point<chrono::minutes> tp_m = chrono::time_point_cast<chrono::minutes>( convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); - EXPECT_EQ("04:00", format("%M:%E*S", tp_m, utc)); + EXPECT_EQ("04:00", absl::time_internal::cctz::format("%M:%E*S", tp_m, utc)); const time_point<chrono::hours> tp_h = chrono::time_point_cast<chrono::hours>( convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); - EXPECT_EQ("00:00", format("%M:%E*S", tp_h, utc)); + EXPECT_EQ("00:00", absl::time_internal::cctz::format("%M:%E*S", tp_h, utc)); } TEST(MakeTime, Normalization) { @@ -941,9 +965,11 @@ TEST(MakeTime, SysSecondsLimits) { // Approach the maximal time_point<cctz::seconds> value from below. tp = convert(civil_second(292277026596, 12, 4, 15, 30, 6), utc); - EXPECT_EQ("292277026596-12-04T15:30:06+00:00", format(RFC3339, tp, utc)); + EXPECT_EQ("292277026596-12-04T15:30:06+00:00", + absl::time_internal::cctz::format(RFC3339, tp, utc)); tp = convert(civil_second(292277026596, 12, 4, 15, 30, 7), utc); - EXPECT_EQ("292277026596-12-04T15:30:07+00:00", format(RFC3339, tp, utc)); + EXPECT_EQ("292277026596-12-04T15:30:07+00:00", + absl::time_internal::cctz::format(RFC3339, tp, utc)); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); tp = convert(civil_second(292277026596, 12, 4, 15, 30, 8), utc); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); @@ -952,7 +978,8 @@ TEST(MakeTime, SysSecondsLimits) { // Checks that we can also get the maximal value for a far-east zone. tp = convert(civil_second(292277026596, 12, 5, 5, 30, 7), east); - EXPECT_EQ("292277026596-12-05T05:30:07+14:00", format(RFC3339, tp, east)); + EXPECT_EQ("292277026596-12-05T05:30:07+14:00", + absl::time_internal::cctz::format(RFC3339, tp, east)); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); tp = convert(civil_second(292277026596, 12, 5, 5, 30, 8), east); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); @@ -961,7 +988,8 @@ TEST(MakeTime, SysSecondsLimits) { // Checks that we can also get the maximal value for a far-west zone. tp = convert(civil_second(292277026596, 12, 4, 1, 30, 7), west); - EXPECT_EQ("292277026596-12-04T01:30:07-14:00", format(RFC3339, tp, west)); + EXPECT_EQ("292277026596-12-04T01:30:07-14:00", + absl::time_internal::cctz::format(RFC3339, tp, west)); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); tp = convert(civil_second(292277026596, 12, 4, 7, 30, 8), west); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp); @@ -970,9 +998,11 @@ TEST(MakeTime, SysSecondsLimits) { // Approach the minimal time_point<cctz::seconds> value from above. tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 53), utc); - EXPECT_EQ("-292277022657-01-27T08:29:53+00:00", format(RFC3339, tp, utc)); + EXPECT_EQ("-292277022657-01-27T08:29:53+00:00", + absl::time_internal::cctz::format(RFC3339, tp, utc)); tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 52), utc); - EXPECT_EQ("-292277022657-01-27T08:29:52+00:00", format(RFC3339, tp, utc)); + EXPECT_EQ("-292277022657-01-27T08:29:52+00:00", + absl::time_internal::cctz::format(RFC3339, tp, utc)); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 51), utc); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); @@ -981,7 +1011,8 @@ TEST(MakeTime, SysSecondsLimits) { // Checks that we can also get the minimal value for a far-east zone. tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 52), east); - EXPECT_EQ("-292277022657-01-27T22:29:52+14:00", format(RFC3339, tp, east)); + EXPECT_EQ("-292277022657-01-27T22:29:52+14:00", + absl::time_internal::cctz::format(RFC3339, tp, east)); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 51), east); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); @@ -990,7 +1021,8 @@ TEST(MakeTime, SysSecondsLimits) { // Checks that we can also get the minimal value for a far-west zone. tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 52), west); - EXPECT_EQ("-292277022657-01-26T18:29:52-14:00", format(RFC3339, tp, west)); + EXPECT_EQ("-292277022657-01-26T18:29:52-14:00", + absl::time_internal::cctz::format(RFC3339, tp, west)); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 51), west); EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp); @@ -1007,14 +1039,20 @@ TEST(MakeTime, SysSecondsLimits) { const time_zone cut = LoadZone("libc:UTC"); const year_t max_tm_year = year_t{std::numeric_limits<int>::max()} + 1900; tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), cut); -#if defined(__FreeBSD__) || defined(__OpenBSD__) - // The BSD gmtime_r() fails on extreme positive tm_year values. +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__) + // Some gmtime_r() impls fail on extreme positive values. #else - EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, cut)); + EXPECT_EQ("2147485547-12-31T23:59:59+00:00", + absl::time_internal::cctz::format(RFC3339, tp, cut)); #endif const year_t min_tm_year = year_t{std::numeric_limits<int>::min()} + 1900; tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), cut); - EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, cut)); +#if defined(__Fuchsia__) || defined(__EMSCRIPTEN__) + // Some gmtime_r() impls fail on extreme negative values (fxbug.dev/78527). +#else + EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", + absl::time_internal::cctz::format(RFC3339, tp, cut)); +#endif #endif } } @@ -1026,7 +1064,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__) && !defined(__ANDROID__) +#if defined(__linux__) && defined(__GLIBC__) && !defined(__ANDROID__) const char* const ep = getenv("TZ"); std::string tz_name = (ep != nullptr) ? ep : ""; for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { @@ -1039,7 +1077,7 @@ TEST(MakeTime, LocalTimeLibC) { tp = zi.lookup(transition.to).trans) { const auto fcl = zi.lookup(transition.from); const auto tcl = zi.lookup(transition.to); - civil_second cs; // compare cs in zi and lc + civil_second cs, us; // compare cs and us in zi and lc if (fcl.kind == time_zone::civil_lookup::UNIQUE) { if (tcl.kind == time_zone::civil_lookup::UNIQUE) { // Both unique; must be an is_dst or abbr change. @@ -1055,12 +1093,14 @@ TEST(MakeTime, LocalTimeLibC) { } ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind); cs = transition.to; + us = transition.from; } else { ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind); ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind); cs = transition.from; + us = transition.to; } - if (cs.year() > 2037) break; // limit test time (and to 32-bit time_t) + if (us.year() > 2037) break; // limit test time (and to 32-bit time_t) const auto cl_zi = zi.lookup(cs); if (zi.lookup(cl_zi.pre).is_dst == zi.lookup(cl_zi.post).is_dst) { // The "libc" implementation cannot correctly classify transitions @@ -1092,6 +1132,13 @@ TEST(MakeTime, LocalTimeLibC) { EXPECT_EQ(cl_zi.pre, cl_lc.pre); EXPECT_EQ(cl_zi.trans, cl_lc.trans); EXPECT_EQ(cl_zi.post, cl_lc.post); + const auto ucl_zi = zi.lookup(us); + const auto ucl_lc = lc.lookup(us); + SCOPED_TRACE(testing::Message() << "For " << us << " in " << *np); + EXPECT_EQ(ucl_zi.kind, ucl_lc.kind); + EXPECT_EQ(ucl_zi.pre, ucl_lc.pre); + EXPECT_EQ(ucl_zi.trans, ucl_lc.trans); + EXPECT_EQ(ucl_zi.post, ucl_lc.post); } } if (ep == nullptr) { @@ -1165,6 +1212,45 @@ TEST(PrevTransition, AmericaNewYork) { // We have a transition but we don't know which one. } +TEST(NextTransition, Scan) { + for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { + SCOPED_TRACE(testing::Message() << "In " << *np); + time_zone tz; + // EXPECT_TRUE(load_time_zone(*np, &tz)); + if (!load_time_zone(*np, &tz)) { + continue; // tolerate kTimeZoneNames/zoneinfo skew + } + + auto tp = time_point<absl::time_internal::cctz::seconds>::min(); + time_zone::civil_transition trans; + while (tz.next_transition(tp, &trans)) { + time_zone::civil_lookup from_cl = tz.lookup(trans.from); + EXPECT_NE(from_cl.kind, time_zone::civil_lookup::REPEATED); + time_zone::civil_lookup to_cl = tz.lookup(trans.to); + EXPECT_NE(to_cl.kind, time_zone::civil_lookup::SKIPPED); + + auto trans_tp = to_cl.trans; + time_zone::absolute_lookup trans_al = tz.lookup(trans_tp); + EXPECT_EQ(trans_al.cs, trans.to); + auto pre_trans_tp = trans_tp - absl::time_internal::cctz::seconds(1); + time_zone::absolute_lookup pre_trans_al = tz.lookup(pre_trans_tp); + EXPECT_EQ(pre_trans_al.cs + 1, trans.from); + + auto offset_delta = trans_al.offset - pre_trans_al.offset; + EXPECT_EQ(offset_delta, trans.to - trans.from); + if (offset_delta == 0) { + // This "transition" is only an is_dst or abbr change. + EXPECT_EQ(to_cl.kind, time_zone::civil_lookup::UNIQUE); + if (trans_al.is_dst == pre_trans_al.is_dst) { + EXPECT_STRNE(trans_al.abbr, pre_trans_al.abbr); + } + } + + tp = trans_tp; // continue scan from transition + } + } +} + TEST(TimeZoneEdgeCase, AmericaNewYork) { const time_zone tz = LoadZone("America/New_York"); |