1414 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// TODO TZDB review the test based on review comments in10// https://github.com/llvm/llvm-project/pull/8561911 12// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23, c++2613// UNSUPPORTED: no-filesystem, no-localization, no-tzdb14 15// XFAIL: libcpp-has-no-experimental-tzdb16// XFAIL: availability-tzdb-missing17 18// <chrono>19 20// class time_zone;21 22// template <class _Duration>23// sys_info get_info(const sys_time<_Duration>& time) const;24 25// This test uses the system provided database. This makes the test portable,26// but may cause failures when the database information changes. Historic data27// may change if new facts are uncovered, future data may change when regions28// change their time zone or daylight saving time. Most tests will not look in29// the future to attempt to avoid issues. All tests list the data on which they30// are based, this makes debugging easier upon failure; including to see whether31// the provided data has not been changed32//33//34// The data in the tests can be validated by using the zdump tool. For35// example36// zdump -v Asia/Hong_Kong37// show all transitions in the Hong Kong time zone. Or38// zdump -c1970,1980 -v Asia/Hong_Kong39// shows all transitions in Hong Kong between 1970 and 1980.40 41#include <algorithm>42#include <cassert>43#include <chrono>44#include <format>45 46#include "test_macros.h"47#include "assert_macros.h"48#include "concat_macros.h"49 50/***** ***** HELPERS ***** *****/51 52[[nodiscard]] static std::chrono::sys_seconds to_sys_seconds(53 std::chrono::year year,54 std::chrono::month month,55 std::chrono::day day,56 std::chrono::hours h = std::chrono::hours(0),57 std::chrono::minutes m = std::chrono::minutes{0},58 std::chrono::seconds s = std::chrono::seconds{0}) {59 std::chrono::year_month_day result{year, month, day};60 61 return std::chrono::time_point_cast<std::chrono::seconds>(static_cast<std::chrono::sys_days>(result)) + h + m + s;62}63 64static void assert_equal(const std::chrono::sys_info& lhs, const std::chrono::sys_info& rhs) {65 TEST_REQUIRE(lhs.begin == rhs.begin,66 TEST_WRITE_CONCATENATED("\nBegin:\nExpected output ", lhs.begin, "\nActual output ", rhs.begin, '\n'));67 TEST_REQUIRE(lhs.end == rhs.end,68 TEST_WRITE_CONCATENATED("\nEnd:\nExpected output ", lhs.end, "\nActual output ", rhs.end, '\n'));69 TEST_REQUIRE(70 lhs.offset == rhs.offset,71 TEST_WRITE_CONCATENATED("\nOffset:\nExpected output ", lhs.offset, "\nActual output ", rhs.offset, '\n'));72 TEST_REQUIRE(lhs.save == rhs.save,73 TEST_WRITE_CONCATENATED("\nSave:\nExpected output ", lhs.save, "\nActual output ", rhs.save, '\n'));74 TEST_REQUIRE(75 lhs.abbrev == rhs.abbrev,76 TEST_WRITE_CONCATENATED("\nAbbrev:\nExpected output ", lhs.abbrev, "\nActual output ", rhs.abbrev, '\n'));77}78 79static void assert_equal(std::string_view expected, const std::chrono::sys_info& value) {80 // Note the output of operator<< is implementation defined, use this81 // format to keep the test portable.82 std::string result = std::format(83 "[{}, {}) {:%T} {:%Q%q} {}",84 value.begin,85 value.end,86 std::chrono::hh_mm_ss{value.offset},87 value.save,88 value.abbrev);89 90 TEST_REQUIRE(expected == result,91 TEST_WRITE_CONCATENATED("\nExpected output ", expected, "\nActual output ", result, '\n'));92}93 94static void95assert_range(std::string_view expected, const std::chrono::sys_info& begin, const std::chrono::sys_info& end) {96 assert_equal(expected, begin);97 assert_equal(expected, end);98}99 100static void assert_cycle(101 std::string_view expected_1,102 const std::chrono::sys_info& begin_1,103 const std::chrono::sys_info& end_1,104 std::string_view expected_2,105 const std::chrono::sys_info& begin_2,106 const std::chrono::sys_info& end_2107 108) {109 assert_range(expected_1, begin_1, end_1);110 assert_range(expected_2, begin_2, end_2);111}112 113/***** ***** TESTS ***** *****/114 115static void test_gmt() {116 // Simple zone always valid, no rule entries, lookup using a link.117 // L Etc/GMT GMT118 // Z Etc/GMT 0 - GMT119 120 const std::chrono::time_zone* tz = std::chrono::locate_zone("GMT");121 122 assert_equal(123 std::chrono::sys_info(124 std::chrono::sys_seconds::min(),125 std::chrono::sys_seconds::max(),126 std::chrono::seconds(0),127 std::chrono::minutes(0),128 "GMT"),129 tz->get_info(std::chrono::sys_seconds::min()));130 assert_equal(131 std::chrono::sys_info(132 std::chrono::sys_seconds::min(),133 std::chrono::sys_seconds::max(),134 std::chrono::seconds(0),135 std::chrono::minutes(0),136 "GMT"),137 tz->get_info(std::chrono::sys_seconds(std::chrono::seconds{0})));138 139 assert_equal(140 std::chrono::sys_info(141 std::chrono::sys_seconds::min(),142 std::chrono::sys_seconds::max(),143 std::chrono::seconds(0),144 std::chrono::minutes(0),145 "GMT"),146 tz->get_info(std::chrono::sys_seconds::max() - std::chrono::seconds{1})); // max is not valid147}148 149static void test_durations() {150 // Doesn't test a location, instead tests whether different duration151 // specializations work.152 const std::chrono::time_zone* tz = std::chrono::locate_zone("GMT");153 154 // Using the GMT zone means every call gives the same result.155 std::chrono::sys_info expected(156 std::chrono::sys_seconds::min(),157 std::chrono::sys_seconds::max(),158 std::chrono::seconds(0),159 std::chrono::minutes(0),160 "GMT");161 162 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::nanoseconds>{}));163 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::microseconds>{}));164 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::milliseconds>{}));165 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::seconds>{}));166 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::minutes>{}));167 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::minutes>{}));168 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::hours>{}));169 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::days>{}));170 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::weeks>{}));171 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::months>{}));172 assert_equal(expected, tz->get_info(std::chrono::sys_time<std::chrono::years>{}));173}174 175static void test_antarctica_syowa() {176 // One change, no rules, no dst changes177 // This change uses an ON field with a day number178 //179 // There don't seem to be rule-less zones that use last day or a180 // constrained day181 182 // Z Antarctica/Syowa 0 - -00 1957 Ja 29183 // 3 - +03184 185 const std::chrono::time_zone* tz = std::chrono::locate_zone("Antarctica/Syowa");186 187 std::chrono::sys_seconds transition =188 to_sys_seconds(std::chrono::year(1957), std::chrono::January, std::chrono::day(29));189 190 assert_equal(191 std::chrono::sys_info(192 std::chrono::sys_seconds::min(), //193 transition, //194 std::chrono::seconds(0), //195 std::chrono::minutes(0), //196 "-00"), //197 tz->get_info(std::chrono::sys_seconds::min()));198 199 assert_equal(200 std::chrono::sys_info(201 std::chrono::sys_seconds::min(), //202 transition, //203 std::chrono::seconds(0), //204 std::chrono::minutes(0), //205 "-00"), //206 tz->get_info(transition - std::chrono::seconds(1)));207 208 assert_equal(209 std::chrono::sys_info(210 transition, //211 std::chrono::sys_seconds::max(), //212 std::chrono::hours(3), //213 std::chrono::minutes(0), //214 "+03"), //215 tz->get_info(transition));216}217 218static void test_asia_hong_kong() {219 // A more typical entry, first some hard-coded entires and then at the220 // end a rules based entry. This rule is valid for its entire period221 //222 // Z Asia/Hong_Kong 7:36:42 - LMT 1904 O 30 0:36:42223 // 8 - HKT 1941 Jun 15 3224 // 8 1 HKST 1941 O 1 4225 // 8 0:30 HKWT 1941 D 25226 // 9 - JST 1945 N 18 2227 // 8 HK HK%sT228 //229 // R HK 1946 o - Ap 21 0 1 S230 // R HK 1946 o - D 1 3:30s 0 -231 // R HK 1947 o - Ap 13 3:30s 1 S232 // R HK 1947 o - N 30 3:30s 0 -233 // R HK 1948 o - May 2 3:30s 1 S234 // R HK 1948 1952 - O Su>=28 3:30s 0 -235 // R HK 1949 1953 - Ap Su>=1 3:30 1 S236 // R HK 1953 1964 - O Su>=31 3:30 0 -237 // R HK 1954 1964 - Mar Su>=18 3:30 1 S238 // R HK 1965 1976 - Ap Su>=16 3:30 1 S239 // R HK 1965 1976 - O Su>=16 3:30 0 -240 // R HK 1973 o - D 30 3:30 1 S241 // R HK 1979 o - May 13 3:30 1 S242 // R HK 1979 o - O 21 3:30 0 -243 244 using namespace std::literals::chrono_literals;245 const std::chrono::time_zone* tz = std::chrono::locate_zone("Asia/Hong_Kong");246 247 assert_equal(248 std::chrono::sys_info(249 std::chrono::sys_seconds::min(),250 to_sys_seconds(1904y, std::chrono::October, 29d, 17h), // 7:36:42 - LMT 1904 O 30 0:36:42251 7h + 36min + 42s,252 0min,253 "LMT"),254 tz->get_info(std::chrono::sys_seconds::min()));255 256 assert_equal(257 std::chrono::sys_info(258 std::chrono::sys_seconds::min(),259 to_sys_seconds(1904y, std::chrono::October, 29d, 17h), // 7:36:42 - LMT 1904 O 30 0:36:42260 7h + 36min + 42s,261 0min,262 "LMT"),263 tz->get_info(to_sys_seconds(1904y, std::chrono::October, 29d, 16h, 59min, 59s)));264 265 assert_range("[1904-10-29 17:00:00, 1941-06-14 19:00:00) 08:00:00 0min HKT", // 8 - HKT 1941 Jun 15 3266 tz->get_info(to_sys_seconds(1904y, std::chrono::October, 29d, 17h)),267 tz->get_info(to_sys_seconds(1941y, std::chrono::June, 14d, 18h, 59min, 59s)));268 269 assert_range("[1941-06-14 19:00:00, 1941-09-30 19:00:00) 09:00:00 60min HKST", // 8 1 HKST 1941 O 1 4270 tz->get_info(to_sys_seconds(1941y, std::chrono::June, 14d, 19h)),271 tz->get_info(to_sys_seconds(1941y, std::chrono::September, 30d, 18h, 59min, 59s)));272 273 assert_range("[1941-09-30 19:00:00, 1941-12-24 15:30:00) 08:30:00 30min HKWT", // 8 0:30 HKWT 1941 D 25274 tz->get_info(to_sys_seconds(1941y, std::chrono::September, 30d, 19h)),275 tz->get_info(to_sys_seconds(1941y, std::chrono::December, 24d, 15h, 29min, 59s)));276 277 assert_range("[1941-12-24 15:30:00, 1945-11-17 17:00:00) 09:00:00 0min JST", // 9 - JST 1945 N 18 2278 tz->get_info(to_sys_seconds(1941y, std::chrono::December, 24d, 15h, 30min)),279 tz->get_info(to_sys_seconds(1945y, std::chrono::November, 17d, 16h, 59min, 59s)));280 281 assert_range("[1945-11-17 17:00:00, 1946-04-20 16:00:00) 08:00:00 0min HKT", // 8 HK%sT282 tz->get_info(to_sys_seconds(1945y, std::chrono::November, 17d, 17h)),283 tz->get_info(to_sys_seconds(1946y, std::chrono::April, 20d, 15h, 59min, 59s)));284 285 assert_cycle( // 8 HK%sT286 "[1946-04-20 16:00:00, 1946-11-30 19:30:00) 09:00:00 60min HKST",287 tz->get_info(to_sys_seconds(1946y, std::chrono::April, 20d, 16h)), // 1946 o Ap 21 0 1 S288 tz->get_info(to_sys_seconds(1946y, std::chrono::November, 30d, 19h, 29min, 59s)), // 1946 o D 1 3:30s 0 -289 "[1946-11-30 19:30:00, 1947-04-12 19:30:00) 08:00:00 0min HKT",290 tz->get_info(to_sys_seconds(1946y, std::chrono::November, 30d, 19h, 30min)), // 1946 o D 1 3:30s 0 -291 tz->get_info(to_sys_seconds(1947y, std::chrono::April, 12d, 19h, 29min, 59s))); // 1947 o Ap 13 3:30s 1 S292 293 assert_cycle( // 8 HK%sT294 "[1947-04-12 19:30:00, 1947-11-29 19:30:00) 09:00:00 60min HKST",295 tz->get_info(to_sys_seconds(1947y, std::chrono::April, 12d, 19h, 30min)), // 1947 o Ap 13 3:30s 1 S296 tz->get_info(to_sys_seconds(1947y, std::chrono::November, 29d, 19h, 29min, 59s)), // 1947 o N 30 3:30s 0 -297 "[1947-11-29 19:30:00, 1948-05-01 19:30:00) 08:00:00 0min HKT",298 tz->get_info(to_sys_seconds(1947y, std::chrono::November, 29d, 19h, 30min)), // 1947 o N 30 3:30s 0 -299 tz->get_info(to_sys_seconds(1948y, std::chrono::May, 1d, 19h, 29min, 59s))); // 1948 o May 2 3:30s 1 S300 301 assert_cycle( // 8 HK%sT302 "[1948-05-01 19:30:00, 1948-10-30 19:30:00) 09:00:00 60min HKST",303 tz->get_info(to_sys_seconds(1948y, std::chrono::May, 1d, 19h, 30min)), // 1948 o May 2 3:30s 1 S304 tz->get_info(to_sys_seconds(1948y, std::chrono::October, 30d, 19h, 29min, 59s)), // 1948 1952 O Su>=28 3:30s 0 -305 "[1948-10-30 19:30:00, 1949-04-02 19:30:00) 08:00:00 0min HKT",306 tz->get_info(to_sys_seconds(1948y, std::chrono::October, 30d, 19h, 30min)), // 1948 1952 O Su>=28 3:30s 0 -307 tz->get_info(to_sys_seconds(1949y, std::chrono::April, 2d, 19h, 29min, 59s))); // 1949 1953 Ap Su>=1 3:30 1 S308 309 assert_cycle( // 8 HK%sT310 "[1949-04-02 19:30:00, 1949-10-29 19:30:00) 09:00:00 60min HKST",311 tz->get_info(to_sys_seconds(1949y, std::chrono::April, 2d, 19h, 30min)), // 1949 1953 Ap Su>=1 3:30 1 S312 tz->get_info(to_sys_seconds(1949y, std::chrono::October, 29d, 19h, 29min, 59s)), // 1948 1952 O Su>=28 3:30s 0313 "[1949-10-29 19:30:00, 1950-04-01 19:30:00) 08:00:00 0min HKT",314 tz->get_info(to_sys_seconds(1949y, std::chrono::October, 29d, 19h, 30min)), // 1948 1952 O Su>=28 3:30s 0315 tz->get_info(to_sys_seconds(1950y, std::chrono::April, 1d, 19h, 29min, 59s))); // 1949 1953 Ap Su>=1 3:30 1 S316 317 assert_range(318 "[1953-10-31 18:30:00, 1954-03-20 19:30:00) 08:00:00 0min HKT",319 tz->get_info(to_sys_seconds(1953y, std::chrono::October, 31d, 18h, 30min)), // 1953 1964 - O Su>=31 3:30 0 -320 tz->get_info(to_sys_seconds(1954y, std::chrono::March, 20d, 19h, 29min, 59s))); // 1954 1964 - Mar Su>=18 3:30 1 S321 322 assert_cycle( // 8 HK%sT323 "[1953-04-04 19:30:00, 1953-10-31 18:30:00) 09:00:00 60min HKST",324 tz->get_info(to_sys_seconds(1953y, std::chrono::April, 4d, 19h, 30min)), // 1949 1953 Ap Su>=1 3:30 1 S325 tz->get_info(to_sys_seconds(1953y, std::chrono::October, 31d, 18h, 29min, 59s)), // 1953 1964 - O Su>=31 3:30 0 -326 "[1953-10-31 18:30:00, 1954-03-20 19:30:00) 08:00:00 0min HKT",327 tz->get_info(to_sys_seconds(1953y, std::chrono::October, 31d, 18h, 30min)), // 1953 1964 - O Su>=31 3:30 0 -328 tz->get_info(to_sys_seconds(1954y, std::chrono::March, 20d, 19h, 29min, 59s))); // 1954 1964 - Mar Su>=18 3:30 1 S329 330 assert_cycle( // 8 HK%sT331 "[1972-04-15 19:30:00, 1972-10-21 18:30:00) 09:00:00 60min HKST",332 tz->get_info(to_sys_seconds(1972y, std::chrono::April, 19d, 19h, 30min)), // 1965 1976 - Ap Su>=16 3:30 1 S333 tz->get_info(to_sys_seconds(1972y, std::chrono::October, 21d, 18h, 29min, 59s)), // 1965 1976 - O Su>=16 3:30 0 -334 "[1972-10-21 18:30:00, 1973-04-21 19:30:00) 08:00:00 0min HKT",335 tz->get_info(to_sys_seconds(1972y, std::chrono::October, 21d, 18h, 30min)), // 1965 1976 - O Su>=16 3:30 0 -336 tz->get_info(to_sys_seconds(1973y, std::chrono::April, 21d, 19h, 29min, 59s))); // 1965 1976 - Ap Su>=16 3:30 1 S337 338 assert_range( // 8 HK%sT339 "[1973-04-21 19:30:00, 1973-10-20 18:30:00) 09:00:00 60min HKST",340 tz->get_info(to_sys_seconds(1973y, std::chrono::April, 21d, 19h, 30min)), // 1965 1976 - Ap Su>=16 3:30 1 S341 tz->get_info(to_sys_seconds(1973y, std::chrono::October, 20d, 18h, 29min, 59s))); // 1965 1976 - O Su>=16 3:30 0 -342 343 assert_range( // 8 HK%sT, test "1973 o - D 30 3:30 1 S"344 "[1973-10-20 18:30:00, 1973-12-29 19:30:00) 08:00:00 0min HKT",345 tz->get_info(to_sys_seconds(1973y, std::chrono::October, 20d, 18h, 30min)), // 1965 1976 - O Su>=16 3:30346 tz->get_info(to_sys_seconds(1973y, std::chrono::December, 29d, 19h, 29min, 59s))); // 1973 o - D 30 3:30 1 S347 348 assert_range( // 8 HK%sT349 "[1973-12-29 19:30:00, 1974-10-19 18:30:00) 09:00:00 60min HKST",350 tz->get_info(to_sys_seconds(1973y, std::chrono::December, 29d, 19h, 30min)), // 1973 o - D 30 3:30 1 S351 tz->get_info(to_sys_seconds(1974y, std::chrono::October, 19d, 18h, 29min, 59s))); // 1965 1976 - O Su>=16 3:30352 353 assert_range( // 8 HK%sT, between 1973 and 1979 no rule is active so falls back to default354 "[1976-04-17 19:30:00, 1976-10-16 18:30:00) 09:00:00 60min HKST",355 tz->get_info(to_sys_seconds(1976y, std::chrono::April, 17d, 19h, 30min)), // 1965 1976 - Ap Su>=16 3:30 1 S356 tz->get_info(to_sys_seconds(1976y, std::chrono::October, 16d, 18h, 29min, 59s))); // 1965 1976 - O Su>=16 3:30 0 -357 358 assert_range( // 8 HK%sT, between 1973 and 1979 no rule is active so falls back to default359 "[1976-10-16 18:30:00, 1979-05-12 19:30:00) 08:00:00 0min HKT",360 tz->get_info(to_sys_seconds(1976y, std::chrono::October, 16d, 18h, 30min)), // 1965 1976 - O Su>=16 3:30 0 -361 tz->get_info(to_sys_seconds(1979y, std::chrono::May, 12d, 19h, 29min, 59s))); // 1979 o - May 13 3:30 1 S362 363 assert_range( // 8 HK%sT364 "[1979-05-12 19:30:00, 1979-10-20 18:30:00) 09:00:00 60min HKST",365 tz->get_info(to_sys_seconds(1979y, std::chrono::May, 12d, 19h, 30min)), // 1979 o - May 13 3:30 1 S366 tz->get_info(to_sys_seconds(1979y, std::chrono::October, 20d, 18h, 29min, 59s))); // 1979 o - O 21 3:30 0 -367 368 assert_equal(369 std::chrono::sys_info(370 to_sys_seconds(1979y, std::chrono::October, 20d, 18h, 30min),371 std::chrono::sys_seconds::max(),372 8h,373 std::chrono::minutes(0),374 "HKT"),375 tz->get_info(to_sys_seconds(1979y, std::chrono::October, 20d, 18h, 30min)));376 377 assert_equal(378 std::chrono::sys_info(379 to_sys_seconds(1979y, std::chrono::October, 20d, 18h, 30min),380 std::chrono::sys_seconds::max(),381 8h,382 std::chrono::minutes(0),383 "HKT"),384 tz->get_info(std::chrono::sys_seconds::max() - std::chrono::seconds{1})); // max is not valid385}386 387static void test_europe_berlin() {388 // A more typical entry, first some hard-coded entires and then at the389 // end a rules based entry. This rule is valid for its entire period390 //391 392 // Z Europe/Berlin 0:53:28 - LMT 1893 Ap393 // 1 c CE%sT 1945 May 24 2394 // 1 So CE%sT 1946395 // 1 DE CE%sT 1980396 // 1 E CE%sT397 //398 // R c 1916 o - Ap 30 23 1 S399 // R c 1916 o - O 1 1 0 -400 // R c 1917 1918 - Ap M>=15 2s 1 S401 // R c 1917 1918 - S M>=15 2s 0 -402 // R c 1940 o - Ap 1 2s 1 S403 // R c 1942 o - N 2 2s 0 -404 // R c 1943 o - Mar 29 2s 1 S405 // R c 1943 o - O 4 2s 0 -406 // R c 1944 1945 - Ap M>=1 2s 1 S407 // R c 1944 o - O 2 2s 0 -408 // R c 1945 o - S 16 2s 0 -409 // R c 1977 1980 - Ap Su>=1 2s 1 S410 // R c 1977 o - S lastSu 2s 0 -411 // R c 1978 o - O 1 2s 0 -412 // R c 1979 1995 - S lastSu 2s 0 -413 // R c 1981 ma - Mar lastSu 2s 1 S414 // R c 1996 ma - O lastSu 2s 0 -415 //416 // R So 1945 o - May 24 2 2 M417 // R So 1945 o - S 24 3 1 S418 // R So 1945 o - N 18 2s 0 -419 //420 // R DE 1946 o - Ap 14 2s 1 S421 // R DE 1946 o - O 7 2s 0 -422 // R DE 1947 1949 - O Su>=1 2s 0 -423 // R DE 1947 o - Ap 6 3s 1 S424 // R DE 1947 o - May 11 2s 2 M425 // R DE 1947 o - Jun 29 3 1 S426 // R DE 1948 o - Ap 18 2s 1 S427 // R DE 1949 o - Ap 10 2s 1 S428 //429 // R E 1977 1980 - Ap Su>=1 1u 1 S430 // R E 1977 o - S lastSu 1u 0 -431 // R E 1978 o - O 1 1u 0 -432 // R E 1979 1995 - S lastSu 1u 0 -433 // R E 1981 ma - Mar lastSu 1u 1 S434 // R E 1996 ma - O lastSu 1u 0 -435 //436 // Note the European Union decided to stop the seasonal change in437 // 2021. In 2023 seasonal changes are still in effect.438 439 using namespace std::literals::chrono_literals;440 const std::chrono::time_zone* tz = std::chrono::locate_zone("Europe/Berlin");441 442 assert_equal(443 std::chrono::sys_info(444 std::chrono::sys_seconds::min(),445 to_sys_seconds(1893y, std::chrono::March, 31d, 23h, 6min, 32s), // 0:53:28 - LMT 1893 Ap446 53min + 28s,447 0min,448 "LMT"),449 tz->get_info(std::chrono::sys_seconds::min()));450 451 assert_equal(452 std::chrono::sys_info(453 std::chrono::sys_seconds::min(),454 to_sys_seconds(1893y, std::chrono::March, 31d, 23h, 6min, 32s), // 0:53:28 - LMT 1893 Ap455 53min + 28s,456 0min,457 "LMT"),458 tz->get_info(to_sys_seconds(1893y, std::chrono::March, 31d, 23h, 6min, 31s)));459 460 assert_range(461 // 1 CE%sT before 1916 o - Ap 30 23 1 S462 "[1893-03-31 23:06:32, 1916-04-30 22:00:00) 01:00:00 0min CET",463 tz->get_info(to_sys_seconds(1893y, std::chrono::March, 31d, 23h, 6min, 32s)),464 tz->get_info(to_sys_seconds(1916y, std::chrono::April, 30d, 21h, 59min, 59s)));465 466 assert_cycle(467 // 1 CE%sT468 "[1916-04-30 22:00:00, 1916-09-30 23:00:00) 02:00:00 60min CEST",469 tz->get_info(to_sys_seconds(1916y, std::chrono::April, 30d, 22h)), // 1916 o - Ap 30 23 1 S470 tz->get_info(to_sys_seconds(1916y, std::chrono::September, 30d, 22h, 59min, 59s)), // o - O 1 1 0 -471 "[1916-09-30 23:00:00, 1917-04-16 01:00:00) 01:00:00 0min CET",472 tz->get_info(to_sys_seconds(1916y, std::chrono::September, 30d, 23h)), // o - O 1 1 0 -473 tz->get_info(to_sys_seconds(1917y, std::chrono::April, 16d, 0h, 59min, 59s))); // 1917 1918 - Ap M>=15 2s 1 S474 475 assert_cycle(476 // 1 CE%sT477 "[1917-04-16 01:00:00, 1917-09-17 01:00:00) 02:00:00 60min CEST",478 tz->get_info(to_sys_seconds(1917y, std::chrono::April, 16d, 1h)), // 1917 1918 Ap M>=15 2s 1 S479 tz->get_info(to_sys_seconds(1917y, std::chrono::September, 17d, 0h, 59min, 59s)), // 1917 1918 S M>=15 2s 0 -480 "[1917-09-17 01:00:00, 1918-04-15 01:00:00) 01:00:00 0min CET",481 tz->get_info(to_sys_seconds(1917y, std::chrono::September, 17d, 1h)), // 1917 1918 S M>=15 2s 0 -482 tz->get_info(to_sys_seconds(1918y, std::chrono::April, 15d, 0h, 59min, 59s))); // 1917 1918 Ap M>=15 2s 1 S483 484 assert_cycle(485 // 1 CE%sT (The cycle is more than 1 year)486 "[1918-04-15 01:00:00, 1918-09-16 01:00:00) 02:00:00 60min CEST",487 tz->get_info(to_sys_seconds(1918y, std::chrono::April, 15d, 1h)), // 1917 1918 Ap M>=15 2s 1 S488 tz->get_info(to_sys_seconds(1918y, std::chrono::September, 16d, 0h, 59min, 59s)), // 1917 1918 S M>=15 2s 0 -489 "[1918-09-16 01:00:00, 1940-04-01 01:00:00) 01:00:00 0min CET",490 tz->get_info(to_sys_seconds(1918y, std::chrono::September, 16d, 1h)), // 1917 1918 S M>=15 2s 0 -491 tz->get_info(to_sys_seconds(1940y, std::chrono::April, 1d, 0h, 59min, 59s))); // 1940 o Ap 1 2s 1 S492 493 assert_cycle(494 // 1 CE%sT (The cycle is more than 1 year)495 "[1940-04-01 01:00:00, 1942-11-02 01:00:00) 02:00:00 60min CEST",496 tz->get_info(to_sys_seconds(1940y, std::chrono::April, 1d, 1h)), // 1940 o Ap 1 2s 1 S497 tz->get_info(to_sys_seconds(1942y, std::chrono::November, 2d, 0h, 59min, 59s)), // 1942 o N 2 2s 0 -498 "[1942-11-02 01:00:00, 1943-03-29 01:00:00) 01:00:00 0min CET",499 tz->get_info(to_sys_seconds(1942y, std::chrono::November, 2d, 1h)), // 1942 o N 2 2s 0 -500 tz->get_info(to_sys_seconds(1943y, std::chrono::March, 29d, 0h, 59min, 59s))); // 1943 o Mar 29 2s 1 S501 502 assert_range(503 // Here the zone changes from c (C-Eur) to So (SovietZone).504 // The rule c ends on 1945-09-16, instead it ends at the zone change date/time505 // There is a tricky part in the time506 // "1 c CE%sT" has an offset of 1 at the moment the rule507 // ends there is a save of 60 minutes. This means the508 // local offset to UTC is 2 hours. The rule ends at509 // 1945-05-24 02:00:00 local time, which is510 // 1945-05-24 00:00:00 UTC.511 "[1945-04-02 01:00:00, 1945-05-24 00:00:00) 02:00:00 60min CEST",512 tz->get_info(to_sys_seconds(1945y, std::chrono::April, 2d, 1h)), // 1 CE%sT & 1945 Ap M>=1 2s 1 S513 tz->get_info(to_sys_seconds(1945y, std::chrono::May, 23d, 23h, 59min, 59s))); // 1 c CE%sT & 1945 May 24 2514 515 assert_range( // --516 "[1945-05-24 00:00:00, 1945-09-24 00:00:00) 03:00:00 120min CEMT",517 tz->get_info(to_sys_seconds(1945y, std::chrono::May, 24d)), // 1 c CE%sT & 1945 May 24 2518 tz->get_info(to_sys_seconds(1945y, std::chrono::September, 23d, 23h, 59min, 59s))); // 1945 o S 24 3 1 S519 520 assert_range(521 // 1 c CE%sT 1945 May 24 2522 "[1945-09-24 00:00:00, 1945-11-18 01:00:00) 02:00:00 60min CEST",523 tz->get_info(to_sys_seconds(1945y, std::chrono::September, 24d)), // 1945 o S 24 3 1 S524 tz->get_info(to_sys_seconds(1945y, std::chrono::November, 18d, 0h, 59min, 59s))); // 1945 o N 18 2s 0 -525 assert_range( // --526 // Merges 2 continuations527 "[1945-11-18 01:00:00, 1946-04-14 01:00:00) 01:00:00 0min CET",528 tz->get_info(to_sys_seconds(1945y, std::chrono::November, 18d, 1h)), // 1 c CE%sT & 1945 o N 18 2s 0 -529 tz->get_info(to_sys_seconds(1946y, std::chrono::April, 14d, 0h, 59min, 59s))); // 1 So CE%sT & 1946 o Ap 14 2s 1 S530 531 assert_range(532 // 1 DE CE%sT 1980533 "[1946-04-14 01:00:00, 1946-10-07 01:00:00) 02:00:00 60min CEST",534 tz->get_info(to_sys_seconds(1946y, std::chrono::April, 14d, 1h)), // 1946 o Ap 14 2s 1 S535 tz->get_info(to_sys_seconds(1946y, std::chrono::October, 7d, 0h, 59min, 59s))); // 1946 o O 7 2s 0 -536 537 // Note 1947 is an interesting year with 4 rules538 // R DE 1947 1949 - O Su>=1 2s 0 -539 // R DE 1947 o - Ap 6 3s 1 S540 // R DE 1947 o - May 11 2s 2 M541 // R DE 1947 o - Jun 29 3 1 S542 assert_range(543 // 1 DE CE%sT 1980544 "[1946-10-07 01:00:00, 1947-04-06 02:00:00) 01:00:00 0min CET",545 tz->get_info(to_sys_seconds(1946y, std::chrono::October, 7d, 1h)), // 1946 o O 7 2s 0 -546 tz->get_info(to_sys_seconds(1947y, std::chrono::April, 6d, 1h, 59min, 59s))); // 1947 o Ap 6 3s 1 S547 548 assert_range(549 // 1 DE CE%sT 1980550 "[1947-04-06 02:00:00, 1947-05-11 01:00:00) 02:00:00 60min CEST",551 tz->get_info(to_sys_seconds(1947y, std::chrono::April, 6d, 2h)), // 1947 o Ap 6 3s 1 S552 tz->get_info(to_sys_seconds(1947y, std::chrono::May, 11d, 0h, 59min, 59s))); // 1947 o May 11 2s 2 M553 554 assert_range(555 // 1 DE CE%sT 1980556 "[1947-05-11 01:00:00, 1947-06-29 00:00:00) 03:00:00 120min CEMT",557 tz->get_info(to_sys_seconds(1947y, std::chrono::May, 11d, 1h)), // 1947 o May 11 2s 2 M558 tz->get_info(to_sys_seconds(1947y, std::chrono::June, 28d, 23h, 59min, 59s))); // 1947 o Jun 29 3 1 S559 560 assert_cycle(561 // 1 DE CE%sT 1980562 "[1947-06-29 00:00:00, 1947-10-05 01:00:00) 02:00:00 60min CEST",563 tz->get_info(to_sys_seconds(1947y, std::chrono::June, 29d)), // 1947 o Jun 29 3 1 S564 tz->get_info(to_sys_seconds(1947y, std::chrono::October, 5d, 0h, 59min, 59s)), // 1947 1949 O Su>=1 2s 0 -565 "[1947-10-05 01:00:00, 1948-04-18 01:00:00) 01:00:00 0min CET",566 tz->get_info(to_sys_seconds(1947y, std::chrono::October, 5d, 1h)), // 1947 1949 O Su>=1 2s 0 -567 tz->get_info(to_sys_seconds(1948y, std::chrono::April, 18d, 0h, 59min, 59s))); // 1948 o Ap 18 2s 1 S568 569 assert_cycle(570 // 1 DE CE%sT 1980571 "[1948-04-18 01:00:00, 1948-10-03 01:00:00) 02:00:00 60min CEST",572 tz->get_info(to_sys_seconds(1948y, std::chrono::April, 18d, 1h)), // 1948 o Ap 18 2s 1 S573 tz->get_info(to_sys_seconds(1948y, std::chrono::October, 3d, 0h, 59min, 59s)), // 1947 1949 O Su>=1 2s 0 -574 "[1948-10-03 01:00:00, 1949-04-10 01:00:00) 01:00:00 0min CET",575 tz->get_info(to_sys_seconds(1948y, std::chrono::October, 3d, 1h)), // 1947 1949 O Su>=1 2s 0 -576 tz->get_info(to_sys_seconds(1949y, std::chrono::April, 10d, 0h, 59min, 59s))); // 1949 o Ap 10 2s 1 S577 578 assert_cycle( // Note the end time is in a different continuation.579 "[1949-04-10 01:00:00, 1949-10-02 01:00:00) 02:00:00 60min CEST", // 1 DE CE%sT 1980580 tz->get_info(to_sys_seconds(1949y, std::chrono::April, 10d, 1h)), // 1949 o Ap 10 2s 1 S581 tz->get_info(to_sys_seconds(1949y, std::chrono::October, 2d, 0h, 59min, 59s)), // 1947 1949 O Su>=1 2s 0 -582 "[1949-10-02 01:00:00, 1980-04-06 01:00:00) 01:00:00 0min CET",583 tz->get_info(to_sys_seconds(1949y, std::chrono::October, 2d, 1h)), // 1947 1949 O Su>=1 2s 0 -584 tz->get_info( // 1 E CE%sT585 to_sys_seconds(1980y, std::chrono::April, 6d, 0h, 59min, 59s))); // 1977 1980 Ap Su>=1 1u 1 S586 587 assert_cycle(588 // 1 E CE%sT589 "[2020-03-29 01:00:00, 2020-10-25 01:00:00) 02:00:00 60min CEST",590 tz->get_info(to_sys_seconds(2020y, std::chrono::March, 29d, 1h)), // 1981 ma Mar lastSu 1u 1 S591 tz->get_info(to_sys_seconds(2020y, std::chrono::October, 25d, 0h, 59min, 59s)), // 1996 ma O lastSu 1u 0 -592 "[2020-10-25 01:00:00, 2021-03-28 01:00:00) 01:00:00 0min CET",593 tz->get_info(to_sys_seconds(2020y, std::chrono::October, 25d, 1h)), // 1996 ma O lastSu 1u 0 -594 tz->get_info(to_sys_seconds(2021y, std::chrono::March, 28d, 0h, 59min, 59s))); // 1981 ma Mar lastSu 1u 1 S595 596 assert_cycle(597 // 1 E CE%sT598 "[2021-03-28 01:00:00, 2021-10-31 01:00:00) 02:00:00 60min CEST",599 tz->get_info(to_sys_seconds(2021y, std::chrono::March, 28d, 1h)), // 1981 ma Mar lastSu 1u 1 S600 tz->get_info(to_sys_seconds(2021y, std::chrono::October, 31d, 0h, 59min, 59s)), // 1996 ma O lastSu 1u 0 -601 "[2021-10-31 01:00:00, 2022-03-27 01:00:00) 01:00:00 0min CET",602 tz->get_info(to_sys_seconds(2021y, std::chrono::October, 31d, 1h)), // 1996 ma O lastSu 1u 0 -603 tz->get_info(to_sys_seconds(2022y, std::chrono::March, 27d, 0h, 59min, 59s))); // 1981 ma Mar lastSu 1u 1 S604}605 606static void test_america_st_johns() {607 // A more typical entry,608 // Uses letters both when DST is active and not and has multiple609 // letters. Uses negative offsets.610 // Switches several times between their own and Canadian rules611 // Switches the stdoff from -3:30:52 to -3:30 while observing the same rule612 613 // Z America/St_Johns -3:30:52 - LMT 1884614 // -3:30:52 j N%sT 1918615 // -3:30:52 C N%sT 1919616 // -3:30:52 j N%sT 1935 Mar 30617 // -3:30 j N%sT 1942 May 11618 // -3:30 C N%sT 1946619 // -3:30 j N%sT 2011 N620 // -3:30 C N%sT621 //622 // R j 1917 o - Ap 8 2 1 D623 // R j 1917 o - S 17 2 0 S624 // R j 1919 o - May 5 23 1 D625 // R j 1919 o - Au 12 23 0 S626 // R j 1920 1935 - May Su>=1 23 1 D627 // R j 1920 1935 - O lastSu 23 0 S628 // R j 1936 1941 - May M>=9 0 1 D629 // R j 1936 1941 - O M>=2 0 0 S630 // R j 1946 1950 - May Su>=8 2 1 D631 // R j 1946 1950 - O Su>=2 2 0 S632 // R j 1951 1986 - Ap lastSu 2 1 D633 // R j 1951 1959 - S lastSu 2 0 S634 // R j 1960 1986 - O lastSu 2 0 S635 // R j 1987 o - Ap Su>=1 0:1 1 D636 // R j 1987 2006 - O lastSu 0:1 0 S637 // R j 1988 o - Ap Su>=1 0:1 2 DD638 // R j 1989 2006 - Ap Su>=1 0:1 1 D639 // R j 2007 2011 - Mar Su>=8 0:1 1 D640 // R j 2007 2010 - N Su>=1 0:1 0 S641 //642 // R C 1918 o - Ap 14 2 1 D643 // R C 1918 o - O 27 2 0 S644 // R C 1942 o - F 9 2 1 W645 // R C 1945 o - Au 14 23u 1 P646 // R C 1945 o - S 30 2 0 S647 // R C 1974 1986 - Ap lastSu 2 1 D648 // R C 1974 2006 - O lastSu 2 0 S649 // R C 1987 2006 - Ap Su>=1 2 1 D650 // R C 2007 ma - Mar Su>=8 2 1 D651 // R C 2007 ma - N Su>=1 2 0 S652 653 using namespace std::literals::chrono_literals;654 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/St_Johns");655 656 assert_equal( // --657 std::chrono::sys_info(658 std::chrono::sys_seconds::min(),659 to_sys_seconds(1884y, std::chrono::January, 1d, 3h, 30min, 52s), // -3:30:52 - LMT 1884660 -(3h + 30min + 52s),661 0min,662 "LMT"),663 tz->get_info(std::chrono::sys_seconds::min()));664 665 assert_equal( // --666 std::chrono::sys_info(667 std::chrono::sys_seconds::min(),668 to_sys_seconds(1884y, std::chrono::January, 1d, 3h, 30min, 52s), // -3:30:52 - LMT 1884669 -(3h + 30min + 52s),670 0min,671 "LMT"),672 tz->get_info(to_sys_seconds(1884y, std::chrono::January, 1d, 3h, 30min, 51s)));673 674 assert_range( // -3:30:52 j N%sT 1918675 "[1884-01-01 03:30:52, 1917-04-08 05:30:52) -03:30:52 0min NST",676 tz->get_info(to_sys_seconds(1884y, std::chrono::January, 1d, 3h, 30min, 52s)), // no rule active677 tz->get_info(to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 51s))); // 1917 o Ap 8 2 1 D678 679 assert_range( // -3:30:52 j N%sT 1918680 "[1917-04-08 05:30:52, 1917-09-17 04:30:52) -02:30:52 60min NDT",681 tz->get_info(to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s)), // 1917 o Ap 8 2 1 D682 tz->get_info(to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 51s))); // 1917 o S 17 2 0 S683 684 assert_range("[1917-09-17 04:30:52, 1918-04-14 05:30:52) -03:30:52 0min NST",685 tz->get_info( // -3:30:52 j N%sT 1918686 to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 52s)), // 1917 o S 17 2 0 S687 tz->get_info( // -3:30:52 C N%sT 1919688 to_sys_seconds(1918y, std::chrono::April, 14d, 5h, 30min, 51s))); // 1918 o Ap 14 2 1 D689 690 assert_range( // -3:30:52 C N%sT 1919691 "[1918-04-14 05:30:52, 1918-10-27 04:30:52) -02:30:52 60min NDT",692 tz->get_info(to_sys_seconds(1918y, std::chrono::April, 14d, 5h, 30min, 52s)), // 1918 o Ap 14 2 1 D693 tz->get_info(to_sys_seconds(1918y, std::chrono::October, 27d, 4h, 30min, 51s))); // 1918 o O 27 2 0 S694 695 assert_range("[1918-10-27 04:30:52, 1919-05-06 02:30:52) -03:30:52 0min NST",696 tz->get_info( // -3:30:52 C N%sT 1919697 to_sys_seconds(1918y, std::chrono::October, 27d, 4h, 30min, 52s)), // 1918 o O 27 2 0 S698 tz->get_info( // -3:30:52 j N%sT 1935 Mar 30699 to_sys_seconds(1919y, std::chrono::May, 6d, 2h, 30min, 51s))); // 1919 o May 5 23 1 D700 701 assert_range( // -3:30:52 j N%sT 1935 Mar 30702 "[1934-10-29 01:30:52, 1935-03-30 03:30:52) -03:30:52 0min NST",703 tz->get_info(to_sys_seconds(1934y, std::chrono::October, 29d, 1h, 30min, 52s)), // 1920 1935 O lastSu 23 0 S704 tz->get_info(to_sys_seconds(1935y, std::chrono::March, 30d, 3h, 30min, 51s))); // 1920 1935 May Su>=1 23 1 D705 706 assert_range( // -3:30 j N%sT 1942 May 11707 // Changed the stdoff while the same rule remains active.708 "[1935-03-30 03:30:52, 1935-05-06 02:30:00) -03:30:00 0min NST",709 tz->get_info(to_sys_seconds(1935y, std::chrono::March, 30d, 3h, 30min, 52s)), // 1920 1935 O lastSu 23 0 S710 tz->get_info(to_sys_seconds(1935y, std::chrono::May, 6d, 2h, 29min, 59s))); // 1920 1935 May Su>=1 23 1 D711 712 assert_range( // -3:30 j N%sT 1942 May 11713 "[1935-05-06 02:30:00, 1935-10-28 01:30:00) -02:30:00 60min NDT",714 tz->get_info(to_sys_seconds(1935y, std::chrono::May, 6d, 2h, 30min, 0s)), // 1920 1935 May Su>=1 23 1 D715 tz->get_info(to_sys_seconds(1935y, std::chrono::October, 28d, 1h, 29min, 59s))); // 1920 1935 O lastSu 23 0 S716 717 assert_range( // -3:30 j N%sT 1942 May 11718 "[1941-10-06 02:30:00, 1942-05-11 03:30:00) -03:30:00 0min NST",719 tz->get_info(to_sys_seconds(1941y, std::chrono::October, 6d, 2h, 30min, 0s)), // 1936 1941 O M>=2 0 0 S720 tz->get_info(to_sys_seconds(1942y, std::chrono::May, 11d, 3h, 29min, 59s))); // 1946 1950 May Su>=8 2 1 D721 722 assert_range( // -3:30 C N%sT 1946723 "[1942-05-11 03:30:00, 1945-08-14 23:00:00) -02:30:00 60min NWT",724 tz->get_info(to_sys_seconds(1942y, std::chrono::May, 11d, 3h, 30min, 0s)), // 1942 o F 9 2 1 W725 tz->get_info(to_sys_seconds(1945y, std::chrono::August, 14d, 22h, 59min, 59s))); // 1945 o Au 14 23u 1 P726 727 assert_range( // -3:30 C N%sT 1946728 "[1945-08-14 23:00:00, 1945-09-30 04:30:00) -02:30:00 60min NPT",729 tz->get_info(to_sys_seconds(1945y, std::chrono::August, 14d, 23h, 0min, 0s)), // 1945 o Au 14 23u 1 P730 tz->get_info(to_sys_seconds(1945y, std::chrono::September, 30d, 4h, 29min, 59s))); // 1945 o S 30 2 0 S731 732 assert_range(733 "[1945-09-30 04:30:00, 1946-05-12 05:30:00) -03:30:00 0min NST",734 tz->get_info(735 to_sys_seconds(1945y, std::chrono::September, 30d, 4h, 30min, 0s)), // -3:30 C N%sT 1946 & 945 o S 30 2 0 S736 tz->get_info(to_sys_seconds(737 1946y, std::chrono::May, 12d, 5h, 29min, 59s))); // -3:30 j N%sT 2011 N & 1946 1950 May Su>=8 2 1 D738 739 assert_range( // -3:30 j N%sT 2011 N740 "[1988-04-03 03:31:00, 1988-10-30 01:31:00) -01:30:00 120min NDDT",741 tz->get_info(to_sys_seconds(1988y, std::chrono::April, 3d, 3h, 31min, 0s)), // 1988 o Ap Su>=1 0:1 2 DD742 tz->get_info(to_sys_seconds(1988y, std::chrono::October, 30d, 1h, 30min, 59s))); // 1987 2006 O lastSu 0:1 0 S743 744 assert_range("[2011-03-13 03:31:00, 2011-11-06 04:30:00) -02:30:00 60min NDT",745 tz->get_info( // -3:30 j N%sT 2011 N746 to_sys_seconds(2011y, std::chrono::March, 13d, 3h, 31min, 0s)), // 2007 2011 Mar Su>=8 0:1 1 D747 tz->get_info( // -3:30 C N%sT748 to_sys_seconds(2011y, std::chrono::November, 6d, 04h, 29min, 59s))); // 2007 ma N Su>=1 2 0 S749}750 751static void test_get_at_standard_time_universal() {752 // Z Asia/Barnaul 5:35 - LMT 1919 D 10753 // ...754 // 7 R +07/+08 1995 May 28755 // 6 R +06/+07 2011 Mar 27 2s756 // ...757 //758 // ...759 // R R 1985 2010 - Mar lastSu 2s 1 S760 // R R 1996 2010 - O lastSu 2s 0 -761 762 using namespace std::literals::chrono_literals;763 const std::chrono::time_zone* tz = std::chrono::locate_zone("Asia/Barnaul");764 765 assert_equal(766 std::chrono::sys_info(767 to_sys_seconds(2010y, std::chrono::October, 30d, 20h),768 to_sys_seconds(2011y, std::chrono::March, 26d, 20h),769 6h,770 0min,771 "+06"),772 tz->get_info(to_sys_seconds(2010y, std::chrono::October, 31d, 10h)));773}774 775static void test_get_at_standard_time_standard() {776 // Z Africa/Bissau -1:2:20 - LMT 1912 Ja 1 1u777 using namespace std::literals::chrono_literals;778 const std::chrono::time_zone* tz = std::chrono::locate_zone("Africa/Bissau");779 780 assert_equal(781 std::chrono::sys_info(782 std::chrono::sys_seconds::min(),783 to_sys_seconds(1912y, std::chrono::January, 1d, 1h),784 -(1h + 2min + 20s),785 0min,786 "LMT"),787 tz->get_info(std::chrono::sys_seconds::min()));788}789 790static void test_get_at_save_universal() {791 // Z America/Tijuana -7:48:4 - LMT 1922 Ja 1 0:11:56792 // -7 - MST 1924793 // -8 - PST 1927 Jun 10 23794 // -7 - MST 1930 N 15795 // -8 - PST 1931 Ap796 // -8 1 PDT 1931 S 30797 // -8 - PST 1942 Ap 24798 // -8 1 PWT 1945 Au 14 23u799 // ...800 801 using namespace std::literals::chrono_literals;802 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Tijuana");803 804 assert_equal(805 std::chrono::sys_info(806 to_sys_seconds(1942y, std::chrono::April, 24d, 8h),807 to_sys_seconds(1945y, std::chrono::August, 14d, 23h),808 -7h,809 60min,810 "PWT"),811 tz->get_info(to_sys_seconds(1942y, std::chrono::April, 24d, 8h)));812}813 814static void test_get_at_rule_standard() {815 // Z Antarctica/Macquarie 0 - -00 1899 N816 // 10 - AEST 1916 O 1 2817 // 10 1 AEDT 1917 F818 // 10 AU AE%sT 1919 Ap 1 0s819 // ...820 //821 // R AU 1917 o - Ja 1 2s 1 D822 // R AU 1917 o - Mar lastSu 2s 0 S823 // R AU 1942 o - Ja 1 2s 1 D824 // ...825 826 using namespace std::literals::chrono_literals;827 const std::chrono::time_zone* tz = std::chrono::locate_zone("Antarctica/Macquarie");828 829 // Another rule where the S propagates?830 assert_equal(831 std::chrono::sys_info(832 to_sys_seconds(1916y, std::chrono::September, 30d, 16h),833 to_sys_seconds(1917y, std::chrono::March, 24d, 16h),834 11h,835 60min,836 "AEDT"),837 tz->get_info(to_sys_seconds(1916y, std::chrono::September, 30d, 16h)));838}839 840static void test_get_at_rule_universal() {841 // Z America/Nuuk -3:26:56 - LMT 1916 Jul 28842 // -3 - -03 1980 Ap 6 2843 // -3 E -03/-02 2023 O 29 1u844 // -2 E -02/-01845 //846 // R E 1977 1980 - Ap Su>=1 1u 1 S847 // R E 1977 o - S lastSu 1u 0 -848 // R E 1978 o - O 1 1u 0 -849 // R E 1979 1995 - S lastSu 1u 0 -850 // R E 1981 ma - Mar lastSu 1u 1 S851 // R E 1996 ma - O lastSu 1u 0 -852 853 using namespace std::literals::chrono_literals;854 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Nuuk");855 856 assert_equal(857 std::chrono::sys_info(858 to_sys_seconds(1980y, std::chrono::April, 6d, 5h),859 to_sys_seconds(1980y, std::chrono::September, 28d, 1h),860 -2h,861 60min,862 "-02"),863 tz->get_info(to_sys_seconds(1980y, std::chrono::April, 6d, 5h)));864}865 866static void test_format_with_alternatives_west() {867 // Z America/Nuuk -3:26:56 - LMT 1916 Jul 28868 // -3 - -03 1980 Ap 6 2869 // -3 E -03/-02 2023 O 29 1u870 // -2 E -02/-01871 //872 // ...873 // R E 1981 ma - Mar lastSu 1u 1 S874 // R E 1996 ma - O lastSu 1u 0 -875 876 using namespace std::literals::chrono_literals;877 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Nuuk");878 879 assert_cycle( // -3 E -03/-02880 "[2019-10-27 01:00:00, 2020-03-29 01:00:00) -03:00:00 0min -03",881 tz->get_info(to_sys_seconds(2019y, std::chrono::October, 27d, 1h)), // 1981 ma Mar lastSu 1u 1 S882 tz->get_info(to_sys_seconds(2020y, std::chrono::March, 29d, 0h, 59min, 59s)), // 1996 ma O lastSu 1u 0 -883 "[2020-03-29 01:00:00, 2020-10-25 01:00:00) -02:00:00 60min -02",884 tz->get_info(to_sys_seconds(2020y, std::chrono::March, 29d, 1h)), // 1996 ma O lastSu 1u 0 -885 tz->get_info(to_sys_seconds(2020y, std::chrono::October, 25d, 0h, 59min, 59s))); // 1981 ma Mar lastSu 1u 1 S886}887 888static void test_format_with_alternatives_east() {889 // Z Asia/Barnaul 5:35 - LMT 1919 D 10890 // ...891 // 6 R +06/+07 2011 Mar 27 2s892 // ...893 //894 // ...895 // R R 1985 2010 - Mar lastSu 2s 1 S896 // R R 1996 2010 - O lastSu 2s 0 -897 898 using namespace std::literals::chrono_literals;899 const std::chrono::time_zone* tz = std::chrono::locate_zone("Asia/Barnaul");900 901 assert_cycle( // 6 R +06/+07 2011 Mar 27 2s902 "[2000-03-25 20:00:00, 2000-10-28 20:00:00) 07:00:00 60min +07",903 tz->get_info(to_sys_seconds(2000y, std::chrono::March, 25d, 20h)), // 1985 2010 Mar lastSu 2s 1 S904 tz->get_info(to_sys_seconds(2000y, std::chrono::October, 28d, 19h, 59min, 59s)), // 1996 2010 O lastSu 2s 0 -905 "[2000-10-28 20:00:00, 2001-03-24 20:00:00) 06:00:00 0min +06",906 tz->get_info(to_sys_seconds(2000y, std::chrono::October, 28d, 20h)), // 1996 2010 O lastSu 2s 0 -907 tz->get_info(to_sys_seconds(2001y, std::chrono::March, 24d, 19h, 59min, 59s))); // 1985 2010 Mar lastSu 2s 1 S908}909 910static void test_africa_algiers() {911 using namespace std::literals::chrono_literals;912 const std::chrono::time_zone* tz = std::chrono::locate_zone("Africa/Algiers");913 914 assert_equal(915 std::chrono::sys_info(916 to_sys_seconds(1977y, std::chrono::October, 20d, 23h),917 to_sys_seconds(1978y, std::chrono::March, 24d),918 1h,919 std::chrono::minutes(0),920 "CET"),921 tz->get_info(to_sys_seconds(1977y, std::chrono::October, 20d, 23h)));922 923 assert_range("[1977-05-06 00:00:00, 1977-10-20 23:00:00) 01:00:00 60min WEST", // 0 d WE%sT 1977 O 21924 tz->get_info(to_sys_seconds(1977y, std::chrono::May, 6d)),925 tz->get_info(to_sys_seconds(1977y, std::chrono::October, 20d, 22h, 59min, 59s)));926 927 assert_range("[1977-10-20 23:00:00, 1978-03-24 00:00:00) 01:00:00 0min CET", // 1 d CE%sT 1979 O 26928 tz->get_info(to_sys_seconds(1977y, std::chrono::October, 20d, 23h)),929 tz->get_info(to_sys_seconds(1978y, std::chrono::March, 23d, 23h, 59min, 59s)));930}931 932static void test_africa_casablanca() {933 // Z Africa/Casablanca -0:30:20 - LMT 1913 O 26934 // 0 M +00/+01 1984 Mar 16935 // 1 - +01 1986936 // 0 M +00/+01 2018 O 28 3937 // 1 M +01/+00938 //939 // ...940 // R M 2013 2018 - O lastSu 3 0 -941 // R M 2014 2018 - Mar lastSu 2 1 -942 // R M 2014 o - Jun 28 3 0 -943 // R M 2014 o - Au 2 2 1 -944 // R M 2015 o - Jun 14 3 0 -945 // R M 2015 o - Jul 19 2 1 -946 // R M 2016 o - Jun 5 3 0 -947 // R M 2016 o - Jul 10 2 1 -948 // R M 2017 o - May 21 3 0 -949 // R M 2017 o - Jul 2 2 1 -950 // R M 2018 o - May 13 3 0 -951 // R M 2018 o - Jun 17 2 1 -952 // R M 2019 o - May 5 3 -1 -953 // R M 2019 o - Jun 9 2 0 -954 // R M 2020 o - Ap 19 3 -1 -955 // ...956 957 using namespace std::literals::chrono_literals;958 const std::chrono::time_zone* tz = std::chrono::locate_zone("Africa/Casablanca");959 960 assert_range("[2018-06-17 02:00:00, 2018-10-28 02:00:00) 01:00:00 60min +01",961 tz->get_info(to_sys_seconds(2018y, std::chrono::June, 17d, 2h)),962 tz->get_info(to_sys_seconds(2018y, std::chrono::October, 28d, 1h, 59min, 59s)));963 964 assert_range("[2018-10-28 02:00:00, 2019-05-05 02:00:00) 01:00:00 0min +01",965 tz->get_info( // 1 M +01/+00 & R M 2018 o - Jun 17 2 1 -966 to_sys_seconds(2018y, std::chrono::October, 28d, 2h)),967 tz->get_info( // 1 M +01/+00 & R M 2019 o - May 5 3 -1 -968 to_sys_seconds(2019y, std::chrono::May, 5d, 1h, 59min, 59s)));969 970 // 1 M +01/+00971 // Note the SAVE contains a negative value972 assert_range("[2019-05-05 02:00:00, 2019-06-09 02:00:00) 00:00:00 -60min +00",973 tz->get_info(to_sys_seconds(2019y, std::chrono::May, 5d, 2h)), // R M 2019 o - May 5 3 -1 -974 tz->get_info(to_sys_seconds(2019y, std::chrono::June, 9d, 1h, 59min, 59s))); // R M 2019 o - Jun 9 2 0 -975 976 assert_range("[2019-06-09 02:00:00, 2020-04-19 02:00:00) 01:00:00 0min +01",977 tz->get_info( // 1 M +01/+00 & R M 2019 o - Jun 9 2 0 -978 to_sys_seconds(2019y, std::chrono::June, 9d, 2h)),979 tz->get_info( // 1 M +01/+00 & R M 2020 o - Ap 19 3 -1 -980 to_sys_seconds(2020y, std::chrono::April, 19d, 1h, 59min, 59s))); //981}982 983static void test_africa_ceuta() {984 // Z Africa/Ceuta -0:21:16 - LMT 1900 D 31 23:38:44985 // 0 - WET 1918 May 6 23986 // 0 1 WEST 1918 O 7 23987 // 0 - WET 1924988 // 0 s WE%sT 1929989 // 0 - WET 1967990 // 0 Sp WE%sT 1984 Mar 16991 // 1 - CET 1986992 // 1 E CE%sT993 //994 // ...995 // R s 1926 o - Ap 17 23 1 S996 // R s 1926 1929 - O Sa>=1 24s 0 -997 // R s 1927 o - Ap 9 23 1 S998 // R s 1928 o - Ap 15 0 1 S999 // R s 1929 o - Ap 20 23 1 S1000 // R s 1937 o - Jun 16 23 1 S1001 // ...1002 //1003 // R Sp 1967 o - Jun 3 12 1 S1004 // R Sp 1967 o - O 1 0 0 -1005 // R Sp 1974 o - Jun 24 0 1 S1006 // R Sp 1974 o - S 1 0 0 -1007 // R Sp 1976 1977 - May 1 0 1 S1008 // R Sp 1976 o - Au 1 0 0 -1009 // R Sp 1977 o - S 28 0 0 -1010 // R Sp 1978 o - Jun 1 0 1 S1011 // R Sp 1978 o - Au 4 0 0 -1012 1013 using namespace std::literals::chrono_literals;1014 const std::chrono::time_zone* tz = std::chrono::locate_zone("Africa/Ceuta");1015 1016 assert_range(1017 1018 "[1928-10-07 00:00:00, 1967-06-03 12:00:00) 00:00:00 0min WET",1019 tz->get_info(to_sys_seconds(1928y, std::chrono::October, 7d)), // 0 s WE%sT 1929 & 1926 1929 O Sa>=1 24s 0 -1020 tz->get_info( // No transitions in "0 - WET 1967"1021 to_sys_seconds(1967y, std::chrono::June, 3d, 11h, 59min, 59s))); // 0 - WET 1967 & 1967 o Jun 3 12 1 S1022}1023 1024static void test_africa_freetown() {1025 // Z Africa/Freetown -0:53 - LMT 18821026 // -0:53 - FMT 1913 Jul1027 // -1 SL %s 1939 S 51028 // -1 - -01 1941 D 6 241029 // 0 - GMT1030 //1031 // R SL 1932 o - D 1 0 0:20 -00401032 // R SL 1933 1938 - Mar 31 24 0 -011033 // R SL 1933 1939 - Au 31 24 0:20 -00401034 // R SL 1939 o - May 31 24 0 -011035 1036 using namespace std::literals::chrono_literals;1037 const std::chrono::time_zone* tz = std::chrono::locate_zone("Africa/Freetown");1038 1039 // When a continuation has a named rule, the transition time determined by1040 // the active rule can be wrong. The next continuation may set the clock to an1041 // earlier time. This is tested for San Luis. This tests the rule is not used1042 // when the rule is not a named rule.1043 //1044 // Fixes:1045 // Expected output [1882-01-01 00:53:00, 1913-07-01 00:53:00) -00:53:00 0min FMT1046 // Actual output [1882-01-01 00:53:00, 1913-07-01 00:46:00) -00:53:00 0min FMT1047 1048 assert_range("[1882-01-01 00:53:00, 1913-07-01 00:53:00) -00:53:00 0min FMT",1049 tz->get_info(to_sys_seconds(1882y, std::chrono::January, 1d, 0h, 53min)), // -0:53 - FMT 1913 Jul1050 tz->get_info( // -1 SL %s 1939 S 5 & before first rule1051 to_sys_seconds(1913y, std::chrono::July, 1d, 0h, 52min, 59s)));1052 1053 // Tests whether the "-1 SL %s 1939 S 5" until gets the proper local time1054 // adjustment.1055 assert_range("[1939-09-01 01:00:00, 1939-09-05 00:40:00) -00:40:00 20min -0040",1056 tz->get_info( // -1 SL %s 1939 S 5 & R SL 1933 1939 - Au 31 24 0:20 -00401057 to_sys_seconds(1939y, std::chrono::September, 1d, 1h)),1058 tz->get_info( // -1 - -01 1941 D 6 241059 to_sys_seconds(1939y, std::chrono::September, 5d, 0h, 39min, 59s)));1060}1061 1062static void test_africa_windhoek() {1063 // Tests the LETTER/S used before the first rule per1064 // https://data.iana.org/time-zones/tz-how-to.html1065 // If switching to a named rule before any transition has happened,1066 // assume standard time (SAVE zero), and use the LETTER data from1067 // the earliest transition with a SAVE of zero.1068 1069 // Z Africa/Windhoek 1:8:24 - LMT 1892 F 81070 // 1:30 - +0130 1903 Mar1071 // 2 - SAST 1942 S 20 21072 // 2 1 SAST 1943 Mar 21 21073 // 2 - SAST 1990 Mar 211074 // 2 NA %s1075 //1076 // R NA 1994 o - Mar 21 0 -1 WAT1077 // R NA 1994 2017 - S Su>=1 2 0 CAT1078 // R NA 1995 2017 - Ap Su>=1 2 -1 WAT1079 1080 using namespace std::literals::chrono_literals;1081 const std::chrono::time_zone* tz = std::chrono::locate_zone("Africa/Windhoek");1082 1083 assert_range( // 2 - EET 2012 N 10 21084 "[1990-03-20 22:00:00, 1994-03-20 22:00:00) 02:00:00 0min CAT",1085 tz->get_info(to_sys_seconds(1990y, std::chrono::March, 20d, 22h)),1086 tz->get_info(to_sys_seconds(1994y, std::chrono::March, 20d, 21h, 59min, 59s)));1087}1088 1089static void test_america_adak() {1090 // Z America/Adak 12:13:22 - LMT 1867 O 19 12:44:351091 // ...1092 // -11 u B%sT 1983 O 30 21093 // -10 u AH%sT 1983 N 301094 // -10 u H%sT1095 //1096 // ...1097 // R u 1945 o - S 30 2 0 S1098 // R u 1967 2006 - O lastSu 2 0 S1099 // R u 1967 1973 - Ap lastSu 2 1 D1100 // R u 1974 o - Ja 6 2 1 D1101 // R u 1975 o - F lastSu 2 1 D1102 // R u 1976 1986 - Ap lastSu 2 1 D1103 // R u 1987 2006 - Ap Su>=1 2 1 D1104 // ...1105 1106 using namespace std::literals::chrono_literals;1107 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Adak");1108 1109 assert_range( // 2 - EET 2012 N 10 21110 "[1983-10-30 12:00:00, 1983-11-30 10:00:00) -10:00:00 0min AHST",1111 tz->get_info(to_sys_seconds(1983y, std::chrono::October, 30d, 12h)), // -11 u B%sT 1983 O 30 21112 tz->get_info(to_sys_seconds(1983y, std::chrono::November, 30d, 9h, 59min, 59s))); // -10 u AH%sT 1983 N 301113}1114 1115static void test_america_auncion() {1116 // R y 2013 ma - Mar Su>=22 0 0 -1117 // Z America/Asuncion -3:50:40 - LMT 18901118 // -3:50:40 - AMT 1931 O 101119 // -4 - -04 1972 O1120 // -3 - -03 1974 Ap1121 // -4 y -04/-031122 //1123 // R y 1975 1988 - O 1 0 1 -1124 // R y 1975 1978 - Mar 1 0 0 -1125 // R y 1979 1991 - Ap 1 0 0 -1126 // ...1127 1128 using namespace std::literals::chrono_literals;1129 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Asuncion");1130 1131 assert_range("[1974-04-01 03:00:00, 1975-10-01 04:00:00) -04:00:00 0min -04",1132 tz->get_info(to_sys_seconds(1974y, std::chrono::April, 1d, 3h)),1133 tz->get_info(to_sys_seconds(1975y, std::chrono::October, 1d, 3h, 59min, 59s)));1134 1135 assert_range("[1975-10-01 04:00:00, 1976-03-01 03:00:00) -03:00:00 60min -03",1136 tz->get_info(to_sys_seconds(1975y, std::chrono::October, 1d, 4h)),1137 tz->get_info(to_sys_seconds(1976y, std::chrono::March, 1d, 2h, 59min, 59s)));1138}1139 1140static void test_america_ciudad_juarez() {1141 // Z America/Ciudad_Juarez -7:5:56 - LMT 1922 Ja 1 7u1142 // -7 - MST 1927 Jun 10 231143 // -6 - CST 1930 N 151144 // -7 m MST 1932 Ap1145 // -6 - CST 19961146 // -6 m C%sT 19981147 // ...1148 //1149 // R m 1939 o - F 5 0 1 D1150 // R m 1939 o - Jun 25 0 0 S1151 // R m 1940 o - D 9 0 1 D1152 // R m 1941 o - Ap 1 0 0 S1153 // R m 1943 o - D 16 0 1 W1154 // R m 1944 o - May 1 0 0 S1155 // R m 1950 o - F 12 0 1 D1156 // R m 1950 o - Jul 30 0 0 S1157 // R m 1996 2000 - Ap Su>=1 2 1 D1158 // R m 1996 2000 - O lastSu 2 0 S1159 // ...1160 1161 using namespace std::literals::chrono_literals;1162 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Ciudad_Juarez");1163 1164 // 1996 has a similar issue, instead of __time the __until end before1165 // the first rule in 1939. Between the two usages of RULE Mexico1166 // a different continuation RULE is active1167 assert_range("[1996-04-07 08:00:00, 1996-10-27 07:00:00) -05:00:00 60min CDT",1168 tz->get_info(to_sys_seconds(1996y, std::chrono::April, 7d, 8h)),1169 tz->get_info(to_sys_seconds(1996y, std::chrono::October, 27d, 6h, 59min, 59s)));1170}1171 1172static void test_america_argentina_buenos_aires() {1173 // Z America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 O 311174 // -4:16:48 - CMT 1920 May1175 // -4 - -04 1930 D1176 // -4 A -04/-03 1969 O 51177 // -3 A -03/-02 1999 O 31178 // -4 A -04/-03 2000 Mar 31179 // -3 A -03/-021180 //1181 // ...1182 // R A 1989 1992 - O Su>=15 0 1 -1183 // R A 1999 o - O Su>=1 0 1 -1184 // R A 2000 o - Mar 3 0 0 -1185 // R A 2007 o - D 30 0 1 -1186 // ...1187 1188 // The 1999 switch uses the same rule, but with a different stdoff.1189 // R A 1999 o - O Su>=1 0 1 -1190 // stdoff -3 -> 1999-10-03 03:00:001191 // stdoff -4 -> 1999-10-03 04:00:001192 // This generates an invalid entry and this is evaluated as a transition.1193 // Looking at the zdump like output in libc++ this generates jumps in1194 // the UTC time1195 1196 using namespace std::literals::chrono_literals;1197 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Argentina/Buenos_Aires");1198 1199 assert_range("[1999-10-03 03:00:00, 2000-03-03 03:00:00) -03:00:00 60min -03",1200 tz->get_info(to_sys_seconds(1999y, std::chrono::October, 3d, 3h)),1201 tz->get_info(to_sys_seconds(2000y, std::chrono::March, 3d, 2h, 59min, 59s)));1202 assert_range("[2000-03-03 03:00:00, 2007-12-30 03:00:00) -03:00:00 0min -03",1203 tz->get_info(to_sys_seconds(2000y, std::chrono::March, 3d, 3h)),1204 tz->get_info(to_sys_seconds(2007y, std::chrono::December, 30d, 2h, 59min, 59s)));1205}1206 1207static void test_america_argentina_la_rioja() {1208 // Z America/Argentina/La_Rioja -4:27:24 - LMT 1894 O 311209 // ...1210 // -4 A -04/-03 1969 O 51211 // -3 A -03/-02 1991 Mar1212 // -4 - -04 1991 May 71213 // -3 A -03/-02 1999 O 31214 // ...1215 //1216 // ...1217 // R A 1988 o - D 1 0 1 -1218 // R A 1989 1993 - Mar Su>=1 0 0 -1219 // R A 1989 1992 - O Su>=15 0 1 -1220 // R A 1999 o - O Su>=1 0 1 -1221 // ...1222 1223 using namespace std::literals::chrono_literals;1224 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Argentina/La_Rioja");1225 1226 assert_range("[1990-10-21 03:00:00, 1991-03-01 02:00:00) -02:00:00 60min -02",1227 tz->get_info(to_sys_seconds(1990y, std::chrono::October, 21d, 3h)),1228 tz->get_info(to_sys_seconds(1991y, std::chrono::March, 1d, 1h, 59min, 59s)));1229}1230 1231static void test_america_argentina_san_luis() {1232 // Z America/Argentina/San_Luis -4:25:24 - LMT 1894 O 311233 // ...1234 // -4 A -04/-03 1969 O 51235 // -3 A -03/-02 19901236 // -3 1 -02 1990 Mar 141237 // -4 - -04 1990 O 151238 // -4 1 -03 1991 Mar1239 // -4 - -04 1991 Jun1240 // -3 - -03 1999 O 31241 // -4 1 -03 2000 Mar 31242 // -4 - -04 2004 Jul 251243 // -3 A -03/-02 2008 Ja 211244 // -4 Sa -04/-03 2009 O 111245 // -3 - -031246 //1247 // ...1248 // R A 1988 o - D 1 0 1 -1249 // R A 1989 1993 - Mar Su>=1 0 0 -1250 // R A 1989 1992 - O Su>=15 0 1 -1251 // R A 1999 o - O Su>=1 0 1 -1252 // R A 2000 o - Mar 3 0 0 -1253 // R A 2007 o - D 30 0 1 -1254 // R A 2008 2009 - Mar Su>=15 0 0 -1255 // R A 2008 o - O Su>=15 0 1 -1256 //1257 // R Sa 2008 2009 - Mar Su>=8 0 0 -1258 // R Sa 2007 2008 - O Su>=8 0 1 -1259 1260 using namespace std::literals::chrono_literals;1261 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Argentina/San_Luis");1262 1263 assert_range("[1989-10-15 03:00:00, 1990-03-14 02:00:00) -02:00:00 60min -02",1264 tz->get_info( // -3 A -03/-02 1990 & R A 1989 1992 - O Su>=15 0 1 -1265 to_sys_seconds(1989y, std::chrono::October, 15d, 3h)),1266 tz->get_info( // UNTIL -3 1 -02 1990 Mar 141267 to_sys_seconds(1990y, std::chrono::March, 14d, 1h, 59min, 59s)));1268 1269 assert_range("[2008-01-21 02:00:00, 2008-03-09 03:00:00) -03:00:00 60min -03",1270 tz->get_info(to_sys_seconds(2008y, std::chrono::January, 21d, 2h)),1271 tz->get_info(to_sys_seconds(2008y, std::chrono::March, 9d, 2h, 59min, 59s)));1272}1273 1274static void test_america_indiana_knox() {1275 // Z America/Indiana/Knox -5:46:30 - LMT 1883 N 18 12:13:301276 // -6 u C%sT 19471277 // -6 St C%sT 1962 Ap 29 21278 // -5 - EST 1963 O 27 21279 // -6 u C%sT 1991 O 27 21280 // -5 - EST 2006 Ap 2 21281 // -6 u C%sT1282 //1283 // ...1284 // R u 1976 1986 - Ap lastSu 2 1 D1285 // R u 1987 2006 - Ap Su>=1 2 1 D1286 // R u 2007 ma - Mar Su>=8 2 1 D1287 // R u 2007 ma - N Su>=1 2 0 S1288 1289 using namespace std::literals::chrono_literals;1290 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Indiana/Knox");1291 1292 // The continuations1293 // -5 - EST1294 // -6 u C%sT1295 // have different offsets. The start time of the first active rule in1296 // RULE u should use the offset at the end of -5 - EST.1297 assert_range("[2006-04-02 07:00:00, 2006-10-29 07:00:00) -05:00:00 60min CDT",1298 tz->get_info(to_sys_seconds(2006y, std::chrono::April, 2d, 7h)),1299 tz->get_info(to_sys_seconds(2006y, std::chrono::October, 29d, 6h, 59min, 59s)));1300}1301 1302static void test_america_punta_arenas() {1303 // Z America/Punta_Arenas -4:43:40 - LMT 18901304 // ...1305 // -4 - -04 1919 Jul1306 // -4:42:45 - SMT 1927 S1307 // -5 x -05/-04 1932 S1308 // ...1309 //1310 // R x 1927 1931 - S 1 0 1 -1311 // R x 1928 1932 - Ap 1 0 0 -1312 // ...1313 1314 using namespace std::literals::chrono_literals;1315 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/Punta_Arenas");1316 1317 assert_equal(1318 std::chrono::sys_info(1319 to_sys_seconds(1927y, std::chrono::September, 1d, 4h, 42min, 45s),1320 to_sys_seconds(1928y, std::chrono::April, 1d, 4h),1321 -4h,1322 60min,1323 "-04"),1324 tz->get_info(to_sys_seconds(1927y, std::chrono::September, 1d, 4h, 42min, 45s)));1325 1326 assert_equal(1327 std::chrono::sys_info(1328 to_sys_seconds(1927y, std::chrono::September, 1d, 4h, 42min, 45s),1329 to_sys_seconds(1928y, std::chrono::April, 1d, 4h),1330 -4h,1331 60min,1332 "-04"),1333 tz->get_info(to_sys_seconds(1928y, std::chrono::April, 1d, 3h, 59min, 59s)));1334}1335 1336static void test_europ_ljubljana() {1337 // Z Europe/Ljubljana 0:58:4 - LMT 18841338 // 1 - CET 1941 Ap 18 231339 // 1 c CE%sT 1945 May 8 2s1340 // 1 1 CEST 1945 S 16 2s1341 // 1 - CET 1982 N 271342 // 1 E CE%sT1343 //1344 // ...1345 // R c 1943 o - O 4 2s 0 -1346 // R c 1944 1945 - Ap M>=1 2s 1 S1347 // R c 1944 o - O 2 2s 0 -1348 // R c 1945 o - S 16 2s 0 -1349 // R c 1977 1980 - Ap Su>=1 2s 1 S1350 // ...1351 1352 using namespace std::literals::chrono_literals;1353 const std::chrono::time_zone* tz = std::chrono::locate_zone("Europe/Ljubljana");1354 1355 assert_equal(1356 std::chrono::sys_info(1357 to_sys_seconds(1945y, std::chrono::April, 2d, 1h),1358 to_sys_seconds(1945y, std::chrono::September, 16d, 1h),1359 2h,1360 60min,1361 "CEST"),1362 tz->get_info(to_sys_seconds(1945y, std::chrono::April, 2d, 1h)));1363 1364 assert_equal(1365 std::chrono::sys_info(1366 to_sys_seconds(1945y, std::chrono::April, 2d, 1h),1367 to_sys_seconds(1945y, std::chrono::September, 16d, 1h),1368 2h,1369 60min,1370 "CEST"),1371 tz->get_info(to_sys_seconds(1945y, std::chrono::September, 16d, 0h, 59min, 59s)));1372}1373 1374int main(int, const char**) {1375 // Basic tests1376 test_gmt();1377 test_durations();1378 test_antarctica_syowa();1379 test_asia_hong_kong();1380 test_europe_berlin();1381 1382 test_america_st_johns();1383 1384 // Small tests for not-yet tested conditions1385 test_get_at_standard_time_universal();1386 test_get_at_standard_time_standard();1387 test_get_at_save_universal();1388 test_get_at_rule_standard();1389 test_get_at_rule_universal();1390 1391 test_format_with_alternatives_west();1392 test_format_with_alternatives_east();1393 1394 // Tests based on bugs found1395 test_africa_algiers();1396 test_africa_casablanca();1397 test_africa_ceuta();1398 test_africa_freetown();1399 test_africa_windhoek();1400 test_america_adak();1401 test_america_argentina_buenos_aires();1402 test_america_argentina_la_rioja();1403 test_america_argentina_san_luis();1404 test_america_auncion();1405 test_america_ciudad_juarez();1406 test_america_indiana_knox();1407 1408 // Reverse search bugs1409 test_america_punta_arenas();1410 test_europ_ljubljana();1411 1412 return 0;1413}1414