1307 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// UNSUPPORTED: c++03, c++11, c++14, c++1710// UNSUPPORTED: no-filesystem, no-localization, no-tzdb11// REQUIRES: long_tests12 13// XFAIL: libcpp-has-no-experimental-tzdb14// XFAIL: availability-tzdb-missing15 16// TODO TZDB Investigate why this fails.17// UNSUPPORTED: target={{.*}}18 19// <chrono>20 21// class time_zone;22 23// template <class _Duration>24// local_info get_info(const local_time<_Duration>& time) const;25 26// This test uses the system provided database. This makes the test portable,27// but may cause failures when the database information changes. Historic data28// may change if new facts are uncovered, future data may change when regions29// change their time zone or daylight saving time. Most tests will not look in30// the future to attempt to avoid issues. All tests list the data on which they31// are based, this makes debugging easier upon failure; including to see whether32// the provided data has not been changed.33//34// The first part of the test is manually crafted, the second part compares the35// transitions for all time zones in the database.36 37#include <algorithm>38#include <cassert>39#include <chrono>40#include <format>41 42#include "test_macros.h"43#include "assert_macros.h"44#include "concat_macros.h"45 46// The year range to validate. The dates used in practice are expected to be47// inside the tested range.48constexpr std::chrono::year first{1800};49constexpr std::chrono::year last{2100};50 51/***** ***** HELPERS ***** *****/52 53[[nodiscard]] static std::chrono::sys_seconds to_sys_seconds(54 std::chrono::year year,55 std::chrono::month month,56 std::chrono::day day,57 std::chrono::hours h = std::chrono::hours(0),58 std::chrono::minutes m = std::chrono::minutes{0},59 std::chrono::seconds s = std::chrono::seconds{0}) {60 std::chrono::year_month_day result{year, month, day};61 62 return std::chrono::time_point_cast<std::chrono::seconds>(static_cast<std::chrono::sys_days>(result)) + h + m + s;63}64 65[[nodiscard]] static std::chrono::local_seconds to_local_seconds(66 std::chrono::year year,67 std::chrono::month month,68 std::chrono::day day,69 std::chrono::hours h = std::chrono::hours(0),70 std::chrono::minutes m = std::chrono::minutes{0},71 std::chrono::seconds s = std::chrono::seconds{0}) {72 std::chrono::year_month_day result{year, month, day};73 74 return std::chrono::time_point_cast<std::chrono::seconds>(static_cast<std::chrono::local_days>(result)) + h + m + s;75}76 77static void assert_equal(const std::chrono::sys_info& lhs, const std::chrono::sys_info& rhs) {78 TEST_REQUIRE(lhs.begin == rhs.begin,79 TEST_WRITE_CONCATENATED("\nBegin:\nExpected output ", lhs.begin, "\nActual output ", rhs.begin, '\n'));80 TEST_REQUIRE(lhs.end == rhs.end,81 TEST_WRITE_CONCATENATED("\nEnd:\nExpected output ", lhs.end, "\nActual output ", rhs.end, '\n'));82 TEST_REQUIRE(83 lhs.offset == rhs.offset,84 TEST_WRITE_CONCATENATED("\nOffset:\nExpected output ", lhs.offset, "\nActual output ", rhs.offset, '\n'));85 TEST_REQUIRE(lhs.save == rhs.save,86 TEST_WRITE_CONCATENATED("\nSave:\nExpected output ", lhs.save, "\nActual output ", rhs.save, '\n'));87 TEST_REQUIRE(88 lhs.abbrev == rhs.abbrev,89 TEST_WRITE_CONCATENATED("\nAbbrev:\nExpected output ", lhs.abbrev, "\nActual output ", rhs.abbrev, '\n'));90}91 92static void assert_equal(const std::chrono::local_info& lhs, const std::chrono::local_info& rhs) {93 TEST_REQUIRE(94 lhs.result == rhs.result,95 TEST_WRITE_CONCATENATED("\nResult:\nExpected output ", lhs.result, "\nActual output ", rhs.result, '\n'));96 97 assert_equal(lhs.first, rhs.first);98 assert_equal(lhs.second, rhs.second);99}100 101/***** ***** TESTS ***** *****/102 103static void test_gmt() {104 // Simple zone always valid, no rule entries, lookup using a link.105 // L Etc/GMT GMT106 // Z Etc/GMT 0 - GMT107 108 using namespace std::literals::chrono_literals;109 const std::chrono::time_zone* tz = std::chrono::locate_zone("GMT");110 111 assert_equal(112 std::chrono::local_info(113 std::chrono::local_info::unique,114 std::chrono::sys_info(std::chrono::sys_seconds::min(), std::chrono::sys_seconds::max(), 0s, 0min, "GMT"),115 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),116 tz->get_info(std::chrono::local_seconds::min()));117}118 119static void test_local_time_out_of_range() {120 // Fixed positive offset121 // Etc/GMT-1 1 - +01122 123 using namespace std::literals::chrono_literals;124 { // lower bound125 const std::chrono::time_zone* tz = std::chrono::locate_zone("Etc/GMT-1");126 127 assert_equal(128 std::chrono::local_info(129 -1,130 std::chrono::sys_info(std::chrono::sys_seconds::min(), std::chrono::sys_seconds::max(), 1h, 0min, "+01"),131 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),132 tz->get_info(std::chrono::local_seconds::min()));133 134 assert_equal(135 std::chrono::local_info(136 -1,137 std::chrono::sys_info(std::chrono::sys_seconds::min(), std::chrono::sys_seconds::max(), 1h, 0min, "+01"),138 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),139 tz->get_info(std::chrono::local_seconds::min() + 59min + 59s));140 141 assert_equal(142 std::chrono::local_info(143 std::chrono::local_info::unique,144 std::chrono::sys_info(std::chrono::sys_seconds::min(), std::chrono::sys_seconds::max(), 1h, 0min, "+01"),145 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),146 tz->get_info(std::chrono::local_seconds::min() + 1h));147 }148 149 { // upper bound150 const std::chrono::time_zone* tz = std::chrono::locate_zone("Etc/GMT+1");151 152 assert_equal(153 std::chrono::local_info(154 -2,155 std::chrono::sys_info(std::chrono::sys_seconds::min(), std::chrono::sys_seconds::max(), -1h, 0min, "-01"),156 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),157 tz->get_info(std::chrono::local_seconds::max() - 1s));158 159 assert_equal(160 std::chrono::local_info(161 std::chrono::local_info::unique,162 std::chrono::sys_info(std::chrono::sys_seconds::min(), std::chrono::sys_seconds::max(), -1h, 0min, "-01"),163 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),164 tz->get_info(std::chrono::local_seconds::max() - 1h - 1s));165 }166}167 168static void test_indian_kerguelen() {169 // One change, no rules, no dst changes.170 171 // Z Indian/Kerguelen 0 - -00 1950172 // 5 - +05173 174 using namespace std::literals::chrono_literals;175 const std::chrono::time_zone* tz = std::chrono::locate_zone("Indian/Kerguelen");176 177 assert_equal(178 std::chrono::local_info(179 std::chrono::local_info::unique,180 std::chrono::sys_info(181 std::chrono::sys_seconds::min(), to_sys_seconds(1950y, std::chrono::January, 1d), 0s, 0min, "-00"),182 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),183 tz->get_info(std::chrono::local_seconds::min()));184 185 assert_equal(186 std::chrono::local_info(187 std::chrono::local_info::nonexistent,188 std::chrono::sys_info(189 std::chrono::sys_seconds::min(), to_sys_seconds(1950y, std::chrono::January, 1d), 0s, 0min, "-00"),190 std::chrono::sys_info(191 to_sys_seconds(1950y, std::chrono::January, 1d), std::chrono::sys_seconds::max(), 5h, 0min, "+05")),192 tz->get_info(to_local_seconds(1950y, std::chrono::January, 1d)));193 194 assert_equal(195 std::chrono::local_info(196 std::chrono::local_info::unique,197 std::chrono::sys_info(198 to_sys_seconds(1950y, std::chrono::January, 1d), std::chrono::sys_seconds::max(), 5h, 0min, "+05"),199 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),200 tz->get_info(to_local_seconds(1950y, std::chrono::January, 1d, 5h)));201 202 assert_equal(203 std::chrono::local_info(204 std::chrono::local_info::unique,205 std::chrono::sys_info(206 to_sys_seconds(1950y, std::chrono::January, 1d), std::chrono::sys_seconds::max(), 5h, 0min, "+05"),207 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),208 tz->get_info(std::chrono::local_seconds::max() - 1s));209}210 211static void test_antarctica_rothera() {212 // One change, no rules, no dst changes213 214 // Z Antarctica/Rothera 0 - -00 1976 D215 // -3 - -03216 217 using namespace std::literals::chrono_literals;218 const std::chrono::time_zone* tz = std::chrono::locate_zone("Antarctica/Rothera");219 220 assert_equal(221 std::chrono::local_info(222 std::chrono::local_info::unique,223 std::chrono::sys_info(224 std::chrono::sys_seconds::min(), to_sys_seconds(1976y, std::chrono::December, 1d), 0s, 0min, "-00"),225 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),226 tz->get_info(std::chrono::local_seconds::min()));227 228 assert_equal(229 std::chrono::local_info(230 std::chrono::local_info::unique,231 std::chrono::sys_info(232 std::chrono::sys_seconds::min(), to_sys_seconds(1976y, std::chrono::December, 1d), 0s, 0min, "-00"),233 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),234 tz->get_info(to_local_seconds(1976y, std::chrono::November, 30d, 20h, 59min, 59s)));235 236 assert_equal(237 std::chrono::local_info(238 std::chrono::local_info::ambiguous,239 std::chrono::sys_info(240 std::chrono::sys_seconds::min(), to_sys_seconds(1976y, std::chrono::December, 1d), 0s, 0min, "-00"),241 std::chrono::sys_info(242 to_sys_seconds(1976y, std::chrono::December, 1d), std::chrono::sys_seconds::max(), -3h, 0min, "-03")),243 tz->get_info(to_local_seconds(1976y, std::chrono::November, 30d, 21h)));244 245 assert_equal(246 std::chrono::local_info(247 std::chrono::local_info::ambiguous,248 std::chrono::sys_info(249 std::chrono::sys_seconds::min(), to_sys_seconds(1976y, std::chrono::December, 1d), 0s, 0min, "-00"),250 std::chrono::sys_info(251 to_sys_seconds(1976y, std::chrono::December, 1d), std::chrono::sys_seconds::max(), -3h, 0min, "-03")),252 tz->get_info(to_local_seconds(1976y, std::chrono::November, 30d, 23h, 59min, 59s)));253 254 assert_equal(255 std::chrono::local_info(256 std::chrono::local_info::unique,257 std::chrono::sys_info(258 to_sys_seconds(1976y, std::chrono::December, 1d), std::chrono::sys_seconds::max(), -3h, 0min, "-03"),259 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),260 tz->get_info(to_local_seconds(1976y, std::chrono::December, 1d)));261 262 assert_equal(263 std::chrono::local_info(264 std::chrono::local_info::unique,265 std::chrono::sys_info(266 to_sys_seconds(1976y, std::chrono::December, 1d), std::chrono::sys_seconds::max(), -3h, 0min, "-03"),267 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),268 tz->get_info(std::chrono::local_seconds::max() - 3h - 1s));269 270 assert_equal(271 std::chrono::local_info(272 -2,273 std::chrono::sys_info(274 to_sys_seconds(1976y, std::chrono::December, 1d), std::chrono::sys_seconds::max(), -3h, 0min, "-03"),275 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),276 tz->get_info(std::chrono::local_seconds::max() - 1s));277}278 279static void test_asia_hong_kong() {280 // A more typical entry, first some hard-coded entires and then at the281 // end a rules based entry. This rule is valid for its entire period282 //283 // Z Asia/Hong_Kong 7:36:42 - LMT 1904 O 30 0:36:42284 // 8 - HKT 1941 Jun 15 3285 // 8 1 HKST 1941 O 1 4286 // 8 0:30 HKWT 1941 D 25287 // 9 - JST 1945 N 18 2288 // 8 HK HK%sT289 //290 // R HK 1946 o - Ap 21 0 1 S291 // R HK 1946 o - D 1 3:30s 0 -292 // R HK 1947 o - Ap 13 3:30s 1 S293 // R HK 1947 o - N 30 3:30s 0 -294 // R HK 1948 o - May 2 3:30s 1 S295 // R HK 1948 1952 - O Su>=28 3:30s 0 -296 // R HK 1949 1953 - Ap Su>=1 3:30 1 S297 // R HK 1953 1964 - O Su>=31 3:30 0 -298 // R HK 1954 1964 - Mar Su>=18 3:30 1 S299 // R HK 1965 1976 - Ap Su>=16 3:30 1 S300 // R HK 1965 1976 - O Su>=16 3:30 0 -301 // R HK 1973 o - D 30 3:30 1 S302 // R HK 1979 o - May 13 3:30 1 S303 // R HK 1979 o - O 21 3:30 0 -304 305 using namespace std::literals::chrono_literals;306 const std::chrono::time_zone* tz = std::chrono::locate_zone("Asia/Hong_Kong");307 308 assert_equal(309 std::chrono::local_info(310 -1,311 std::chrono::sys_info(312 std::chrono::sys_seconds::min(),313 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),314 7h + 36min + 42s,315 0min,316 "LMT"),317 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),318 tz->get_info(std::chrono::local_seconds::min()));319 320 assert_equal(321 std::chrono::local_info(322 -1,323 std::chrono::sys_info(324 std::chrono::sys_seconds::min(),325 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),326 7h + 36min + 42s,327 0min,328 "LMT"),329 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),330 tz->get_info(std::chrono::local_seconds::min() + 7h + 36min + 41s));331 332 assert_equal(333 std::chrono::local_info(334 std::chrono::local_info::unique,335 std::chrono::sys_info(336 std::chrono::sys_seconds::min(),337 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),338 7h + 36min + 42s,339 0min,340 "LMT"),341 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),342 tz->get_info(std::chrono::local_seconds::min() + 7h + 36min + 42s));343 344 assert_equal(345 std::chrono::local_info(346 std::chrono::local_info::unique,347 std::chrono::sys_info(348 std::chrono::sys_seconds::min(),349 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),350 7h + 36min + 42s,351 0min,352 "LMT"),353 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),354 tz->get_info(to_local_seconds(1904y, std::chrono::October, 30d, 0h, 36min, 41s)));355 356 assert_equal(357 std::chrono::local_info(358 std::chrono::local_info::nonexistent,359 std::chrono::sys_info(360 std::chrono::sys_seconds::min(),361 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),362 7h + 36min + 42s,363 0min,364 "LMT"),365 std::chrono::sys_info(366 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),367 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),368 8h,369 0min,370 "HKT")),371 tz->get_info(to_local_seconds(1904y, std::chrono::October, 30d, 0h, 36min, 42s)));372 373 assert_equal(374 std::chrono::local_info(375 std::chrono::local_info::nonexistent,376 std::chrono::sys_info(377 std::chrono::sys_seconds::min(),378 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),379 7h + 36min + 42s,380 0min,381 "LMT"),382 std::chrono::sys_info(383 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),384 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),385 8h,386 0min,387 "HKT")),388 tz->get_info(to_local_seconds(1904y, std::chrono::October, 30d, 0h, 59min, 59s)));389 390 assert_equal(391 std::chrono::local_info(392 std::chrono::local_info::unique,393 std::chrono::sys_info(394 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),395 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),396 8h,397 0min,398 "HKT"),399 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),400 tz->get_info(to_local_seconds(1904y, std::chrono::October, 30d, 1h)));401 402 assert_equal(403 std::chrono::local_info(404 std::chrono::local_info::unique,405 std::chrono::sys_info(406 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),407 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),408 8h,409 0min,410 "HKT"),411 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),412 tz->get_info(to_local_seconds(1941y, std::chrono::June, 15d, 2h, 59min, 59s)));413 414 assert_equal(415 std::chrono::local_info(416 std::chrono::local_info::nonexistent,417 std::chrono::sys_info(418 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),419 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),420 8h,421 0min,422 "HKT"),423 std::chrono::sys_info(424 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),425 to_sys_seconds(1941y, std::chrono::September, 30d, 19h),426 9h,427 60min,428 "HKST")),429 tz->get_info(to_local_seconds(1941y, std::chrono::June, 15d, 3h)));430 431 assert_equal(432 std::chrono::local_info(433 std::chrono::local_info::nonexistent,434 std::chrono::sys_info(435 to_sys_seconds(1904y, std::chrono::October, 29d, 17h),436 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),437 8h,438 0min,439 "HKT"),440 std::chrono::sys_info(441 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),442 to_sys_seconds(1941y, std::chrono::September, 30d, 19h),443 9h,444 60min,445 "HKST")),446 tz->get_info(to_local_seconds(1941y, std::chrono::June, 15d, 3h, 59min, 59s)));447 448 assert_equal(449 std::chrono::local_info(450 std::chrono::local_info::unique,451 std::chrono::sys_info(452 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),453 to_sys_seconds(1941y, std::chrono::September, 30d, 19h),454 9h,455 60min,456 "HKST"),457 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),458 tz->get_info(to_local_seconds(1941y, std::chrono::June, 15d, 4h)));459 460 assert_equal(461 std::chrono::local_info(462 std::chrono::local_info::unique,463 std::chrono::sys_info(464 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),465 to_sys_seconds(1941y, std::chrono::September, 30d, 19h),466 9h,467 60min,468 "HKST"),469 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),470 tz->get_info(to_local_seconds(1941y, std::chrono::October, 1d, 3h, 29min, 29s)));471 472 assert_equal(473 std::chrono::local_info(474 std::chrono::local_info::ambiguous,475 std::chrono::sys_info(476 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),477 to_sys_seconds(1941y, std::chrono::September, 30d, 19h),478 9h,479 60min,480 "HKST"),481 std::chrono::sys_info(482 to_sys_seconds(1941y, std::chrono::September, 30d, 19h),483 to_sys_seconds(1941y, std::chrono::December, 24d, 15h, 30min),484 8h + 30min,485 30min,486 "HKWT")),487 tz->get_info(to_local_seconds(1941y, std::chrono::October, 1d, 3h, 30min)));488 489 assert_equal(490 std::chrono::local_info(491 std::chrono::local_info::ambiguous,492 std::chrono::sys_info(493 to_sys_seconds(1941y, std::chrono::June, 14d, 19h),494 to_sys_seconds(1941y, std::chrono::September, 30d, 19h),495 9h,496 60min,497 "HKST"),498 std::chrono::sys_info(499 to_sys_seconds(1941y, std::chrono::September, 30d, 19h),500 to_sys_seconds(1941y, std::chrono::December, 24d, 15h, 30min),501 8h + 30min,502 30min,503 "HKWT")),504 tz->get_info(to_local_seconds(1941y, std::chrono::October, 1d, 3h, 59min, 59s)));505 506 assert_equal(507 std::chrono::local_info(508 std::chrono::local_info::unique,509 std::chrono::sys_info(510 to_sys_seconds(1941y, std::chrono::September, 30d, 19h),511 to_sys_seconds(1941y, std::chrono::December, 24d, 15h, 30min),512 8h + 30min,513 30min,514 "HKWT"),515 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),516 tz->get_info(to_local_seconds(1941y, std::chrono::October, 1d, 4h)));517}518 519static void test_europe_berlin() {520 // A more typical entry, first some hard-coded entires and then at the521 // end a rules based entry. This rule is valid for its entire period522 //523 524 // Z Europe/Berlin 0:53:28 - LMT 1893 Ap525 // 1 c CE%sT 1945 May 24 2526 // 1 So CE%sT 1946527 // 1 DE CE%sT 1980528 // 1 E CE%sT529 //530 // R c 1916 o - Ap 30 23 1 S531 // R c 1916 o - O 1 1 0 -532 // R c 1917 1918 - Ap M>=15 2s 1 S533 // R c 1917 1918 - S M>=15 2s 0 -534 // R c 1940 o - Ap 1 2s 1 S535 // R c 1942 o - N 2 2s 0 -536 // R c 1943 o - Mar 29 2s 1 S537 // R c 1943 o - O 4 2s 0 -538 // R c 1944 1945 - Ap M>=1 2s 1 S539 // R c 1944 o - O 2 2s 0 -540 // R c 1945 o - S 16 2s 0 -541 // R c 1977 1980 - Ap Su>=1 2s 1 S542 // R c 1977 o - S lastSu 2s 0 -543 // R c 1978 o - O 1 2s 0 -544 // R c 1979 1995 - S lastSu 2s 0 -545 // R c 1981 ma - Mar lastSu 2s 1 S546 // R c 1996 ma - O lastSu 2s 0 -547 //548 // R So 1945 o - May 24 2 2 M549 // R So 1945 o - S 24 3 1 S550 // R So 1945 o - N 18 2s 0 -551 //552 // R DE 1946 o - Ap 14 2s 1 S553 // R DE 1946 o - O 7 2s 0 -554 // R DE 1947 1949 - O Su>=1 2s 0 -555 // R DE 1947 o - Ap 6 3s 1 S556 // R DE 1947 o - May 11 2s 2 M557 // R DE 1947 o - Jun 29 3 1 S558 // R DE 1948 o - Ap 18 2s 1 S559 // R DE 1949 o - Ap 10 2s 1 S560 //561 // R E 1977 1980 - Ap Su>=1 1u 1 S562 // R E 1977 o - S lastSu 1u 0 -563 // R E 1978 o - O 1 1u 0 -564 // R E 1979 1995 - S lastSu 1u 0 -565 // R E 1981 ma - Mar lastSu 1u 1 S566 // R E 1996 ma - O lastSu 1u 0 -567 //568 // Note the European Union decided to stop the seasonal change in569 // 2021. In 2023 seasonal changes are still in effect.570 571 using namespace std::literals::chrono_literals;572 const std::chrono::time_zone* tz = std::chrono::locate_zone("Europe/Berlin");573 574 assert_equal(575 std::chrono::local_info(576 -1,577 std::chrono::sys_info(578 std::chrono::sys_seconds::min(),579 to_sys_seconds(1893y, std::chrono::March, 31d, 23h, 6min, 32s),580 53min + 28s,581 0min,582 "LMT"),583 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),584 tz->get_info(std::chrono::local_seconds::min()));585 586 assert_equal(587 std::chrono::local_info(588 -1,589 std::chrono::sys_info(590 std::chrono::sys_seconds::min(),591 to_sys_seconds(1893y, std::chrono::March, 31d, 23h, 6min, 32s),592 53min + 28s,593 0min,594 "LMT"),595 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),596 tz->get_info(std::chrono::local_seconds::min() + 53min + 27s));597 598 assert_equal(599 std::chrono::local_info(600 std::chrono::local_info::unique,601 std::chrono::sys_info(602 std::chrono::sys_seconds::min(),603 to_sys_seconds(1893y, std::chrono::March, 31d, 23h, 6min, 32s),604 53min + 28s,605 0min,606 "LMT"),607 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),608 tz->get_info(std::chrono::local_seconds::min() + 53min + 28s));609 610 assert_equal(611 std::chrono::local_info(612 std::chrono::local_info::unique,613 std::chrono::sys_info(614 std::chrono::sys_seconds::min(),615 to_sys_seconds(1893y, std::chrono::March, 31d, 23h, 6min, 32s),616 53min + 28s,617 0min,618 "LMT"),619 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),620 tz->get_info(to_local_seconds(1893y, std::chrono::March, 31d, 23h, 59min, 59s)));621 622 assert_equal(623 std::chrono::local_info(624 std::chrono::local_info::unique,625 std::chrono::sys_info(626 to_sys_seconds(1946y, std::chrono::October, 7d, 1h),627 to_sys_seconds(1947y, std::chrono::April, 6d, 2h),628 1h,629 0min,630 "CET"),631 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),632 tz->get_info(to_local_seconds(1947y, std::chrono::April, 6d, 2h, 59min, 59s)));633 634 assert_equal(635 std::chrono::local_info(636 std::chrono::local_info::nonexistent,637 std::chrono::sys_info(638 to_sys_seconds(1946y, std::chrono::October, 7d, 1h),639 to_sys_seconds(1947y, std::chrono::April, 6d, 2h),640 1h,641 0min,642 "CET"),643 std::chrono::sys_info(644 to_sys_seconds(1947y, std::chrono::April, 6d, 2h),645 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),646 2h,647 60min,648 "CEST")),649 tz->get_info(to_local_seconds(1947y, std::chrono::April, 6d, 3h)));650 651 assert_equal(652 std::chrono::local_info(653 std::chrono::local_info::nonexistent,654 std::chrono::sys_info(655 to_sys_seconds(1946y, std::chrono::October, 7d, 1h),656 to_sys_seconds(1947y, std::chrono::April, 6d, 2h),657 1h,658 0min,659 "CET"),660 std::chrono::sys_info(661 to_sys_seconds(1947y, std::chrono::April, 6d, 2h),662 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),663 2h,664 60min,665 "CEST")),666 tz->get_info(to_local_seconds(1947y, std::chrono::April, 6d, 3h, 59min, 59s)));667 668 assert_equal(669 std::chrono::local_info(670 std::chrono::local_info::unique,671 std::chrono::sys_info(672 to_sys_seconds(1947y, std::chrono::April, 6d, 2h),673 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),674 2h,675 60min,676 "CEST"),677 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),678 tz->get_info(to_local_seconds(1947y, std::chrono::April, 6d, 4h)));679 680 assert_equal(681 std::chrono::local_info(682 std::chrono::local_info::unique,683 std::chrono::sys_info(684 to_sys_seconds(1947y, std::chrono::April, 6d, 2h),685 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),686 2h,687 60min,688 "CEST"),689 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),690 tz->get_info(to_local_seconds(1947y, std::chrono::May, 11d, 2h, 59min, 59s)));691 692 assert_equal(693 std::chrono::local_info(694 std::chrono::local_info::nonexistent,695 std::chrono::sys_info(696 to_sys_seconds(1947y, std::chrono::April, 6d, 2h),697 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),698 2h,699 60min,700 "CEST"),701 std::chrono::sys_info(702 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),703 to_sys_seconds(1947y, std::chrono::June, 29d),704 3h,705 120min,706 "CEMT")),707 tz->get_info(to_local_seconds(1947y, std::chrono::May, 11d, 3h)));708 709 assert_equal(710 std::chrono::local_info(711 std::chrono::local_info::nonexistent,712 std::chrono::sys_info(713 to_sys_seconds(1947y, std::chrono::April, 6d, 2h),714 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),715 2h,716 60min,717 "CEST"),718 std::chrono::sys_info(719 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),720 to_sys_seconds(1947y, std::chrono::June, 29d),721 3h,722 120min,723 "CEMT")),724 tz->get_info(to_local_seconds(1947y, std::chrono::May, 11d, 3h, 59min, 59s)));725 726 assert_equal(727 std::chrono::local_info(728 std::chrono::local_info::unique,729 std::chrono::sys_info(730 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),731 to_sys_seconds(1947y, std::chrono::June, 29d),732 3h,733 120min,734 "CEMT"),735 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),736 tz->get_info(to_local_seconds(1947y, std::chrono::May, 11d, 4h)));737 738 assert_equal(739 std::chrono::local_info(740 std::chrono::local_info::unique,741 std::chrono::sys_info(742 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),743 to_sys_seconds(1947y, std::chrono::June, 29d),744 3h,745 120min,746 "CEMT"),747 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),748 tz->get_info(to_local_seconds(1947y, std::chrono::June, 29d, 1h, 59min, 59s)));749 750 assert_equal(751 std::chrono::local_info(752 std::chrono::local_info::ambiguous,753 std::chrono::sys_info(754 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),755 to_sys_seconds(1947y, std::chrono::June, 29d),756 3h,757 120min,758 "CEMT"),759 std::chrono::sys_info(760 to_sys_seconds(1947y, std::chrono::June, 29d),761 to_sys_seconds(1947y, std::chrono::October, 5d, 1h),762 2h,763 60min,764 "CEST")),765 tz->get_info(to_local_seconds(1947y, std::chrono::June, 29d, 2h)));766 767 assert_equal(768 std::chrono::local_info(769 std::chrono::local_info::ambiguous,770 std::chrono::sys_info(771 to_sys_seconds(1947y, std::chrono::May, 11d, 1h),772 to_sys_seconds(1947y, std::chrono::June, 29d),773 3h,774 120min,775 "CEMT"),776 std::chrono::sys_info(777 to_sys_seconds(1947y, std::chrono::June, 29d),778 to_sys_seconds(1947y, std::chrono::October, 5d, 1h),779 2h,780 60min,781 "CEST")),782 tz->get_info(to_local_seconds(1947y, std::chrono::June, 29d, 2h, 59min, 59s)));783 784 assert_equal(785 std::chrono::local_info(786 std::chrono::local_info::unique,787 std::chrono::sys_info(788 to_sys_seconds(1947y, std::chrono::June, 29d),789 to_sys_seconds(1947y, std::chrono::October, 5d, 1h),790 2h,791 60min,792 "CEST"),793 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),794 tz->get_info(to_local_seconds(1947y, std::chrono::June, 29d, 3h)));795 796 assert_equal(797 std::chrono::local_info(798 std::chrono::local_info::unique,799 std::chrono::sys_info(800 to_sys_seconds(1947y, std::chrono::June, 29d),801 to_sys_seconds(1947y, std::chrono::October, 5d, 1h),802 2h,803 60min,804 "CEST"),805 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),806 tz->get_info(to_local_seconds(1947y, std::chrono::October, 5d, 1h, 59min, 59s)));807 808 assert_equal(809 std::chrono::local_info(810 std::chrono::local_info::ambiguous,811 std::chrono::sys_info(812 to_sys_seconds(1947y, std::chrono::June, 29d),813 to_sys_seconds(1947y, std::chrono::October, 5d, 1h),814 2h,815 60min,816 "CEST"),817 std::chrono::sys_info(818 to_sys_seconds(1947y, std::chrono::October, 5d, 1h),819 to_sys_seconds(1948y, std::chrono::April, 18d, 1h),820 1h,821 0min,822 "CET")),823 tz->get_info(to_local_seconds(1947y, std::chrono::October, 5d, 2h)));824 825 assert_equal(826 std::chrono::local_info(827 std::chrono::local_info::ambiguous,828 std::chrono::sys_info(829 to_sys_seconds(1947y, std::chrono::June, 29d),830 to_sys_seconds(1947y, std::chrono::October, 5d, 1h),831 2h,832 60min,833 "CEST"),834 std::chrono::sys_info(835 to_sys_seconds(1947y, std::chrono::October, 5d, 1h),836 to_sys_seconds(1948y, std::chrono::April, 18d, 1h),837 1h,838 0min,839 "CET")),840 tz->get_info(to_local_seconds(1947y, std::chrono::October, 5d, 2h, 59min, 59s)));841 842 assert_equal(843 std::chrono::local_info(844 std::chrono::local_info::unique,845 std::chrono::sys_info(846 to_sys_seconds(1947y, std::chrono::October, 5d, 1h),847 to_sys_seconds(1948y, std::chrono::April, 18d, 1h),848 1h,849 0min,850 "CET"),851 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),852 tz->get_info(to_local_seconds(1947y, std::chrono::October, 5d, 3h)));853}854 855static void test_europe_dublin() {856 // Z Europe/Dublin -0:25:21 - LMT 1880 Au 2857 // -0:25:21 - DMT 1916 May 21 2s858 // -0:25:21 1 IST 1916 O 1 2s859 // 0 G %s 1921 D 6860 // ...861 //862 // R G 1916 o - May 21 2s 1 BST863 // R G 1916 o - O 1 2s 0 GMT864 // R G 1917 o - Ap 8 2s 1 BST865 // ...866 867 using namespace std::literals::chrono_literals;868 const std::chrono::time_zone* tz = std::chrono::locate_zone("Europe/Dublin");869 870 assert_equal(871 std::chrono::local_info(872 std::chrono::local_info::unique,873 std::chrono::sys_info(874 std::chrono::sys_seconds::min(),875 to_sys_seconds(1880y, std::chrono::August, 2d, 0h, 25min, 21s),876 -(25min + 21s),877 0min,878 "LMT"),879 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),880 tz->get_info(std::chrono::local_seconds::min()));881 882 assert_equal(883 std::chrono::local_info(884 std::chrono::local_info::unique,885 std::chrono::sys_info(886 std::chrono::sys_seconds::min(),887 to_sys_seconds(1880y, std::chrono::August, 2d, 0h, 25min, 21s),888 -(25min + 21s),889 0min,890 "LMT"),891 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),892 tz->get_info(to_local_seconds(1880y, std::chrono::August, 1d, 23h, 59min, 59s)));893 894 assert_equal(895 std::chrono::local_info(896 std::chrono::local_info::unique,897 std::chrono::sys_info(898 to_sys_seconds(1880y, std::chrono::August, 2d, 0h, 25min, 21s),899 to_sys_seconds(1916y, std::chrono::May, 21d, 2h, 25min, 21s),900 -(25min + 21s),901 0min,902 "DMT"),903 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),904 tz->get_info(to_local_seconds(1880y, std::chrono::August, 2d)));905 906 assert_equal(907 std::chrono::local_info(908 std::chrono::local_info::unique,909 std::chrono::sys_info(910 to_sys_seconds(1880y, std::chrono::August, 2d, 0h, 25min, 21s),911 to_sys_seconds(1916y, std::chrono::May, 21d, 2h, 25min, 21s),912 -(25min + 21s),913 0min,914 "DMT"),915 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),916 tz->get_info(to_local_seconds(1916y, std::chrono::May, 21d, 1h, 59min, 59s)));917 918 assert_equal(919 std::chrono::local_info(920 std::chrono::local_info::nonexistent,921 std::chrono::sys_info(922 to_sys_seconds(1880y, std::chrono::August, 2d, 0h, 25min, 21s),923 to_sys_seconds(1916y, std::chrono::May, 21d, 2h, 25min, 21s),924 -(25min + 21s),925 0min,926 "DMT"),927 std::chrono::sys_info(928 to_sys_seconds(1916y, std::chrono::May, 21d, 2h, 25min, 21s),929 to_sys_seconds(1916y, std::chrono::October, 1d, 02h, 25min, 21s),930 34min + 39s,931 60min,932 "IST")),933 tz->get_info(to_local_seconds(1916y, std::chrono::May, 21d, 2h)));934 935 assert_equal(936 std::chrono::local_info(937 std::chrono::local_info::nonexistent,938 std::chrono::sys_info(939 to_sys_seconds(1880y, std::chrono::August, 2d, 0h, 25min, 21s),940 to_sys_seconds(1916y, std::chrono::May, 21d, 2h, 25min, 21s),941 -(25min + 21s),942 0min,943 "DMT"),944 std::chrono::sys_info(945 to_sys_seconds(1916y, std::chrono::May, 21d, 2h, 25min, 21s),946 to_sys_seconds(1916y, std::chrono::October, 1d, 02h, 25min, 21s),947 34min + 39s,948 60min,949 "IST")),950 tz->get_info(to_local_seconds(1916y, std::chrono::May, 21d, 2h, 59min, 59s)));951 952 assert_equal(953 std::chrono::local_info(954 std::chrono::local_info::unique,955 std::chrono::sys_info(956 to_sys_seconds(1916y, std::chrono::May, 21d, 2h, 25min, 21s),957 to_sys_seconds(1916y, std::chrono::October, 1d, 02h, 25min, 21s),958 34min + 39s,959 60min,960 "IST"),961 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),962 tz->get_info(to_local_seconds(1916y, std::chrono::May, 21d, 6h)));963 964 assert_equal(965 std::chrono::local_info(966 std::chrono::local_info::unique,967 std::chrono::sys_info(968 to_sys_seconds(1916y, std::chrono::May, 21d, 2h, 25min, 21s),969 to_sys_seconds(1916y, std::chrono::October, 1d, 02h, 25min, 21s),970 34min + 39s,971 60min,972 "IST"),973 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),974 tz->get_info(to_local_seconds(1916y, std::chrono::October, 1d, 2h, 25min, 20s)));975 976 assert_equal(977 std::chrono::local_info(978 std::chrono::local_info::ambiguous,979 std::chrono::sys_info(980 to_sys_seconds(1916y, std::chrono::May, 21d, 2h, 25min, 21s),981 to_sys_seconds(1916y, std::chrono::October, 1d, 02h, 25min, 21s),982 34min + 39s,983 60min,984 "IST"),985 std::chrono::sys_info(986 to_sys_seconds(1916y, std::chrono::October, 1d, 02h, 25min, 21s),987 to_sys_seconds(1917y, std::chrono::April, 8d, 2h),988 0s,989 0min,990 "GMT")),991 tz->get_info(to_local_seconds(1916y, std::chrono::October, 1d, 2h, 59min, 59s)));992 993 assert_equal(994 std::chrono::local_info(995 std::chrono::local_info::unique,996 std::chrono::sys_info(997 to_sys_seconds(1916y, std::chrono::October, 1d, 02h, 25min, 21s),998 to_sys_seconds(1917y, std::chrono::April, 8d, 2h),999 0s,1000 0min,1001 "GMT"),1002 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1003 tz->get_info(to_local_seconds(1916y, std::chrono::October, 1d, 3h)));1004 1005 assert_equal(1006 std::chrono::local_info(1007 std::chrono::local_info::unique,1008 std::chrono::sys_info(1009 to_sys_seconds(1916y, std::chrono::October, 1d, 02h, 25min, 21s),1010 to_sys_seconds(1917y, std::chrono::April, 8d, 2h),1011 0s,1012 0min,1013 "GMT"),1014 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1015 tz->get_info(to_local_seconds(1917y, std::chrono::April, 8d, 1h, 59min, 59s)));1016}1017 1018static void test_america_st_johns() {1019 // A more typical entry,1020 // Uses letters both when DST is active and not and has multiple1021 // letters. Uses negative offsets.1022 // Switches several times between their own and Canadian rules1023 // Switches the stdoff from -3:30:52 to -3:30 while observing the same rule1024 1025 // Z America/St_Johns -3:30:52 - LMT 18841026 // -3:30:52 j N%sT 19181027 // -3:30:52 C N%sT 19191028 // ...1029 //1030 // R j 1917 o - Ap 8 2 1 D1031 // R j 1917 o - S 17 2 0 S1032 // R j 1919 o - May 5 23 1 D1033 // R j 1919 o - Au 12 23 0 S1034 // R j 1920 1935 - May Su>=1 23 1 D1035 // ...1036 //1037 // R C 1918 o - Ap 14 2 1 D1038 // R C 1918 o - O 27 2 0 S1039 // R C 1942 o - F 9 2 1 W1040 // ...1041 1042 using namespace std::literals::chrono_literals;1043 const std::chrono::time_zone* tz = std::chrono::locate_zone("America/St_Johns");1044 1045 assert_equal(1046 std::chrono::local_info(1047 std::chrono::local_info::unique,1048 std::chrono::sys_info(1049 std::chrono::sys_seconds::min(),1050 to_sys_seconds(1884y, std::chrono::January, 1d, 3h, 30min, 52s),1051 -(3h + 30min + 52s),1052 0min,1053 "LMT"),1054 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1055 tz->get_info(std::chrono::local_seconds::min()));1056 1057 assert_equal(1058 std::chrono::local_info(1059 std::chrono::local_info::unique,1060 std::chrono::sys_info(1061 std::chrono::sys_seconds::min(),1062 to_sys_seconds(1884y, std::chrono::January, 1d, 3h, 30min, 52s),1063 -(3h + 30min + 52s),1064 0min,1065 "LMT"),1066 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1067 tz->get_info(to_local_seconds(1883y, std::chrono::December, 31d, 23h, 59min, 59s)));1068 1069 assert_equal(1070 std::chrono::local_info(1071 std::chrono::local_info::unique,1072 std::chrono::sys_info(1073 to_sys_seconds(1884y, std::chrono::January, 1d, 3h, 30min, 52s),1074 to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s),1075 -(3h + 30min + 52s),1076 0min,1077 "NST"),1078 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1079 tz->get_info(to_local_seconds(1884y, std::chrono::January, 1d)));1080 1081 assert_equal(1082 std::chrono::local_info(1083 std::chrono::local_info::unique,1084 std::chrono::sys_info(1085 to_sys_seconds(1884y, std::chrono::January, 1d, 3h, 30min, 52s),1086 to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s),1087 -(3h + 30min + 52s),1088 0min,1089 "NST"),1090 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1091 tz->get_info(to_local_seconds(1917y, std::chrono::April, 8d, 1h, 59min, 59s)));1092 1093 assert_equal(1094 std::chrono::local_info(1095 std::chrono::local_info::nonexistent,1096 std::chrono::sys_info(1097 to_sys_seconds(1884y, std::chrono::January, 1d, 3h, 30min, 52s),1098 to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s),1099 -(3h + 30min + 52s),1100 0min,1101 "NST"),1102 std::chrono::sys_info(1103 to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s),1104 to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 52s),1105 -(2h + 30min + 52s),1106 60min,1107 "NDT")),1108 tz->get_info(to_local_seconds(1917y, std::chrono::April, 8d, 2h)));1109 1110 assert_equal(1111 std::chrono::local_info(1112 std::chrono::local_info::nonexistent,1113 std::chrono::sys_info(1114 to_sys_seconds(1884y, std::chrono::January, 1d, 3h, 30min, 52s),1115 to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s),1116 -(3h + 30min + 52s),1117 0min,1118 "NST"),1119 std::chrono::sys_info(1120 to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s),1121 to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 52s),1122 -(2h + 30min + 52s),1123 60min,1124 "NDT")),1125 tz->get_info(to_local_seconds(1917y, std::chrono::April, 8d, 2h, 59min, 59s)));1126 1127 assert_equal(1128 std::chrono::local_info(1129 std::chrono::local_info::unique,1130 std::chrono::sys_info(1131 to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s),1132 to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 52s),1133 -(2h + 30min + 52s),1134 60min,1135 "NDT"),1136 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1137 tz->get_info(to_local_seconds(1917y, std::chrono::April, 8d, 3h)));1138 1139 assert_equal(1140 std::chrono::local_info(1141 std::chrono::local_info::unique,1142 std::chrono::sys_info(1143 to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s),1144 to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 52s),1145 -(2h + 30min + 52s),1146 60min,1147 "NDT"),1148 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1149 tz->get_info(to_local_seconds(1917y, std::chrono::September, 17d, 0h, 59min, 59s)));1150 1151 assert_equal(1152 std::chrono::local_info(1153 std::chrono::local_info::ambiguous,1154 std::chrono::sys_info(1155 to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s),1156 to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 52s),1157 -(2h + 30min + 52s),1158 60min,1159 "NDT"),1160 std::chrono::sys_info(1161 to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 52s),1162 to_sys_seconds(1918y, std::chrono::April, 14d, 5h, 30min, 52s),1163 -(3h + 30min + 52s),1164 0min,1165 "NST")),1166 tz->get_info(to_local_seconds(1917y, std::chrono::September, 17d, 1h)));1167 1168 assert_equal(1169 std::chrono::local_info(1170 std::chrono::local_info::ambiguous,1171 std::chrono::sys_info(1172 to_sys_seconds(1917y, std::chrono::April, 8d, 5h, 30min, 52s),1173 to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 52s),1174 -(2h + 30min + 52s),1175 60min,1176 "NDT"),1177 std::chrono::sys_info(1178 to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 52s),1179 to_sys_seconds(1918y, std::chrono::April, 14d, 5h, 30min, 52s),1180 -(3h + 30min + 52s),1181 0min,1182 "NST")),1183 tz->get_info(to_local_seconds(1917y, std::chrono::September, 17d, 1h, 59min, 59s)));1184 1185 assert_equal(1186 std::chrono::local_info(1187 std::chrono::local_info::unique,1188 std::chrono::sys_info(1189 to_sys_seconds(1917y, std::chrono::September, 17d, 4h, 30min, 52s),1190 to_sys_seconds(1918y, std::chrono::April, 14d, 5h, 30min, 52s),1191 -(3h + 30min + 52s),1192 0min,1193 "NST"),1194 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1195 tz->get_info(to_local_seconds(1917y, std::chrono::September, 17d, 2h)));1196}1197 1198static void validate_transitions(const std::chrono::time_zone& zone) {1199 using namespace std::literals::chrono_literals;1200 1201 constexpr auto begin = std::chrono::time_point_cast<std::chrono::seconds>(1202 static_cast<std::chrono::sys_days>(std::chrono::year_month_day{first, std::chrono::January, 1d}));1203 constexpr auto end = std::chrono::time_point_cast<std::chrono::seconds>(1204 static_cast<std::chrono::sys_days>(std::chrono::year_month_day{last, std::chrono::January, 1d}));1205 1206 // Builds the set of sys_info objects for the selected time range.1207 std::vector<std::chrono::sys_info> input;1208 std::chrono::sys_seconds s = begin;1209 do {1210 input.emplace_back(zone.get_info(s));1211 s = input.back().end;1212 } while (s < end);1213 1214 for (auto previous = input.begin(), next = previous + 1; next != input.end(); ++previous, ++next) {1215 // Now iterates to all adjacent objects.1216 // For every transition gets the locate time of the1217 // - end of the first (a)1218 // - the start if the second (b)1219 // Depending on the difference between 'a' and 'b' different tests are done.1220 std::chrono::local_seconds end_previous{previous->end.time_since_epoch() + previous->offset};1221 std::chrono::local_seconds begin_next{next->begin.time_since_epoch() + next->offset};1222 1223 if (end_previous == begin_next) {1224 // unique transition1225 // a |------------|1226 // b |----------|1227 // T1228 assert_equal(std::chrono::local_info(1229 std::chrono::local_info::unique,1230 *previous,1231 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1232 zone.get_info(end_previous - 1s));1233 1234 assert_equal(std::chrono::local_info(1235 std::chrono::local_info::unique,1236 *next,1237 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1238 zone.get_info(begin_next));1239 1240 } else if (end_previous < begin_next) {1241 // non-existent transition1242 // a |------------|1243 // b |----------|1244 // T T1245 assert_equal(std::chrono::local_info(1246 std::chrono::local_info::unique,1247 *previous,1248 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1249 zone.get_info(end_previous - 1s));1250 1251 assert_equal(std::chrono::local_info(std::chrono::local_info::nonexistent, *previous, *next),1252 zone.get_info(end_previous));1253 1254 assert_equal(std::chrono::local_info(std::chrono::local_info::nonexistent, *previous, *next),1255 zone.get_info(begin_next - 1s));1256 1257 assert_equal(std::chrono::local_info(1258 std::chrono::local_info::unique,1259 *next,1260 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1261 zone.get_info(begin_next));1262 1263 } else {1264 // ambiguous transition1265 // a |------------|1266 // b |----------|1267 // T T1268 assert_equal(std::chrono::local_info(1269 std::chrono::local_info::unique,1270 *previous,1271 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1272 zone.get_info(begin_next - 1s));1273 1274 assert_equal(std::chrono::local_info(std::chrono::local_info::ambiguous, *previous, *next),1275 zone.get_info(begin_next));1276 1277 assert_equal(std::chrono::local_info(std::chrono::local_info::ambiguous, *previous, *next),1278 zone.get_info(end_previous - 1s));1279 1280 assert_equal(std::chrono::local_info(1281 std::chrono::local_info::unique,1282 *next,1283 std::chrono::sys_info(std::chrono::sys_seconds(0s), std::chrono::sys_seconds(0s), 0s, 0min, "")),1284 zone.get_info(end_previous));1285 }1286 }1287}1288 1289int main(int, const char**) {1290 test_gmt();1291 test_local_time_out_of_range();1292 test_indian_kerguelen();1293 test_antarctica_rothera();1294 1295 test_asia_hong_kong();1296 test_europe_berlin();1297 test_europe_dublin();1298 test_america_st_johns();1299 1300 const std::chrono::tzdb& tzdb = std::chrono::get_tzdb();1301 for (const auto& zone : tzdb.zones) {1302 validate_transitions(zone);1303 }1304 1305 return 0;1306}1307