From 8fd5ec295a80d483fb1473c36cc20caf0a99f46a Mon Sep 17 00:00:00 2001 From: Bruno Tremblay Date: Wed, 25 Mar 2026 13:20:22 -0400 Subject: [PATCH 1/6] Squashed 'src/cctz/' changes from 182b96ca..00fc77b8 00fc77b8 Update zoneinfo files to 2026a (#339) 52f82e49 Fix cctz::format()/parse() to treat NULs like any other chars (#338) 58b6d4b4 Fixes cctz::parse() to reject input with embedded NULs (#337) 5a446d2f Remove unnecessary TODO (#335) 10993e26 Fix signed/unsigned mismatch warning with msvc (#334) cdaca908 CI Maintenence: (#336) 24f284d2 Update zoneinfo files to 2025c (#332) de801239 Ensure HAS_STRPTIME is defined by default (#331) 46d62c00 Fix -Wsign-compare and -Wundef warnings from clang on Windows (#330) 27ca1731 Reimplement GetWindowsLocalTimeZone without icu.h (#329) c6faf078 Optimize %F/%T format/parse (#322) 4a499021 Adds a time zone fuzz test (#326) d85cf7b2 Update the time_point used in Format.PosixConversions (#325) 67014858 Update the Bazel build for future compatibility (#324) d2f2abda Fix GCC attribute warning introduced by #319 (#320) cd757b1e Disable fsanitize=array-bounds for days_per_month (#319) 306fd9b3 Fix -Wsign-compare warning f8e494f0 Fix for "No Target Architecture" error (#317) 2ebbe0d8 Remove WinRT deps from `cctz::local_time_zone` (#316) 74e787f5 Fix typo (#314) 510f2208 Miscellaneous cleanup for MODULE.bazel and README.md (#312) 739fd5a8 Update zoneinfo files to 2025b (#310) 25e510fc CIFuzz: Update upload-artifact to v4 (#311) 1f2268a1 Update zoneinfo files to 2025a (#306) 70c3bd1a Revert "[fuchsia] Updates the FIDL bindings in Fuchsia-specific code (#302)" (#303) b98efcf0 [fuchsia] Updates the FIDL bindings in Fuchsia-specific code (#302) d1397431 Update zoneinfo files to 2024b (#300) 8bdbd840 Fix mingw compiler error due to missing function declaration (#297) 6624659e Add GitHub Actions CI (#299) 4f257821 Add support for Bzlmod (#296) 88b30979 Revert "Use reference in range-for with non trivial type (#294)" (#295) 151b37b4 Use reference in range-for with non trivial type (#294) 64d12062 [cmake] Find Benchmark quiet (#293) f62d7b77 [cmake] Require CMake 3.16 (#292) 5b5c77df Do not redefine _CRT_SECURE_NO_WARNINGS if it's defined (#289) bb0595b6 [Android] Remove unnecessary __system_property_get definition (#286) 2d9f3d01 Add support for DLLs on Windows (#285) 981dc6b1 Update zoneinfo files to 2024a (#284) 89d3c319 Update zoneinfo files to 2023d (#283) 2878b411 Stop trimming "redundant" trailing transitions. (#281) 2acd9f2b Add new tzdata path for Android (#279) b6d7a852 [fuchsia] Adds new tzdata dir, explains all dirs (#278) 65036e93 Bazel: Support header_modules, layering_check and parse_headers (#277) c8cd07ca test: trim the kTimeZoneNames[] lists to "real" zones (#276) ffce47e8 MSVC version greater 17.7.1 would give errors for civil_time_detail.h (#273) 1261fab0 Give FreeBSD the same treatment as OpenBSD re _XOPEN_SOURCE (#271) 17c7dbc8 Changes the Windows SDK version check to support MingW (#269) 04186a81 Extend transitions for 401 years (#268) 6355d604 Use a specific value (500) for _XOPEN_SOURCE (#266) 616401dc Revert "build: fix cross-platform android builds on OS X (#237)" (#264) f46ef8f5 Add a couple of direct-dependency includes (#263) 467c42af Add factory functions for named time zones (#262) e542de5f Streamline time_zone::Impl::UTCImpl to bypass general LoadTimeZone(). (#256) 2837e1be Fix missing include in time_zone.h (#261) b43d4d29 Add VxWorks support (#260) 13b90c85 Avoid implicit long -> int conversion when calling tm_gmtoff (#258) ac497c9e Fix the "libc:localtime" implementation (#257) ee249732 Explicit sign conversions on Windows (#255) 5ea90471 Fully qualify another instance of cctz::format() in time_zone_format_test.cc (#253) 1bb996ca local_time_zone: Add Windows support with WinRT (#242) 8b81c2e5 Fully qualify cctz::format in tests (#251) bb4d205e Prefer std::copy_n() over std::copy() where appropriate (#250) 6c9fa5e5 Correct a spelling mistake (#249) 1fb16492 Update zoneinfo files to 2023c. (#245) 4eda7435 Update zoneinfo files to 2023b. (#244) 1d3efe8b Update zoneinfo files to 2023a. (#243) 3803b961 Add an option to separate benchmark build from tests (#241) 49ba88fa Fix build on cygwin (#240) 790e1abe Update zoneinfo files to 2022g. (#239) 83ffd88d ci: add CIFuzz github action (#238) 54176545 build: fix cross-platform android builds on OS X (#237) c674330e Fix skipping unused portions in TimeZoneInfo::Load() for version 1 zonefiles. (#236) 6caa145a Update zoneinfo files to 2022f. (#235) 8b7632e8 cleanup: zic.c no longer tries to "WORK_AROUND_QTBUG_53071" (#234) c83606d3 Update zoneinfo files to 2022e. (#233) c2bbd835 Update zoneinfo files to 2022d. (#232) ec5d1d33 Fix a signedness conversion warning. (#231) dcb83e0c Update zoneinfo files to 2022c-1-gaca1a70. (#230) 022394a1 Update zoneinfo files to 2022c. (#228) e0494c62 Fix call placement of recently-introduced AllYearDST() (#229) e1524937 Start using the "backzone" file when building the testdata. (#227) 1c87d550 Update zoneinfo files to 2022b. (#226) c7c193f3 Buildfix OpenBSD. (#224) 9d47fcdb [fuchsia] Remove the dependency on the fdio library (#223) 5575351b Limit MakeTime.LocalTimeLibC test to GLIBC (#221) 2b003c42 Limit testing of extended format/parse specifiers to GLIBC (#220) 455b5f5c Add a NextTransition.Scan test case to time_zone_lookup_test. (#218) 15551f93 Update the script for generating testdata/zoneinfo. (#219) 467c50eb Update zoneinfo files to 2022a. (#217) 2d2bfe5b Replace NULL with nullptr (#216) b5546d7f Add missing #include for 'std::left'. (#215) 6921e4f8 Small microptimizations to year_index. (#209) 02918d62 Fix 32-bit ARM builds (#208) 18f5c213 [fuchsia] Fix bug in Fuchsia async code (#207) 793f7933 Update zoneinfo files to 2021e. (#206) 1bb06d9f Remove a few redundant calls to `unique_ptr.get()`: https://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-smartptr-get.html (#205) c93ba281 Update zoneinfo files to 2021d. (#204) 3e2b9048 Remove bazelbuild/rules_cc dependency (#203) 913019ee [reland] Add basic support for Fuchsia (#202) 769622e0 Avoid min()/max() macro conflicts (#201) 9af727a3 Breakdown the "seconds + femtoseconds => time_point" overflow issue. (#200) 556a1bc6 Update zoneinfo files to 2021c. (#198) b6e11eeb Update zoneinfo files to 2021b. (#197) da8be708 Use the Bazel @platforms repository for platform constraints (#196) 63b7130d Revert "Add basic support for Fuchsia (#189)" (#195) f6cef0a3 fix installation of dll on windows (#194) e2649a4c fix cross-build to iOS when tools are enabled (#193) e5b9c1c8 Updates the GoogleTest and Google Benchmark dependencies (#192) b86f0265 Fixes -Wrange-loop-construct warning in GCC 11 (#191) 31628f21 Move raw FILE* values into an auto-closing unique_ptr ASAP. (#190) 51a84719 Add basic support for Fuchsia (#189) 28334ea7 Fixes -Wrange-loop-construct warning in GCC 11 (#188) ed267413 Revert time_tool to use "localtime" for the local timezone. (#186) 583c52d1 Add support for cctz::load_time_zone("UTC0", &tz) (#185) 46251525 Update zoneinfo files to 2021a. (#184) 3eae9cae Update zoneinfo files to 2020f. (#183) 79e03767 Update zoneinfo files to 2020e. (#182) 98fb541c Fix tm_gmtoff build failure on AIX (#177) b1453a1d Update zoneinfo files to 2020d. (#175) 2934704a Workaround gcc-5.5 ICE bug. (#174) 3ab2dae7 Update zoneinfo files to 2020c. (#172) c8dbe1c4 Update zoneinfo files to 2020b. (#171) 8b443b39 Exports test suite for all our tests to other Bazel workspaces. (#170) e1bf5046 Disable a "libc:UTC" test expectation that fails on BSD systems (#166) 6cba7759 Update to a newer version of bazelbuild/rules_cc (#167) 9352dc28 Tie google/googletest and google/benchmark to a recent release (#168) da5a52d9 Removes license comment (#160) 0c3d6cd2 Succumb to the pressure of -Wshadow. (#159) 5dca604a Stick with uint_least8_t rather than a (possibly) narrowing conversion. (#157) 7853000b Fixes a few compile warnings (#156) 4c87213d handle "slim" TZif files in TimeZoneInfo::ExtendTransitions() (#155) e87b391f handle "slim" TZif files in TimeZoneInfo::ExtendTransitions() (#154) 8bb48f4f check for year overflow when parsing %U/%W conversions e74639b2 avoid year overflow (if possible) when normalizing a civil time (#152) 79d457bc avoid civil_day overflow when computing week numbers (#151) a2721107 Don't hold a lock while reading zoneinfo data (#149) 19556269 Support %U/%u and %W/%w specifiers in cctz::format() and cctz::parse() (#150) 2a910637 Mention 'z' and 'Z' as possible UTC offsets for cctz::parse() (#148) dfad4792 Use the new %ET format specifier in time_tool (#147) 2d6d54cf Adds support for MSVC 32-bit ARM platforms (#145) 24e9dcfb support parsing 'T' and 'Z' case insensitively (#144) 00f4089c Test with a new timezone, America/Nuuk, added in 2020a. (#141) f092f1e2 Update zoneinfo files to 2020a. (#140) 44541cf2 Cmake fixes (#135) d01654e0 style: make some allowances for -Wshadow (#133) a26bc5f2 We choose to pass cctz::civil_second by value. (#131) a1dc7108 Disables the zone_info_source extension under the MinGW compiler (#130) 7b847489 Defeat leak detectors in ClearTimeZoneMapTestOnly() (#129) cc84fe45 Modify how a zone-name "file:" prefix is discarded (#128) ac08afdb Fix a spelling error (#127) d78ebaaf Update zoneinfo files to 2019c (#126) b4935eef Load @rules_cc for compatibility with Bazel 1.0 (#125) f11e008c Fix SIOF issue by moving time_zone_mutex into function (#124) 1e7fb5e0 Ensure we don't call destructor for global static time_zone_mutex (#123) a66daf52 Set the correct union field for PosixTransition::N (#122) 742d3707 Update zoneinfo files to 2019b (#120) c73f8c9e Update #116 to use a civil_second parameter for get_{week,year}day() (#119) 8cabbb3f Avoid a "-Wshadow-uncaptured-local" warning (#118) ceb0539d Allow get_weekday() and get_yearday() to take all civil-time types (#116) 8800e59f Define _XOPEN_SOURCE to import strptime (#115) b8027cb6 Avoid strcpy() calls to quash MSVC warnings (#113) 74ca13c6 Reverse the checks for __has_attribute(weak) and _MSC_VER (#109) fcad8d7d Fix time_zone_libc.cc compilation error (#112) e50563d1 Add casts to suppress implicit-conversion-loss warnings (#111) ba90e43d Fix -Wunused-member-function warning. (#110) ce76fd46 Simplify the handling of the tm_gmtoff and tm_zone extension fields (#108) 30de25c8 Change the suggestions for the non-strict next/prev-weekday calls (#107) b9fd30b0 A 5X performance improvement in next_weekday()/prev_weekday() (#105) 4632ec21 Correct some BUILD formatting errors introduced in #102. (#104) 049e4b60 Cater to -Wundef by also checking defined() in #if tests (#103) b820d31e Link to CoreFoundation in time_zone (#102) 93f8d105 Update per-platform support for determining the local time zone (#101) 157a94af Update zoneinfo files to 2019a. (#100) 6548c6bd Remove use of CFStringGetCStringPtr (#99) 913f8422 Fix MacOS compilation (Fix #96) (#97) 65e6ffcb Use CFTimeZoneCopyDefault() instead of CFTimeZoneCopySystem() to allow overrides with CFTimeZoneSetDefault for tests (#95) 805a025a Make local_time_zone() work on iOS (#94) 01dbbed2 Updated HTTP URLs to HTTPS: Apache Headers and Miscellaneous URLs (#93) 6ad4fee5 Add pragma alternate name support for Windows ARM64 (#90) 901b0d87 Disable MakeTime.LocalTimeLibC on Android, where the heritage of the bionic tzdata, particularly that provided by the test environment, is questionable. a7edd280 Fixed build under MinGW. (#87) 57e07f2d Solve GCC warnings 493735f6 Add Asia/Qostanay to lists of known time zones. a9d1e18d Merge pull request #88 from sggts04/master 3976ca1d Fixed Grammer Mistake in Readme Example 2 1b9f55e6 Remove the (now) unused VersionCmp() from time_zone_format_test. 13bdd696 Update zoneinfo files to 2018i. 7efc590b Support multiple, comma-separated timezones in the --tz flag. Also add a new --fmt flag to override the cctz::format() format specifier. c18700a7 Add support for the %:z, %::z, and %:::z format specifiers. bc3eff4c Add a blank line to the end of the license file (for Abseil compat). 603d2e92 Harden civil_time_detail.h against platforms that #define min and max. b14d4c98 Remove a mod operation from get_weekday() by slightly increasing the size of the offset vector. 2cbee9fa Expand the TimeZoneLibC implementation to support SKIPPED and AMBIGUOUS civil_lookup values (although it is still necessarily incomplete). Also be more careful about the representable range of "time_t", "tm", and "time_point" values. bd1baeff Update zoneinfo files to 2018g-9-gf0d2759. e5ba9ead Update zoneinfo files to 2018f-1-g401c42d. cdd9939f The new test for overflow in "libc" timezones also does not apply when std::time_t is less than 64 bits wide. e8297fb8 Disable the new test for overflow in "libc" timezones on Windows. It seems that Microsoft doesn't believe in years past 3000. Let's hope they're mistaken. 228192d9 Merge pull request #83 from Mizux/master acd1b358 Remove the use of target_sources d201d04c Avoid integer overflow for large years in the "libc" timezones. 19efc141 Merge pull request #84 from tkoeppe/anon 412df1f3 [time_zone_posix.h] Replace "nested anonymous struct", which is not valid C++, with named types. d0f8d102 Update README.md 6f1642e7 Remove _SRCS variable and keep CCTZ_HDRS b7a2f3ce Avoid snprintf() in FixedOffsetToName() for performance reasons. 6cd87896 Add install rules to CMakelists.txt (Fix #82) 47a5b26f Add PUBLIC_HEADER properties to cctz library c665ac68 Add header files to cctz library a2acba29 Remove the references to some bygone interfaces in comments and benchmark names. 776e781b Avoid overflow on extreme year values in cctz::get_weekday() by mapping the year to an equivalent contemporary one. @@ -506,12 +506,8 @@ CONSTEXPR_F weekday get_weekday(const civil_day& cd) noexcept { 4801e708 Mark civil_time::max() and min() as constexpr functions. 6f2e06e1 Unify decl/defn parameter naming for {next,prev}_transition(). 340caa7a Make both the "32-bit tzdata" comments the same. da51548f Teach the NextTransition.AmericaNewYork test case about 32-bit tzdata, which only extends back to 1901-12-13T20:45:52+00:00. cf42d801 Remove undesirable include of "time_zone_impl.h". 4e3dc522 Add cctz::time_zone member functions next_transition(), prev_transition(), version(), and description(). The first two can be used to enumerate the offset-transition points in a time zone. The latter two give descriptive text about a time zone. Note that all these new interfaces should only be used for informational purposes. cd6aeff6 Mark the civil_time friend declarations as CONSTEXPR_F (function) instead of CONSTEXPR_M (member). eb1b8121 Remove the redundant "inline"s from the friend definitions of the civil_time binary arithmetic operators. Also always use pass by value. 81f9be42 Assume that gcc supports __attribute__((weak)). 6896a516 Allow for platforms that do not support __attribute__((weak)). 2005efab Switch from cctz::sys_seconds to cctz::seconds for the 64-bit, seconds-resolution duration. The "sys" part was an historical artifact. 4e190dce Tweak some test cases to allow for running in Android environments with old tzdata. In general we want to run tests using the fresh data from testdata/zoneinfo, but this is difficult for Android. c4b1b273 Merge pull request #77 from astrelni/benchmark_target 50b8b08e Remove extra newline at eof. 8b0e0f90 Update benchmark source file name to match new target name. 3517257f Update benchmark target for consistency with other google projects. 52c2e4f1 Make a similar allowance in the ExtendedSecondOffset test case when looking for local mean time in Europe/Moscow as we did for America/New_York. (The Moscow test fails using Android tzdata.) 8fdbf255 Merge pull request #76 from astrelni/workspace 281027b5 Update benchmark http_archive name to match benchmark WORKSPACE name ad660f84 Update WORKSPACE; google/benchmark has bazel support a2dd3d0f Update time-zone lists to match 2018e-2-g99dd695 testdata. cf31b098 Update zoneinfo files to 2018e-2-g99dd695. 3f8873a5 Merge pull request #74 from rongjiecomputer/constexpr f5efbbac Merge branch 'master' into constexpr d5a783db Simplify macros 804fef2c Enable C++14 contsexpr for Visual Studio 2017 and above 2408b22f Change the abbreviations for fixed-offset time zones to use the same syntax as named time zones with numeric-style abbreviations. For example, fixed_time_zone(hours(12) + minutes(45)) will use "+1245" just like Pacific/Chatham. de72db74 Declare the tz2017b release are ubiquitous, so re-enable the test. 7b9a73fb Add a note about the possible future use of the RFC3339 "Unknown Local Offset Convention" when loading the local time zone fails. 7d18cd24 Enable C++14 constexpr for more compilers 46dcee9b Generalize references to third_party/tz. 6ace0133 Move to DATAFORM=vanguard to use the latest, bleeding-edge data format. 3eee631c Remove mention of US/Pacific-New, which we no longer generate. 62917470 Update zoneinfo files to 2018d-1-g260ea0d. 919dcce6 Merge pull request #73 from sbc100/fix_wasm_build 2dd8e023 Fix native WebAssembly emscripten build d541fda6 Fix location of "_MSC_VER" comment. dda20f80 Relax the Format.ExtendedSecondOffset test to allow for zoneinfo files, such as on OSX, that do not list the 1883-11-18 transition off local mean time in America/New_York. 19bf53d2 Remove some unnecessary qualification of cctz::year_t. This makes some upstream transformations a little easier. 7a155f5e Start using %E*z in time_tool. Also, parsing of civil times should be done using utc_time_zone(), not the zone from the command line. b4a53f10 Add support for the %E*z cctz::format() specifier, which renders the UTC offset with resolution to the second. That is, [-+]hh:mm:ss. In contrast, the existing %Ez truncates to the minute. 9fbe363e Merge pull request #71 from sigmoidal/master 8768b6d0 BUILD_TOOLS option added to switch on/off compilation of executable tools. e19879df Update zoneinfo files and tzfile.h to 2018c-20-ga6cc661. For the time being we comment out the tests for pre-1913 offsets in America/Jamaica. 7a97a6f7 Add the -pthread link option to the "benchmark" library. I'm not sure what the right fix is here, but this works for now. 2b51f4a1 Add copyright headers to benchmarks.cc and civil_time_detail.cc. 8aa5b777 Run CONTRIBUTING.md through mdformat. cab5d98d Update zoneinfo files to 2018c. 291a51d1 Merge pull request #66 from suertreus/patch-1 a3ce88d8 Add a workspace() rule with the project name to the WORKSPACE file 708483db Given the recent reinterpretation of "IST" in post-1968 Europe/Dublin as "Irish Standard Time" but still prevailing during the summer months, with the "daylight saving time" applying during the winter months using a negative delta, it is no longer accurate to think of the STD->DST transition as occurring in Spring and the DST->STD transition as occurring in Autumn. So, let's avoid using those labels. 017e6857 Allow for __system_property_get() being hidden in Android 'L' and beyond. 36a8fffa Update the "currently known to work on" documentation. Also fix a signature to be consistent with local style. 9cff736c Add support for reading Bionic-style tzdata files and for obtaining the local time-zone name from the "persist.sys.timezone" system property. aee90961 mdformat --in_place README.md. 2c07467b Don't even try to parse %C/%y or %EC/%Ey format specifiers. Until we do something to group them, they will never work. a9e322de Avoid duplication of CivilTime.Difference test-case name. 8bcfadd3 React to commit 5b2c086 to google/benchmark, "Enforce using a semicolon after BENCHMARK_MAIN to remove compiler warnings." 1e5d7938 Merge pull request #64 from Sarcasm/master 9fd5fdbc CMake: remove getopt checking code, time_tool no longer requires it 93f34591 README.md: fix broken numbered list a82ef3ea use FeatureSummary to handle require packages a25e2ba6 Run mdformat after the recent changes to README.md. 4f1803d0 Remove from src/time_tool.cc by manually handling the command-line options. This is for the same of portability. ecb90a9b Reduce the number of TimeZones.LoadZonesConcurrently threads (from 256 to 128) for portability reasons. a59b930a Merge pull request #54 from Sarcasm/master 03db0263 CMake: use target_compile_features(... cxx_std_11) when available 41f2ef80 FindGMock.cmake: put GMOCK_LIBRARY as first argument after DEFAULT_MSG b28cf201 Revert "CMake: add CMake "workspace" project to build cctz and its dependencies" 4d6cb4a2 CMake: changes after review from @Sydius 793f6327 CMake: add CMake "workspace" project to build cctz and its dependencies 79c7c0ad CMake: remove install target 0225120c CMake: specify C++ standard per-target f6b2a6a4 CMake: remove -fcolor-diagnostics Ninja workaround 03f13276 add CMake support 4f9776a3 Avoid weak vtables (see clang's -Wweak-vtables) by making the destructors of TimeZoneIf and ZoneInfoSource "key" functions. 9715eea4 Add 2017c zoneinfo files to CCTZ for possible use on systems that don't have their own (like Windows). They are also useful for hermetic testing. f1776e91 Suppress testing of %c in FormatParse.RoundTrip on Windows. 47f500e7 Merge pull request #59 from google/fix-benchmarks 95494374 formatted build content b8e502b1 Fixed GoogleBenchmarks build to work on Windows 15d0cc7f Merge pull request #58 from dcower/patch-1 4cd2f98b Fix ambiguous conditional expression via Clang+Windows 3441e339 Tag the time_tool target as "manual". It currently is not portable due to its use of . bc83a60d Fix problem with strptime() emulation when the entire input is consumed. Add internal support for %% parsing/formatting and %e parsing. Expect %x to match either M/D/Y or D/M/Y. 9e7f637e Merge pull request #55 from kant/patch-1 b339a311 Minor fixes (proposal) 12025d64 Define _CRT_SECURE_NO_WARNINGS in the same way as you would get from -D_CRT_SECURE_NO_WARNINGS on the command line (i.e., as 1), the goal being to avoid a redefinition warning. 52564b2c Add a user-defined default constructor for cctz::time_zone instead of using the compiler-generated one and in-class initialization. This avoids a (somewhat bogus) "default initialization of an object of const type without a user-provided default constructor" error when declaring a (somewhat useless, but tested for) const cctz::time_zone. 90bf1bdd Change the MakeTime.SysSecondsLimits test case to use fixed-offset zones for far-east/west conversions. Pacific/Apia and America/Dawson both have transitions before time_t(-2147483648) that are not represented in the macOS zoneinfo files, so conversions in the distant past will give unexpected results when using that data. Fixed zones sidestep the issue. d5e227e6 Merge pull request #51 from mwinterb/vs2017-codegen-fix 809b420e Declaring kDigits static to avoid a codegen bug in VS2017. 149b2995 Removed incorrect slash after 5b17020a Moves includes into a "cctz" subdirectory. 0e2dd887 Change "BaseTime" to "CCTZ" in benchmark names. f2bdef96 Merge pull request #50 from gennadiycivil/master 8f71aaa5 Switch to googletest provided bazel build files bd0f9066 Fixed some compilation issues on windwos 2e86a776 Merge pull request #48 from sheu-google/master 416ce790 Fix extern declaration of default_factory with initializer 0a5cc500 Optimize cctz::get_weekday(), cctz::get_yearday(), and civil_time construction with "day" values in the previous year (-365 < d <= 0). Also add a temporary optimization for converting contemporary times in fixed-offset zones. 237c3357 Parameterize the BM_Format_{Format,Parse}Time benchmarks by the format string. This will provide better insight into performance changes. Also delete the redundant BM_Format_RoundTrip* benchmarks. c7675c3b Add a new TimeZoneInfo::LocalTime() overload that takes the prevailing Transition. This means we need only perform a single addition in the civil_second domain during an absolute lookup(). 1912dee9 Remove some trailing white space from lines in README.md. e27a6f12 Fix the civil_time.h link in README.md. ff4b7ae8 Add benchmarks for civil_time.h interfaces. b6ac6bf6 BUILD changes that should have been part of the last commit. 2de157c7 Add benchmarks for time_zone.h interfaces. 75f1f882 added testonly attribute to benchmarks binary 7da4b9f6 Moved benchmarks to their own file/target 8422279e Adds support for benchmarking e563641e Allow a small number of failures in TimeZones.LoadZonesConcurrently to account for skew between the contents of kTimeZoneNames and the zoneinfo data source. 94c76d44 Add "zdump" support to time_tool. a72d6448 cctz::time_zone::lookup(const time_point&) should floor its argument rather than truncate it. The "zero" time_point has no special significance. a5478b94 Add mangled symbol names for _MSC_VER/_M_IX86. f7e17e7e Correct the Windows weak-symbol names. 05f52fe8 Add support for user-supplied sources of zoneinfo data. 5e7c6944 Tidy up some more #include lines. 65554a3f Don't ignore an empty ${TZ} in local_time_zone() and just allow "${TZDIR}/" to fallback to UTC, which will match "env TZ= date". 7c9a405f Tidy up some #include lines. 45e6c87a Fix the dependencies of a couple of examples, the includes of a couple of tests, and some recently added, overly long lines. 669b9d33 Merge pull request #45 from gabeschine/master 7185fc7f Guard get_offset_abbr() impls in src/time_zone_libc.cc 8d4b2a56 Move the handling of "localtime" (which typically maps to /etc/localtime) to local_time_zone(), where ${TZ} was already handled. This means that load_time_zone("localtime", &zone) will only look for ${TZDIR}/localtime. 58b88861 Avoid the non-portable %F and %T format specifiers in the examples. 8775f882 Simplify the wrapping of strerror_r(). ecee594c reserves space for format's result string ac5c51a4 Tweak the new cctz::fixed_time_zone() to take a duration instead of a raw count of seconds. 3daf1638 removes accidental blank line 2c890264 Added overflow checking to parse() 65e40c90 Avoid std:: qualifying snprintf() for the time being. 1fa607b3 Remove TAB character that slipped in during previous commit. 2d4e939a Add support for time zones that are fixed offsets (<=24h) from UTC. b9c7ea8a The 2017b tzdata release moved the shift from -004430 to +00 from 1972-05-01 to 1972-01-07, so we temporarily accept both outcomes until 2017b is ubiquitous. 3db86d49 Define the behavior of cctz::time_zone::lookup(const civil_second&) when the argument civil_second is beyond the representable range of the time_point results. The results will be saturated. 10c18558 Parse a civil-time argument with respect to the flag-specified time zone, not UTC. This makes a difference when we are at the extremes of the representable range. 15d4a35f Update test case TimeZoneEdgeCase.AfricaMonrovia for tzdata 2017b. 5759ba55 Now that we have in-class initializers for TimeZoneInfo::local_time_hint_ and time_local_hint_, we don't need any dynamic initialization. 1f928b3e Remove remnant references to DateTime. 52f18a07 Change the civil-time index into the transitions vector from the 64-bit DateTime to a cctz::civil_second. This allows us to reach the extremities of 64-bit timestamps in all time zones. 83069901 Inline the civil-time relational operators. 68d8e15a Merge pull request #41 from proller/patch-1 7461a4be Added an error out-param to detail::parse() 5c02ff35 fix valgrind/s Conditional jump or move depends on uninitialised value(s) b7662bca Don't call UTCImpl(), which might initialize a function-local static, while holding time_zone_mutex. This avoids a deadlock on a platform that shall go nameless. 27cbf5ab Change cctz::time_zone::absolute_lookup::abbr from a std::string to a const char*. This is an interface change, but it allows cctz::time_zone::lookup(time_point) to guarantee that it does no memory allocations. 38174cf0 Refactored platform #ifdefs to use sfinae to be a bit more robust a3e0f5ca Avoid using a global civil_second (at least until it can be constexpr). 24d310d2 Stop comparing zone abbreviations until tzdata changes settle down. 6e29f905 Make the n_sec() normalization optimization a little clearer. cce7cecd Update tzfile.h to 2017a release. 598e92c7 Added header guard to civil_time_detail.h d3fc80bd Avoid any possibility of a signed/unsigned comparison warning. Also fix an issue should int_fastXX_t be larger then XX bits. 3f701349 Removed now unneeded includes 5572fa35 added section separator 6a11c32f Moved civil-time output streaming to src/civil_time_detail.cc 1338f4d1 Stop assuming that a zoneinfo file with a future rule will end with two transitions in the same calendar year ... this will no longer be true in the upcoming tzdata release. 79ddaf6c addes OFFSET()/ABBR() defines for myriad2 processors fca4cd45 Made the errnum->string logic more robust 6c7526b3 Fix cut-and-paste error in previous commit. 71b4c066 Avoid INT*_{MIN,MAX} for portability reasons. 248892dc Add explicit but safe narrowing/sign casts to silence -Wconversion. 86f216aa Removed linkopt for libm, which is no longer needed 8ad10a03 Stopped linking against pthread, because I don't see why it's needed and it breaks on some platforms 70f46f05 Add ANDROID conditionals for strerror_r() and tm_{gmtoff,zone}. 6b0c1879 Add __FreeBSD__ conditionals for strerror_r and tm_gmtoff/zone. Thanks to Rainer Hurling. 9f1f7397 Use TimeZoneInfo::Load()::bp (in an assert) before it dies in order to quash a "Value stored to 'bp' is never read" warning from the clang static analyzer. Thanks to Siesh1oo. a8563087 Prepare for an upcoming change to third_party/tz/tzfile.h. a3294e3d Optimize civil_time (non-constexpr) construction when the fields are already normalized. 90ef68be Some requested changes to the Makefile. 44d0052e Comment out recently added zones from time_zone_lookup_test in deference to slightly out-of-date zoneinfo installations. 2c5612ca Support parsing year values beyond the width of tm_year. cce8c5b6 Ensure that there are always transitions in the first and second half of the time line so that the signed difference between a DateTime and the DateTime of its previous transition is always representable, without overflow and without (for now) extended precision. bc607f60 Eliminate the possibility of intermediate overflow when calculating civil_time differences. Add test cases that would have previously produced over/underflow even though the final result was representable. c54f233b Fix a problem with Decode32() when std::int_fast32_t is wider than 32 bits. c318823e Eliminate a gratuitous difference between internal and external. 26449a64 Resolve TODO regarding overflow in (civil_day - civil_day). 1f0b1f01 Trim redundant transitions instead of just skipping over them when looking for extension transition types. This avoids a problem when the first future-specification transition occurs before the (y2038_boundary - 1) transition added to workaround Qt bug 53071. a914620c Tweak type of default_transition_type_, and a couple of comments. 0d2b3a95 Avoid fixed-sized typedefs. b2b2f7ac Add time_zone::name() and support for time_zone equality. 1e943a32 Use the int_fastN_t types for PosixTransition. Size is secondary. 6e09ceb3 Increase the resolution of the internal format/parse functions. 04278e70 Sub-nanoseconds are useless when converting to time_point. These were remnants of the original implementation. 748f94e9 Deleted the CCTZ v1 API 6cbb3ef9 Don't complain if a zoneinfo file does not contain a future rule. 6a694a40 Convert TimeInfo usage to time_zone::civil_lookup. 026a56c6 Avoid possible integer overflow by adding the UTC offset in the civil_second domain. f8f99963 Rename "tp" to "sec" within parse(). 05cc5926 Guarantee that time_point::rep is at least 64 bits. Also add a TODO about parsing large year values. 60d37ed8 Convert Breakdown usage to time_zone::absolute_lookup now that the later supports 64-bit years. bd0df018 Start using civil_time in the time_zone implementation. 66a06c45 Expand civil_time to cover the full range of a 64-bit time_t. cde4bae1 Remove some now-unnecessary year narrowing. Also pass civil_second by reference to time_zone::Impl::MakeTimeInfo(). 837fb199 Move to 64-bit years in civil_time. This allows, for example, a civil_second to represent all the values covered by a 64-bit time_t. 7e3af344 Avoid overflow on civil_month(, 12). c2775b87 Avoid -t flag to install. Add Linux shared-library example. 7d49f0fe Add SHARED_LDFLAGS for CCTZ_SHARED_LIB linking. 5362a831 Use install instead of mkdir/cp. Remove shared-library versioning. Make install_shared_lib an independent target. 2e83ff2e A little Makefile cleanup. 5c54e2a1 Merge pull request #30 from vcatechnology/shared-library-makefile 120694ca int64_t -> std::int64_t. 5e37bb9f Add a new install_shared_lib target fac30f99 Added the libcctz.so target to the Makefile 5a972154 Support DESTDIR in Makefile 3cde9098 Mention the test, tools, and examples object files explicitly so they are created separately and so the generated dependencies are correct. 4b7a168d When extending the compiled transitions using the POSIX-style future rule, search for the last two distinct transition types rather than assuming that the last two transitions already have distinct types. 9fb6bcb9 Use function-local static initialization instead of std::call_once(). Change time_zone_map to an unordered_map, and which does not include the UTC zone. 4b7f6745 Update tests for new-style abbreviations (e.g., +05). a9cefbe4 adds a license directive to the BUILD file 50745f69 Disallows difference between differently aligned civil-time types e887dac7 Use _MSC_VER to detect Windows compilation environments. 6bff5662 Also use tm_{gmtoff,zone} under linux/__USE_MISC. 72d74a72 Updates to the "install" rule. - Make "sudo" optional. - Try to make the destination directories. - Rework so that the sources are VPATH expanded. 03a14dc3 Remove weekday and yearday from cctz::Breakdown. These are now exposed as functions on cctz::civil_day. 635f4fe0 Add %E*f and %E#f support to cctz::format() and parse(). These specifiers deal with only the subsecond part of the time. For a non-zero subsecond, "%E*S" == "%S.%E*f". Like the "ES" formats, # behaves exactly like * on input. d32d4e37 Add some casts during safe narrowing conversions. 61415a09 Fix some issues with the Windows build. b3610ccc Linkified some file paths. git-subtree-dir: src/cctz git-subtree-split: 00fc77b843504f231f89c13eff86327c444094e8 --- .github/workflows/ci.yaml | 167 ++ .github/workflows/cifuzz.yml | 24 + .gitignore | 1 + BUILD | 154 +- CMakeLists.txt | 198 +++ CONTRIBUTING.md | 26 +- LICENSE.txt | 5 +- MODULE.bazel | 41 + Makefile | 80 +- README.md | 136 +- WORKSPACE | 6 - cmake/cctz-config.cmake | 1 + cmake/modules/FindGMock.cmake | 41 + examples/CMakeLists.txt | 27 + examples/classic.cc | 17 +- examples/epoch_shift.cc | 11 +- examples/example1.cc | 10 +- examples/example2.cc | 4 +- examples/example3.cc | 11 +- examples/example4.cc | 15 +- examples/hello.cc | 10 +- include/{ => cctz}/civil_time.h | 14 +- include/cctz/civil_time_detail.h | 606 +++++++ include/cctz/time_zone.h | 452 ++++++ include/cctz/zone_info_source.h | 88 + include/civil_time_detail.h | 511 ------ include/time_zone.h | 283 ---- src/cctz.h | 162 -- src/cctz_benchmark.cc | 434 +++++ src/cctz_v1_test.cc | 1135 ------------- src/civil_time_detail.cc | 86 + src/civil_time_test.cc | 218 ++- src/test_time_zone_names.cc | 509 ++++++ src/test_time_zone_names.h | 25 + src/time_tool.cc | 388 ++++- src/time_zone_fixed.cc | 134 ++ src/time_zone_fixed.h | 45 + src/time_zone_format.cc | 744 ++++++--- src/time_zone_format_test.cc | 1357 ++++++++++++---- src/time_zone_fuzz_test.cc | 76 + src/time_zone_if.cc | 21 +- src/time_zone_if.h | 87 +- src/time_zone_impl.cc | 130 +- src/time_zone_impl.h | 49 +- src/time_zone_info.cc | 1422 +++++++++-------- src/time_zone_info.h | 133 +- src/time_zone_libc.cc | 411 +++-- src/time_zone_libc.h | 32 +- src/time_zone_lookup.cc | 206 ++- src/time_zone_lookup_test.cc | 1356 +++++++--------- src/time_zone_name_win.cc | 176 ++ src/time_zone_name_win.h | 29 + src/time_zone_posix.cc | 20 +- src/time_zone_posix.h | 50 +- src/tzfile.h | 124 +- src/zone_info_source.cc | 72 + testdata/README.zoneinfo | 38 + testdata/version | 1 + testdata/zoneinfo/Africa/Abidjan | Bin 0 -> 130 bytes testdata/zoneinfo/Africa/Accra | Bin 0 -> 700 bytes testdata/zoneinfo/Africa/Addis_Ababa | Bin 0 -> 151 bytes testdata/zoneinfo/Africa/Algiers | Bin 0 -> 470 bytes testdata/zoneinfo/Africa/Asmara | Bin 0 -> 170 bytes testdata/zoneinfo/Africa/Asmera | Bin 0 -> 170 bytes testdata/zoneinfo/Africa/Bamako | Bin 0 -> 158 bytes testdata/zoneinfo/Africa/Bangui | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/Banjul | Bin 0 -> 168 bytes testdata/zoneinfo/Africa/Bissau | Bin 0 -> 149 bytes testdata/zoneinfo/Africa/Blantyre | Bin 0 -> 165 bytes testdata/zoneinfo/Africa/Brazzaville | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/Bujumbura | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/Cairo | Bin 0 -> 1309 bytes testdata/zoneinfo/Africa/Casablanca | Bin 0 -> 1919 bytes testdata/zoneinfo/Africa/Ceuta | Bin 0 -> 562 bytes testdata/zoneinfo/Africa/Conakry | Bin 0 -> 158 bytes testdata/zoneinfo/Africa/Dakar | Bin 0 -> 149 bytes testdata/zoneinfo/Africa/Dar_es_Salaam | Bin 0 -> 161 bytes testdata/zoneinfo/Africa/Djibouti | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/Douala | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/El_Aaiun | Bin 0 -> 1830 bytes testdata/zoneinfo/Africa/Freetown | Bin 0 -> 324 bytes testdata/zoneinfo/Africa/Gaborone | Bin 0 -> 180 bytes testdata/zoneinfo/Africa/Harare | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/Johannesburg | Bin 0 -> 190 bytes testdata/zoneinfo/Africa/Juba | Bin 0 -> 458 bytes testdata/zoneinfo/Africa/Kampala | Bin 0 -> 182 bytes testdata/zoneinfo/Africa/Khartoum | Bin 0 -> 458 bytes testdata/zoneinfo/Africa/Kigali | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/Kinshasa | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/Lagos | Bin 0 -> 180 bytes testdata/zoneinfo/Africa/Libreville | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/Lome | Bin 0 -> 130 bytes testdata/zoneinfo/Africa/Luanda | Bin 0 -> 146 bytes testdata/zoneinfo/Africa/Lubumbashi | Bin 0 -> 150 bytes testdata/zoneinfo/Africa/Lusaka | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/Malabo | Bin 0 -> 150 bytes testdata/zoneinfo/Africa/Maputo | Bin 0 -> 131 bytes testdata/zoneinfo/Africa/Maseru | Bin 0 -> 157 bytes testdata/zoneinfo/Africa/Mbabane | Bin 0 -> 133 bytes testdata/zoneinfo/Africa/Mogadishu | Bin 0 -> 161 bytes testdata/zoneinfo/Africa/Monrovia | Bin 0 -> 164 bytes testdata/zoneinfo/Africa/Nairobi | Bin 0 -> 191 bytes testdata/zoneinfo/Africa/Ndjamena | Bin 0 -> 160 bytes testdata/zoneinfo/Africa/Niamey | Bin 0 -> 169 bytes testdata/zoneinfo/Africa/Nouakchott | Bin 0 -> 158 bytes testdata/zoneinfo/Africa/Ouagadougou | Bin 0 -> 130 bytes testdata/zoneinfo/Africa/Porto-Novo | Bin 0 -> 150 bytes testdata/zoneinfo/Africa/Sao_Tome | Bin 0 -> 173 bytes testdata/zoneinfo/Africa/Timbuktu | Bin 0 -> 158 bytes testdata/zoneinfo/Africa/Tripoli | Bin 0 -> 431 bytes testdata/zoneinfo/Africa/Tunis | Bin 0 -> 449 bytes testdata/zoneinfo/Africa/Windhoek | Bin 0 -> 638 bytes testdata/zoneinfo/America/Adak | Bin 0 -> 969 bytes testdata/zoneinfo/America/Anchorage | Bin 0 -> 977 bytes testdata/zoneinfo/America/Anguilla | Bin 0 -> 130 bytes testdata/zoneinfo/America/Antigua | Bin 0 -> 149 bytes testdata/zoneinfo/America/Araguaina | Bin 0 -> 592 bytes .../zoneinfo/America/Argentina/Buenos_Aires | Bin 0 -> 708 bytes testdata/zoneinfo/America/Argentina/Catamarca | Bin 0 -> 708 bytes .../zoneinfo/America/Argentina/ComodRivadavia | Bin 0 -> 708 bytes testdata/zoneinfo/America/Argentina/Cordoba | Bin 0 -> 708 bytes testdata/zoneinfo/America/Argentina/Jujuy | Bin 0 -> 690 bytes testdata/zoneinfo/America/Argentina/La_Rioja | Bin 0 -> 717 bytes testdata/zoneinfo/America/Argentina/Mendoza | Bin 0 -> 708 bytes .../zoneinfo/America/Argentina/Rio_Gallegos | Bin 0 -> 708 bytes testdata/zoneinfo/America/Argentina/Salta | Bin 0 -> 690 bytes testdata/zoneinfo/America/Argentina/San_Juan | Bin 0 -> 717 bytes testdata/zoneinfo/America/Argentina/San_Luis | Bin 0 -> 717 bytes testdata/zoneinfo/America/Argentina/Tucuman | Bin 0 -> 726 bytes testdata/zoneinfo/America/Argentina/Ushuaia | Bin 0 -> 708 bytes testdata/zoneinfo/America/Aruba | Bin 0 -> 151 bytes testdata/zoneinfo/America/Asuncion | Bin 0 -> 1085 bytes testdata/zoneinfo/America/Atikokan | Bin 0 -> 224 bytes testdata/zoneinfo/America/Atka | Bin 0 -> 969 bytes testdata/zoneinfo/America/Bahia | Bin 0 -> 682 bytes testdata/zoneinfo/America/Bahia_Banderas | Bin 0 -> 700 bytes testdata/zoneinfo/America/Barbados | Bin 0 -> 278 bytes testdata/zoneinfo/America/Belem | Bin 0 -> 394 bytes testdata/zoneinfo/America/Belize | Bin 0 -> 1045 bytes testdata/zoneinfo/America/Blanc-Sablon | Bin 0 -> 205 bytes testdata/zoneinfo/America/Boa_Vista | Bin 0 -> 430 bytes testdata/zoneinfo/America/Bogota | Bin 0 -> 179 bytes testdata/zoneinfo/America/Boise | Bin 0 -> 999 bytes testdata/zoneinfo/America/Buenos_Aires | Bin 0 -> 708 bytes testdata/zoneinfo/America/Cambridge_Bay | Bin 0 -> 883 bytes testdata/zoneinfo/America/Campo_Grande | Bin 0 -> 952 bytes testdata/zoneinfo/America/Cancun | Bin 0 -> 538 bytes testdata/zoneinfo/America/Caracas | Bin 0 -> 190 bytes testdata/zoneinfo/America/Catamarca | Bin 0 -> 708 bytes testdata/zoneinfo/America/Cayenne | Bin 0 -> 151 bytes testdata/zoneinfo/America/Cayman | Bin 0 -> 149 bytes testdata/zoneinfo/America/Chicago | Bin 0 -> 1754 bytes testdata/zoneinfo/America/Chihuahua | Bin 0 -> 691 bytes testdata/zoneinfo/America/Ciudad_Juarez | Bin 0 -> 718 bytes testdata/zoneinfo/America/Coral_Harbour | Bin 0 -> 224 bytes testdata/zoneinfo/America/Cordoba | Bin 0 -> 708 bytes testdata/zoneinfo/America/Costa_Rica | Bin 0 -> 232 bytes testdata/zoneinfo/America/Coyhaique | Bin 0 -> 1362 bytes testdata/zoneinfo/America/Creston | Bin 0 -> 158 bytes testdata/zoneinfo/America/Cuiaba | Bin 0 -> 934 bytes testdata/zoneinfo/America/Curacao | Bin 0 -> 151 bytes testdata/zoneinfo/America/Danmarkshavn | Bin 0 -> 447 bytes testdata/zoneinfo/America/Dawson | Bin 0 -> 1029 bytes testdata/zoneinfo/America/Dawson_Creek | Bin 0 -> 683 bytes testdata/zoneinfo/America/Denver | Bin 0 -> 1042 bytes testdata/zoneinfo/America/Detroit | Bin 0 -> 899 bytes testdata/zoneinfo/America/Dominica | Bin 0 -> 130 bytes testdata/zoneinfo/America/Edmonton | Bin 0 -> 970 bytes testdata/zoneinfo/America/Eirunepe | Bin 0 -> 436 bytes testdata/zoneinfo/America/El_Salvador | Bin 0 -> 176 bytes testdata/zoneinfo/America/Ensenada | Bin 0 -> 1367 bytes testdata/zoneinfo/America/Fort_Nelson | Bin 0 -> 1448 bytes testdata/zoneinfo/America/Fort_Wayne | Bin 0 -> 531 bytes testdata/zoneinfo/America/Fortaleza | Bin 0 -> 484 bytes testdata/zoneinfo/America/Glace_Bay | Bin 0 -> 880 bytes testdata/zoneinfo/America/Godthab | Bin 0 -> 965 bytes testdata/zoneinfo/America/Goose_Bay | Bin 0 -> 1580 bytes testdata/zoneinfo/America/Grand_Turk | Bin 0 -> 853 bytes testdata/zoneinfo/America/Grenada | Bin 0 -> 130 bytes testdata/zoneinfo/America/Guadeloupe | Bin 0 -> 130 bytes testdata/zoneinfo/America/Guatemala | Bin 0 -> 212 bytes testdata/zoneinfo/America/Guayaquil | Bin 0 -> 179 bytes testdata/zoneinfo/America/Guyana | Bin 0 -> 181 bytes testdata/zoneinfo/America/Halifax | Bin 0 -> 1672 bytes testdata/zoneinfo/America/Havana | Bin 0 -> 1117 bytes testdata/zoneinfo/America/Hermosillo | Bin 0 -> 258 bytes .../zoneinfo/America/Indiana/Indianapolis | Bin 0 -> 531 bytes testdata/zoneinfo/America/Indiana/Knox | Bin 0 -> 1016 bytes testdata/zoneinfo/America/Indiana/Marengo | Bin 0 -> 567 bytes testdata/zoneinfo/America/Indiana/Petersburg | Bin 0 -> 683 bytes testdata/zoneinfo/America/Indiana/Tell_City | Bin 0 -> 522 bytes testdata/zoneinfo/America/Indiana/Vevay | Bin 0 -> 369 bytes testdata/zoneinfo/America/Indiana/Vincennes | Bin 0 -> 558 bytes testdata/zoneinfo/America/Indiana/Winamac | Bin 0 -> 603 bytes testdata/zoneinfo/America/Indianapolis | Bin 0 -> 531 bytes testdata/zoneinfo/America/Inuvik | Bin 0 -> 817 bytes testdata/zoneinfo/America/Iqaluit | Bin 0 -> 855 bytes testdata/zoneinfo/America/Jamaica | Bin 0 -> 339 bytes testdata/zoneinfo/America/Jujuy | Bin 0 -> 690 bytes testdata/zoneinfo/America/Juneau | Bin 0 -> 966 bytes testdata/zoneinfo/America/Kentucky/Louisville | Bin 0 -> 1242 bytes testdata/zoneinfo/America/Kentucky/Monticello | Bin 0 -> 972 bytes testdata/zoneinfo/America/Knox_IN | Bin 0 -> 1016 bytes testdata/zoneinfo/America/Kralendijk | Bin 0 -> 151 bytes testdata/zoneinfo/America/La_Paz | Bin 0 -> 170 bytes testdata/zoneinfo/America/Lima | Bin 0 -> 283 bytes testdata/zoneinfo/America/Los_Angeles | Bin 0 -> 1294 bytes testdata/zoneinfo/America/Louisville | Bin 0 -> 1242 bytes testdata/zoneinfo/America/Lower_Princes | Bin 0 -> 151 bytes testdata/zoneinfo/America/Maceio | Bin 0 -> 502 bytes testdata/zoneinfo/America/Managua | Bin 0 -> 295 bytes testdata/zoneinfo/America/Manaus | Bin 0 -> 412 bytes testdata/zoneinfo/America/Marigot | Bin 0 -> 130 bytes testdata/zoneinfo/America/Martinique | Bin 0 -> 178 bytes testdata/zoneinfo/America/Matamoros | Bin 0 -> 437 bytes testdata/zoneinfo/America/Mazatlan | Bin 0 -> 690 bytes testdata/zoneinfo/America/Mendoza | Bin 0 -> 708 bytes testdata/zoneinfo/America/Menominee | Bin 0 -> 917 bytes testdata/zoneinfo/America/Merida | Bin 0 -> 654 bytes testdata/zoneinfo/America/Metlakatla | Bin 0 -> 586 bytes testdata/zoneinfo/America/Mexico_City | Bin 0 -> 773 bytes testdata/zoneinfo/America/Miquelon | Bin 0 -> 550 bytes testdata/zoneinfo/America/Moncton | Bin 0 -> 1493 bytes testdata/zoneinfo/America/Monterrey | Bin 0 -> 709 bytes testdata/zoneinfo/America/Montevideo | Bin 0 -> 969 bytes testdata/zoneinfo/America/Montreal | Bin 0 -> 1717 bytes testdata/zoneinfo/America/Montserrat | Bin 0 -> 130 bytes testdata/zoneinfo/America/Nassau | Bin 0 -> 1006 bytes testdata/zoneinfo/America/New_York | Bin 0 -> 1744 bytes testdata/zoneinfo/America/Nipigon | Bin 0 -> 1717 bytes testdata/zoneinfo/America/Nome | Bin 0 -> 975 bytes testdata/zoneinfo/America/Noronha | Bin 0 -> 484 bytes testdata/zoneinfo/America/North_Dakota/Beulah | Bin 0 -> 1043 bytes testdata/zoneinfo/America/North_Dakota/Center | Bin 0 -> 990 bytes .../zoneinfo/America/North_Dakota/New_Salem | Bin 0 -> 990 bytes testdata/zoneinfo/America/Nuuk | Bin 0 -> 965 bytes testdata/zoneinfo/America/Ojinaga | Bin 0 -> 718 bytes testdata/zoneinfo/America/Panama | Bin 0 -> 149 bytes testdata/zoneinfo/America/Pangnirtung | Bin 0 -> 855 bytes testdata/zoneinfo/America/Paramaribo | Bin 0 -> 187 bytes testdata/zoneinfo/America/Phoenix | Bin 0 -> 240 bytes testdata/zoneinfo/America/Port-au-Prince | Bin 0 -> 565 bytes testdata/zoneinfo/America/Port_of_Spain | Bin 0 -> 130 bytes testdata/zoneinfo/America/Porto_Acre | Bin 0 -> 418 bytes testdata/zoneinfo/America/Porto_Velho | Bin 0 -> 394 bytes testdata/zoneinfo/America/Puerto_Rico | Bin 0 -> 177 bytes testdata/zoneinfo/America/Punta_Arenas | Bin 0 -> 1218 bytes testdata/zoneinfo/America/Rainy_River | Bin 0 -> 1294 bytes testdata/zoneinfo/America/Rankin_Inlet | Bin 0 -> 807 bytes testdata/zoneinfo/America/Recife | Bin 0 -> 484 bytes testdata/zoneinfo/America/Regina | Bin 0 -> 638 bytes testdata/zoneinfo/America/Resolute | Bin 0 -> 807 bytes testdata/zoneinfo/America/Rio_Branco | Bin 0 -> 418 bytes testdata/zoneinfo/America/Rosario | Bin 0 -> 708 bytes testdata/zoneinfo/America/Santa_Isabel | Bin 0 -> 1367 bytes testdata/zoneinfo/America/Santarem | Bin 0 -> 409 bytes testdata/zoneinfo/America/Santiago | Bin 0 -> 1354 bytes testdata/zoneinfo/America/Santo_Domingo | Bin 0 -> 317 bytes testdata/zoneinfo/America/Sao_Paulo | Bin 0 -> 952 bytes testdata/zoneinfo/America/Scoresbysund | Bin 0 -> 984 bytes testdata/zoneinfo/America/Shiprock | Bin 0 -> 1042 bytes testdata/zoneinfo/America/Sitka | Bin 0 -> 956 bytes testdata/zoneinfo/America/St_Barthelemy | Bin 0 -> 130 bytes testdata/zoneinfo/America/St_Johns | Bin 0 -> 1878 bytes testdata/zoneinfo/America/St_Kitts | Bin 0 -> 130 bytes testdata/zoneinfo/America/St_Lucia | Bin 0 -> 149 bytes testdata/zoneinfo/America/St_Thomas | Bin 0 -> 130 bytes testdata/zoneinfo/America/St_Vincent | Bin 0 -> 149 bytes testdata/zoneinfo/America/Swift_Current | Bin 0 -> 368 bytes testdata/zoneinfo/America/Tegucigalpa | Bin 0 -> 194 bytes testdata/zoneinfo/America/Thule | Bin 0 -> 455 bytes testdata/zoneinfo/America/Thunder_Bay | Bin 0 -> 1717 bytes testdata/zoneinfo/America/Tijuana | Bin 0 -> 1367 bytes testdata/zoneinfo/America/Toronto | Bin 0 -> 1717 bytes testdata/zoneinfo/America/Tortola | Bin 0 -> 130 bytes testdata/zoneinfo/America/Vancouver | Bin 0 -> 1330 bytes testdata/zoneinfo/America/Virgin | Bin 0 -> 130 bytes testdata/zoneinfo/America/Whitehorse | Bin 0 -> 1029 bytes testdata/zoneinfo/America/Winnipeg | Bin 0 -> 1294 bytes testdata/zoneinfo/America/Yakutat | Bin 0 -> 946 bytes testdata/zoneinfo/America/Yellowknife | Bin 0 -> 970 bytes testdata/zoneinfo/Antarctica/Casey | Bin 0 -> 287 bytes testdata/zoneinfo/Antarctica/Davis | Bin 0 -> 197 bytes testdata/zoneinfo/Antarctica/DumontDUrville | Bin 0 -> 152 bytes testdata/zoneinfo/Antarctica/Macquarie | Bin 0 -> 976 bytes testdata/zoneinfo/Antarctica/Mawson | Bin 0 -> 152 bytes testdata/zoneinfo/Antarctica/McMurdo | Bin 0 -> 768 bytes testdata/zoneinfo/Antarctica/Palmer | Bin 0 -> 887 bytes testdata/zoneinfo/Antarctica/Rothera | Bin 0 -> 132 bytes testdata/zoneinfo/Antarctica/South_Pole | Bin 0 -> 768 bytes testdata/zoneinfo/Antarctica/Syowa | Bin 0 -> 133 bytes testdata/zoneinfo/Antarctica/Troll | Bin 0 -> 158 bytes testdata/zoneinfo/Antarctica/Vostok | Bin 0 -> 170 bytes testdata/zoneinfo/Arctic/Longyearbyen | Bin 0 -> 676 bytes testdata/zoneinfo/Asia/Aden | Bin 0 -> 133 bytes testdata/zoneinfo/Asia/Almaty | Bin 0 -> 618 bytes testdata/zoneinfo/Asia/Amman | Bin 0 -> 928 bytes testdata/zoneinfo/Asia/Anadyr | Bin 0 -> 743 bytes testdata/zoneinfo/Asia/Aqtau | Bin 0 -> 606 bytes testdata/zoneinfo/Asia/Aqtobe | Bin 0 -> 615 bytes testdata/zoneinfo/Asia/Ashgabat | Bin 0 -> 375 bytes testdata/zoneinfo/Asia/Ashkhabad | Bin 0 -> 375 bytes testdata/zoneinfo/Asia/Atyrau | Bin 0 -> 616 bytes testdata/zoneinfo/Asia/Baghdad | Bin 0 -> 630 bytes testdata/zoneinfo/Asia/Bahrain | Bin 0 -> 173 bytes testdata/zoneinfo/Asia/Baku | Bin 0 -> 744 bytes testdata/zoneinfo/Asia/Bangkok | Bin 0 -> 152 bytes testdata/zoneinfo/Asia/Barnaul | Bin 0 -> 753 bytes testdata/zoneinfo/Asia/Beirut | Bin 0 -> 732 bytes testdata/zoneinfo/Asia/Bishkek | Bin 0 -> 618 bytes testdata/zoneinfo/Asia/Brunei | Bin 0 -> 154 bytes testdata/zoneinfo/Asia/Calcutta | Bin 0 -> 220 bytes testdata/zoneinfo/Asia/Chita | Bin 0 -> 750 bytes testdata/zoneinfo/Asia/Choibalsan | Bin 0 -> 594 bytes testdata/zoneinfo/Asia/Chongqing | Bin 0 -> 393 bytes testdata/zoneinfo/Asia/Chungking | Bin 0 -> 393 bytes testdata/zoneinfo/Asia/Colombo | Bin 0 -> 247 bytes testdata/zoneinfo/Asia/Dacca | Bin 0 -> 231 bytes testdata/zoneinfo/Asia/Damascus | Bin 0 -> 1234 bytes testdata/zoneinfo/Asia/Dhaka | Bin 0 -> 231 bytes testdata/zoneinfo/Asia/Dili | Bin 0 -> 170 bytes testdata/zoneinfo/Asia/Dubai | Bin 0 -> 133 bytes testdata/zoneinfo/Asia/Dushanbe | Bin 0 -> 366 bytes testdata/zoneinfo/Asia/Famagusta | Bin 0 -> 940 bytes testdata/zoneinfo/Asia/Gaza | Bin 0 -> 2950 bytes testdata/zoneinfo/Asia/Harbin | Bin 0 -> 393 bytes testdata/zoneinfo/Asia/Hebron | Bin 0 -> 2968 bytes testdata/zoneinfo/Asia/Ho_Chi_Minh | Bin 0 -> 236 bytes testdata/zoneinfo/Asia/Hong_Kong | Bin 0 -> 775 bytes testdata/zoneinfo/Asia/Hovd | Bin 0 -> 594 bytes testdata/zoneinfo/Asia/Irkutsk | Bin 0 -> 760 bytes testdata/zoneinfo/Asia/Istanbul | Bin 0 -> 1200 bytes testdata/zoneinfo/Asia/Jakarta | Bin 0 -> 248 bytes testdata/zoneinfo/Asia/Jayapura | Bin 0 -> 171 bytes testdata/zoneinfo/Asia/Jerusalem | Bin 0 -> 1074 bytes testdata/zoneinfo/Asia/Kabul | Bin 0 -> 159 bytes testdata/zoneinfo/Asia/Kamchatka | Bin 0 -> 727 bytes testdata/zoneinfo/Asia/Karachi | Bin 0 -> 266 bytes testdata/zoneinfo/Asia/Kashgar | Bin 0 -> 133 bytes testdata/zoneinfo/Asia/Kathmandu | Bin 0 -> 161 bytes testdata/zoneinfo/Asia/Katmandu | Bin 0 -> 161 bytes testdata/zoneinfo/Asia/Khandyga | Bin 0 -> 775 bytes testdata/zoneinfo/Asia/Kolkata | Bin 0 -> 220 bytes testdata/zoneinfo/Asia/Krasnoyarsk | Bin 0 -> 741 bytes testdata/zoneinfo/Asia/Kuala_Lumpur | Bin 0 -> 256 bytes testdata/zoneinfo/Asia/Kuching | Bin 0 -> 320 bytes testdata/zoneinfo/Asia/Kuwait | Bin 0 -> 133 bytes testdata/zoneinfo/Asia/Macao | Bin 0 -> 791 bytes testdata/zoneinfo/Asia/Macau | Bin 0 -> 791 bytes testdata/zoneinfo/Asia/Magadan | Bin 0 -> 751 bytes testdata/zoneinfo/Asia/Makassar | Bin 0 -> 190 bytes testdata/zoneinfo/Asia/Manila | Bin 0 -> 274 bytes testdata/zoneinfo/Asia/Muscat | Bin 0 -> 133 bytes testdata/zoneinfo/Asia/Nicosia | Bin 0 -> 597 bytes testdata/zoneinfo/Asia/Novokuznetsk | Bin 0 -> 726 bytes testdata/zoneinfo/Asia/Novosibirsk | Bin 0 -> 753 bytes testdata/zoneinfo/Asia/Omsk | Bin 0 -> 741 bytes testdata/zoneinfo/Asia/Oral | Bin 0 -> 625 bytes testdata/zoneinfo/Asia/Phnom_Penh | Bin 0 -> 200 bytes testdata/zoneinfo/Asia/Pontianak | Bin 0 -> 247 bytes testdata/zoneinfo/Asia/Pyongyang | Bin 0 -> 183 bytes testdata/zoneinfo/Asia/Qatar | Bin 0 -> 152 bytes testdata/zoneinfo/Asia/Qostanay | Bin 0 -> 624 bytes testdata/zoneinfo/Asia/Qyzylorda | Bin 0 -> 624 bytes testdata/zoneinfo/Asia/Rangoon | Bin 0 -> 187 bytes testdata/zoneinfo/Asia/Riyadh | Bin 0 -> 133 bytes testdata/zoneinfo/Asia/Saigon | Bin 0 -> 236 bytes testdata/zoneinfo/Asia/Sakhalin | Bin 0 -> 755 bytes testdata/zoneinfo/Asia/Samarkand | Bin 0 -> 366 bytes testdata/zoneinfo/Asia/Seoul | Bin 0 -> 415 bytes testdata/zoneinfo/Asia/Shanghai | Bin 0 -> 393 bytes testdata/zoneinfo/Asia/Singapore | Bin 0 -> 256 bytes testdata/zoneinfo/Asia/Srednekolymsk | Bin 0 -> 742 bytes testdata/zoneinfo/Asia/Taipei | Bin 0 -> 511 bytes testdata/zoneinfo/Asia/Tashkent | Bin 0 -> 366 bytes testdata/zoneinfo/Asia/Tbilisi | Bin 0 -> 620 bytes testdata/zoneinfo/Asia/Tehran | Bin 0 -> 812 bytes testdata/zoneinfo/Asia/Tel_Aviv | Bin 0 -> 1074 bytes testdata/zoneinfo/Asia/Thimbu | Bin 0 -> 154 bytes testdata/zoneinfo/Asia/Thimphu | Bin 0 -> 154 bytes testdata/zoneinfo/Asia/Tokyo | Bin 0 -> 213 bytes testdata/zoneinfo/Asia/Tomsk | Bin 0 -> 753 bytes testdata/zoneinfo/Asia/Ujung_Pandang | Bin 0 -> 190 bytes testdata/zoneinfo/Asia/Ulaanbaatar | Bin 0 -> 594 bytes testdata/zoneinfo/Asia/Ulan_Bator | Bin 0 -> 594 bytes testdata/zoneinfo/Asia/Urumqi | Bin 0 -> 133 bytes testdata/zoneinfo/Asia/Ust-Nera | Bin 0 -> 771 bytes testdata/zoneinfo/Asia/Vientiane | Bin 0 -> 218 bytes testdata/zoneinfo/Asia/Vladivostok | Bin 0 -> 742 bytes testdata/zoneinfo/Asia/Yakutsk | Bin 0 -> 741 bytes testdata/zoneinfo/Asia/Yangon | Bin 0 -> 187 bytes testdata/zoneinfo/Asia/Yekaterinburg | Bin 0 -> 760 bytes testdata/zoneinfo/Asia/Yerevan | Bin 0 -> 708 bytes testdata/zoneinfo/Atlantic/Azores | Bin 0 -> 1401 bytes testdata/zoneinfo/Atlantic/Bermuda | Bin 0 -> 1024 bytes testdata/zoneinfo/Atlantic/Canary | Bin 0 -> 478 bytes testdata/zoneinfo/Atlantic/Cape_Verde | Bin 0 -> 175 bytes testdata/zoneinfo/Atlantic/Faeroe | Bin 0 -> 441 bytes testdata/zoneinfo/Atlantic/Faroe | Bin 0 -> 441 bytes testdata/zoneinfo/Atlantic/Jan_Mayen | Bin 0 -> 676 bytes testdata/zoneinfo/Atlantic/Madeira | Bin 0 -> 1372 bytes testdata/zoneinfo/Atlantic/Reykjavik | Bin 0 -> 753 bytes testdata/zoneinfo/Atlantic/South_Georgia | Bin 0 -> 132 bytes testdata/zoneinfo/Atlantic/St_Helena | Bin 0 -> 149 bytes testdata/zoneinfo/Atlantic/Stanley | Bin 0 -> 789 bytes testdata/zoneinfo/Australia/ACT | Bin 0 -> 904 bytes testdata/zoneinfo/Australia/Adelaide | Bin 0 -> 921 bytes testdata/zoneinfo/Australia/Brisbane | Bin 0 -> 289 bytes testdata/zoneinfo/Australia/Broken_Hill | Bin 0 -> 941 bytes testdata/zoneinfo/Australia/Canberra | Bin 0 -> 904 bytes testdata/zoneinfo/Australia/Currie | Bin 0 -> 1003 bytes testdata/zoneinfo/Australia/Darwin | Bin 0 -> 234 bytes testdata/zoneinfo/Australia/Eucla | Bin 0 -> 314 bytes testdata/zoneinfo/Australia/Hobart | Bin 0 -> 1003 bytes testdata/zoneinfo/Australia/LHI | Bin 0 -> 692 bytes testdata/zoneinfo/Australia/Lindeman | Bin 0 -> 325 bytes testdata/zoneinfo/Australia/Lord_Howe | Bin 0 -> 692 bytes testdata/zoneinfo/Australia/Melbourne | Bin 0 -> 904 bytes testdata/zoneinfo/Australia/NSW | Bin 0 -> 904 bytes testdata/zoneinfo/Australia/North | Bin 0 -> 234 bytes testdata/zoneinfo/Australia/Perth | Bin 0 -> 306 bytes testdata/zoneinfo/Australia/Queensland | Bin 0 -> 289 bytes testdata/zoneinfo/Australia/South | Bin 0 -> 921 bytes testdata/zoneinfo/Australia/Sydney | Bin 0 -> 904 bytes testdata/zoneinfo/Australia/Tasmania | Bin 0 -> 1003 bytes testdata/zoneinfo/Australia/Victoria | Bin 0 -> 904 bytes testdata/zoneinfo/Australia/West | Bin 0 -> 306 bytes testdata/zoneinfo/Australia/Yancowinna | Bin 0 -> 941 bytes testdata/zoneinfo/Brazil/Acre | Bin 0 -> 418 bytes testdata/zoneinfo/Brazil/DeNoronha | Bin 0 -> 484 bytes testdata/zoneinfo/Brazil/East | Bin 0 -> 952 bytes testdata/zoneinfo/Brazil/West | Bin 0 -> 412 bytes testdata/zoneinfo/CET | Bin 0 -> 1103 bytes testdata/zoneinfo/CST6CDT | Bin 0 -> 1754 bytes testdata/zoneinfo/Canada/Atlantic | Bin 0 -> 1672 bytes testdata/zoneinfo/Canada/Central | Bin 0 -> 1294 bytes testdata/zoneinfo/Canada/Eastern | Bin 0 -> 1717 bytes testdata/zoneinfo/Canada/Mountain | Bin 0 -> 970 bytes testdata/zoneinfo/Canada/Newfoundland | Bin 0 -> 1878 bytes testdata/zoneinfo/Canada/Pacific | Bin 0 -> 1330 bytes testdata/zoneinfo/Canada/Saskatchewan | Bin 0 -> 638 bytes testdata/zoneinfo/Canada/Yukon | Bin 0 -> 1029 bytes testdata/zoneinfo/Chile/Continental | Bin 0 -> 1354 bytes testdata/zoneinfo/Chile/EasterIsland | Bin 0 -> 1174 bytes testdata/zoneinfo/Cuba | Bin 0 -> 1117 bytes testdata/zoneinfo/EET | Bin 0 -> 682 bytes testdata/zoneinfo/EST | Bin 0 -> 149 bytes testdata/zoneinfo/EST5EDT | Bin 0 -> 1744 bytes testdata/zoneinfo/Egypt | Bin 0 -> 1309 bytes testdata/zoneinfo/Eire | Bin 0 -> 1496 bytes testdata/zoneinfo/Etc/GMT | Bin 0 -> 111 bytes testdata/zoneinfo/Etc/GMT+0 | Bin 0 -> 111 bytes testdata/zoneinfo/Etc/GMT+1 | Bin 0 -> 113 bytes testdata/zoneinfo/Etc/GMT+10 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT+11 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT+12 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT+2 | Bin 0 -> 113 bytes testdata/zoneinfo/Etc/GMT+3 | Bin 0 -> 113 bytes testdata/zoneinfo/Etc/GMT+4 | Bin 0 -> 113 bytes testdata/zoneinfo/Etc/GMT+5 | Bin 0 -> 113 bytes testdata/zoneinfo/Etc/GMT+6 | Bin 0 -> 113 bytes testdata/zoneinfo/Etc/GMT+7 | Bin 0 -> 113 bytes testdata/zoneinfo/Etc/GMT+8 | Bin 0 -> 113 bytes testdata/zoneinfo/Etc/GMT+9 | Bin 0 -> 113 bytes testdata/zoneinfo/Etc/GMT-0 | Bin 0 -> 111 bytes testdata/zoneinfo/Etc/GMT-1 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT-10 | Bin 0 -> 115 bytes testdata/zoneinfo/Etc/GMT-11 | Bin 0 -> 115 bytes testdata/zoneinfo/Etc/GMT-12 | Bin 0 -> 115 bytes testdata/zoneinfo/Etc/GMT-13 | Bin 0 -> 115 bytes testdata/zoneinfo/Etc/GMT-14 | Bin 0 -> 115 bytes testdata/zoneinfo/Etc/GMT-2 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT-3 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT-4 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT-5 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT-6 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT-7 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT-8 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT-9 | Bin 0 -> 114 bytes testdata/zoneinfo/Etc/GMT0 | Bin 0 -> 111 bytes testdata/zoneinfo/Etc/Greenwich | Bin 0 -> 111 bytes testdata/zoneinfo/Etc/UCT | Bin 0 -> 111 bytes testdata/zoneinfo/Etc/UTC | Bin 0 -> 111 bytes testdata/zoneinfo/Etc/Universal | Bin 0 -> 111 bytes testdata/zoneinfo/Etc/Zulu | Bin 0 -> 111 bytes testdata/zoneinfo/Europe/Amsterdam | Bin 0 -> 1071 bytes testdata/zoneinfo/Europe/Andorra | Bin 0 -> 389 bytes testdata/zoneinfo/Europe/Astrakhan | Bin 0 -> 726 bytes testdata/zoneinfo/Europe/Athens | Bin 0 -> 682 bytes testdata/zoneinfo/Europe/Belfast | Bin 0 -> 1599 bytes testdata/zoneinfo/Europe/Belgrade | Bin 0 -> 478 bytes testdata/zoneinfo/Europe/Berlin | Bin 0 -> 705 bytes testdata/zoneinfo/Europe/Bratislava | Bin 0 -> 723 bytes testdata/zoneinfo/Europe/Brussels | Bin 0 -> 1103 bytes testdata/zoneinfo/Europe/Bucharest | Bin 0 -> 661 bytes testdata/zoneinfo/Europe/Budapest | Bin 0 -> 766 bytes testdata/zoneinfo/Europe/Busingen | Bin 0 -> 497 bytes testdata/zoneinfo/Europe/Chisinau | Bin 0 -> 1207 bytes testdata/zoneinfo/Europe/Copenhagen | Bin 0 -> 623 bytes testdata/zoneinfo/Europe/Dublin | Bin 0 -> 1496 bytes testdata/zoneinfo/Europe/Gibraltar | Bin 0 -> 1220 bytes testdata/zoneinfo/Europe/Guernsey | Bin 0 -> 1611 bytes testdata/zoneinfo/Europe/Helsinki | Bin 0 -> 481 bytes testdata/zoneinfo/Europe/Isle_of_Man | Bin 0 -> 1599 bytes testdata/zoneinfo/Europe/Istanbul | Bin 0 -> 1200 bytes testdata/zoneinfo/Europe/Jersey | Bin 0 -> 1611 bytes testdata/zoneinfo/Europe/Kaliningrad | Bin 0 -> 904 bytes testdata/zoneinfo/Europe/Kiev | Bin 0 -> 558 bytes testdata/zoneinfo/Europe/Kirov | Bin 0 -> 735 bytes testdata/zoneinfo/Europe/Kyiv | Bin 0 -> 558 bytes testdata/zoneinfo/Europe/Lisbon | Bin 0 -> 1463 bytes testdata/zoneinfo/Europe/Ljubljana | Bin 0 -> 478 bytes testdata/zoneinfo/Europe/London | Bin 0 -> 1599 bytes testdata/zoneinfo/Europe/Luxembourg | Bin 0 -> 1087 bytes testdata/zoneinfo/Europe/Madrid | Bin 0 -> 897 bytes testdata/zoneinfo/Europe/Malta | Bin 0 -> 928 bytes testdata/zoneinfo/Europe/Mariehamn | Bin 0 -> 481 bytes testdata/zoneinfo/Europe/Minsk | Bin 0 -> 808 bytes testdata/zoneinfo/Europe/Monaco | Bin 0 -> 1114 bytes testdata/zoneinfo/Europe/Moscow | Bin 0 -> 908 bytes testdata/zoneinfo/Europe/Nicosia | Bin 0 -> 597 bytes testdata/zoneinfo/Europe/Oslo | Bin 0 -> 676 bytes testdata/zoneinfo/Europe/Paris | Bin 0 -> 1105 bytes testdata/zoneinfo/Europe/Podgorica | Bin 0 -> 478 bytes testdata/zoneinfo/Europe/Prague | Bin 0 -> 723 bytes testdata/zoneinfo/Europe/Riga | Bin 0 -> 694 bytes testdata/zoneinfo/Europe/Rome | Bin 0 -> 947 bytes testdata/zoneinfo/Europe/Samara | Bin 0 -> 732 bytes testdata/zoneinfo/Europe/San_Marino | Bin 0 -> 947 bytes testdata/zoneinfo/Europe/Sarajevo | Bin 0 -> 478 bytes testdata/zoneinfo/Europe/Saratov | Bin 0 -> 726 bytes testdata/zoneinfo/Europe/Simferopol | Bin 0 -> 865 bytes testdata/zoneinfo/Europe/Skopje | Bin 0 -> 478 bytes testdata/zoneinfo/Europe/Sofia | Bin 0 -> 592 bytes testdata/zoneinfo/Europe/Stockholm | Bin 0 -> 497 bytes testdata/zoneinfo/Europe/Tallinn | Bin 0 -> 675 bytes testdata/zoneinfo/Europe/Tirane | Bin 0 -> 604 bytes testdata/zoneinfo/Europe/Tiraspol | Bin 0 -> 1207 bytes testdata/zoneinfo/Europe/Ulyanovsk | Bin 0 -> 760 bytes testdata/zoneinfo/Europe/Uzhgorod | Bin 0 -> 558 bytes testdata/zoneinfo/Europe/Vaduz | Bin 0 -> 478 bytes testdata/zoneinfo/Europe/Vatican | Bin 0 -> 947 bytes testdata/zoneinfo/Europe/Vienna | Bin 0 -> 658 bytes testdata/zoneinfo/Europe/Vilnius | Bin 0 -> 676 bytes testdata/zoneinfo/Europe/Volgograd | Bin 0 -> 753 bytes testdata/zoneinfo/Europe/Warsaw | Bin 0 -> 923 bytes testdata/zoneinfo/Europe/Zagreb | Bin 0 -> 478 bytes testdata/zoneinfo/Europe/Zaporozhye | Bin 0 -> 558 bytes testdata/zoneinfo/Europe/Zurich | Bin 0 -> 497 bytes testdata/zoneinfo/Factory | Bin 0 -> 113 bytes testdata/zoneinfo/GB | Bin 0 -> 1599 bytes testdata/zoneinfo/GB-Eire | Bin 0 -> 1599 bytes testdata/zoneinfo/GMT | Bin 0 -> 111 bytes testdata/zoneinfo/GMT+0 | Bin 0 -> 111 bytes testdata/zoneinfo/GMT-0 | Bin 0 -> 111 bytes testdata/zoneinfo/GMT0 | Bin 0 -> 111 bytes testdata/zoneinfo/Greenwich | Bin 0 -> 111 bytes testdata/zoneinfo/HST | Bin 0 -> 221 bytes testdata/zoneinfo/Hongkong | Bin 0 -> 775 bytes testdata/zoneinfo/Iceland | Bin 0 -> 753 bytes testdata/zoneinfo/Indian/Antananarivo | Bin 0 -> 160 bytes testdata/zoneinfo/Indian/Chagos | Bin 0 -> 152 bytes testdata/zoneinfo/Indian/Christmas | Bin 0 -> 133 bytes testdata/zoneinfo/Indian/Cocos | Bin 0 -> 140 bytes testdata/zoneinfo/Indian/Comoro | Bin 0 -> 131 bytes testdata/zoneinfo/Indian/Kerguelen | Bin 0 -> 133 bytes testdata/zoneinfo/Indian/Mahe | Bin 0 -> 133 bytes testdata/zoneinfo/Indian/Maldives | Bin 0 -> 152 bytes testdata/zoneinfo/Indian/Mauritius | Bin 0 -> 179 bytes testdata/zoneinfo/Indian/Mayotte | Bin 0 -> 131 bytes testdata/zoneinfo/Indian/Reunion | Bin 0 -> 133 bytes testdata/zoneinfo/Iran | Bin 0 -> 812 bytes testdata/zoneinfo/Israel | Bin 0 -> 1074 bytes testdata/zoneinfo/Jamaica | Bin 0 -> 339 bytes testdata/zoneinfo/Japan | Bin 0 -> 213 bytes testdata/zoneinfo/Kwajalein | Bin 0 -> 219 bytes testdata/zoneinfo/Libya | Bin 0 -> 431 bytes testdata/zoneinfo/MET | Bin 0 -> 1103 bytes testdata/zoneinfo/MST | Bin 0 -> 240 bytes testdata/zoneinfo/MST7MDT | Bin 0 -> 1042 bytes testdata/zoneinfo/Mexico/BajaNorte | Bin 0 -> 1367 bytes testdata/zoneinfo/Mexico/BajaSur | Bin 0 -> 690 bytes testdata/zoneinfo/Mexico/General | Bin 0 -> 773 bytes testdata/zoneinfo/NZ | Bin 0 -> 1043 bytes testdata/zoneinfo/NZ-CHAT | Bin 0 -> 808 bytes testdata/zoneinfo/Navajo | Bin 0 -> 1042 bytes testdata/zoneinfo/PRC | Bin 0 -> 393 bytes testdata/zoneinfo/PST8PDT | Bin 0 -> 1294 bytes testdata/zoneinfo/Pacific/Apia | Bin 0 -> 407 bytes testdata/zoneinfo/Pacific/Auckland | Bin 0 -> 1043 bytes testdata/zoneinfo/Pacific/Bougainville | Bin 0 -> 201 bytes testdata/zoneinfo/Pacific/Chatham | Bin 0 -> 808 bytes testdata/zoneinfo/Pacific/Chuuk | Bin 0 -> 195 bytes testdata/zoneinfo/Pacific/Easter | Bin 0 -> 1174 bytes testdata/zoneinfo/Pacific/Efate | Bin 0 -> 342 bytes testdata/zoneinfo/Pacific/Enderbury | Bin 0 -> 172 bytes testdata/zoneinfo/Pacific/Fakaofo | Bin 0 -> 153 bytes testdata/zoneinfo/Pacific/Fiji | Bin 0 -> 396 bytes testdata/zoneinfo/Pacific/Funafuti | Bin 0 -> 134 bytes testdata/zoneinfo/Pacific/Galapagos | Bin 0 -> 175 bytes testdata/zoneinfo/Pacific/Gambier | Bin 0 -> 132 bytes testdata/zoneinfo/Pacific/Guadalcanal | Bin 0 -> 134 bytes testdata/zoneinfo/Pacific/Guam | Bin 0 -> 350 bytes testdata/zoneinfo/Pacific/Honolulu | Bin 0 -> 221 bytes testdata/zoneinfo/Pacific/Johnston | Bin 0 -> 221 bytes testdata/zoneinfo/Pacific/Kanton | Bin 0 -> 172 bytes testdata/zoneinfo/Pacific/Kiritimati | Bin 0 -> 174 bytes testdata/zoneinfo/Pacific/Kosrae | Bin 0 -> 242 bytes testdata/zoneinfo/Pacific/Kwajalein | Bin 0 -> 219 bytes testdata/zoneinfo/Pacific/Majuro | Bin 0 -> 218 bytes testdata/zoneinfo/Pacific/Marquesas | Bin 0 -> 139 bytes testdata/zoneinfo/Pacific/Midway | Bin 0 -> 169 bytes testdata/zoneinfo/Pacific/Nauru | Bin 0 -> 183 bytes testdata/zoneinfo/Pacific/Niue | Bin 0 -> 154 bytes testdata/zoneinfo/Pacific/Norfolk | Bin 0 -> 237 bytes testdata/zoneinfo/Pacific/Noumea | Bin 0 -> 198 bytes testdata/zoneinfo/Pacific/Pago_Pago | Bin 0 -> 146 bytes testdata/zoneinfo/Pacific/Palau | Bin 0 -> 148 bytes testdata/zoneinfo/Pacific/Pitcairn | Bin 0 -> 153 bytes testdata/zoneinfo/Pacific/Pohnpei | Bin 0 -> 214 bytes testdata/zoneinfo/Pacific/Ponape | Bin 0 -> 214 bytes testdata/zoneinfo/Pacific/Port_Moresby | Bin 0 -> 154 bytes testdata/zoneinfo/Pacific/Rarotonga | Bin 0 -> 406 bytes testdata/zoneinfo/Pacific/Saipan | Bin 0 -> 341 bytes testdata/zoneinfo/Pacific/Samoa | Bin 0 -> 146 bytes testdata/zoneinfo/Pacific/Tahiti | Bin 0 -> 133 bytes testdata/zoneinfo/Pacific/Tarawa | Bin 0 -> 134 bytes testdata/zoneinfo/Pacific/Tongatapu | Bin 0 -> 237 bytes testdata/zoneinfo/Pacific/Truk | Bin 0 -> 195 bytes testdata/zoneinfo/Pacific/Wake | Bin 0 -> 134 bytes testdata/zoneinfo/Pacific/Wallis | Bin 0 -> 134 bytes testdata/zoneinfo/Pacific/Yap | Bin 0 -> 195 bytes testdata/zoneinfo/Poland | Bin 0 -> 923 bytes testdata/zoneinfo/Portugal | Bin 0 -> 1463 bytes testdata/zoneinfo/ROC | Bin 0 -> 511 bytes testdata/zoneinfo/ROK | Bin 0 -> 415 bytes testdata/zoneinfo/Singapore | Bin 0 -> 256 bytes testdata/zoneinfo/Turkey | Bin 0 -> 1200 bytes testdata/zoneinfo/UCT | Bin 0 -> 111 bytes testdata/zoneinfo/US/Alaska | Bin 0 -> 977 bytes testdata/zoneinfo/US/Aleutian | Bin 0 -> 969 bytes testdata/zoneinfo/US/Arizona | Bin 0 -> 240 bytes testdata/zoneinfo/US/Central | Bin 0 -> 1754 bytes testdata/zoneinfo/US/East-Indiana | Bin 0 -> 531 bytes testdata/zoneinfo/US/Eastern | Bin 0 -> 1744 bytes testdata/zoneinfo/US/Hawaii | Bin 0 -> 221 bytes testdata/zoneinfo/US/Indiana-Starke | Bin 0 -> 1016 bytes testdata/zoneinfo/US/Michigan | Bin 0 -> 899 bytes testdata/zoneinfo/US/Mountain | Bin 0 -> 1042 bytes testdata/zoneinfo/US/Pacific | Bin 0 -> 1294 bytes testdata/zoneinfo/US/Samoa | Bin 0 -> 146 bytes testdata/zoneinfo/UTC | Bin 0 -> 111 bytes testdata/zoneinfo/Universal | Bin 0 -> 111 bytes testdata/zoneinfo/W-SU | Bin 0 -> 908 bytes testdata/zoneinfo/WET | Bin 0 -> 1463 bytes testdata/zoneinfo/Zulu | Bin 0 -> 111 bytes testdata/zoneinfo/iso3166.tab | 279 ++++ testdata/zoneinfo/zone1970.tab | 375 +++++ testdata/zoneinfo/zonenow.tab | 293 ++++ 659 files changed, 8706 insertions(+), 4850 deletions(-) create mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/cifuzz.yml create mode 100644 CMakeLists.txt create mode 100644 MODULE.bazel delete mode 100644 WORKSPACE create mode 100644 cmake/cctz-config.cmake create mode 100644 cmake/modules/FindGMock.cmake create mode 100644 examples/CMakeLists.txt rename include/{ => cctz}/civil_time.h (97%) create mode 100644 include/cctz/civil_time_detail.h create mode 100644 include/cctz/time_zone.h create mode 100644 include/cctz/zone_info_source.h delete mode 100644 include/civil_time_detail.h delete mode 100644 include/time_zone.h delete mode 100644 src/cctz.h create mode 100644 src/cctz_benchmark.cc delete mode 100644 src/cctz_v1_test.cc create mode 100644 src/civil_time_detail.cc create mode 100644 src/test_time_zone_names.cc create mode 100644 src/test_time_zone_names.h create mode 100644 src/time_zone_fixed.cc create mode 100644 src/time_zone_fixed.h create mode 100644 src/time_zone_fuzz_test.cc create mode 100644 src/time_zone_name_win.cc create mode 100644 src/time_zone_name_win.h create mode 100644 src/zone_info_source.cc create mode 100644 testdata/README.zoneinfo create mode 100644 testdata/version create mode 100644 testdata/zoneinfo/Africa/Abidjan create mode 100644 testdata/zoneinfo/Africa/Accra create mode 100644 testdata/zoneinfo/Africa/Addis_Ababa create mode 100644 testdata/zoneinfo/Africa/Algiers create mode 100644 testdata/zoneinfo/Africa/Asmara create mode 100644 testdata/zoneinfo/Africa/Asmera create mode 100644 testdata/zoneinfo/Africa/Bamako create mode 100644 testdata/zoneinfo/Africa/Bangui create mode 100644 testdata/zoneinfo/Africa/Banjul create mode 100644 testdata/zoneinfo/Africa/Bissau create mode 100644 testdata/zoneinfo/Africa/Blantyre create mode 100644 testdata/zoneinfo/Africa/Brazzaville create mode 100644 testdata/zoneinfo/Africa/Bujumbura create mode 100644 testdata/zoneinfo/Africa/Cairo create mode 100644 testdata/zoneinfo/Africa/Casablanca create mode 100644 testdata/zoneinfo/Africa/Ceuta create mode 100644 testdata/zoneinfo/Africa/Conakry create mode 100644 testdata/zoneinfo/Africa/Dakar create mode 100644 testdata/zoneinfo/Africa/Dar_es_Salaam create mode 100644 testdata/zoneinfo/Africa/Djibouti create mode 100644 testdata/zoneinfo/Africa/Douala create mode 100644 testdata/zoneinfo/Africa/El_Aaiun create mode 100644 testdata/zoneinfo/Africa/Freetown create mode 100644 testdata/zoneinfo/Africa/Gaborone create mode 100644 testdata/zoneinfo/Africa/Harare create mode 100644 testdata/zoneinfo/Africa/Johannesburg create mode 100644 testdata/zoneinfo/Africa/Juba create mode 100644 testdata/zoneinfo/Africa/Kampala create mode 100644 testdata/zoneinfo/Africa/Khartoum create mode 100644 testdata/zoneinfo/Africa/Kigali create mode 100644 testdata/zoneinfo/Africa/Kinshasa create mode 100644 testdata/zoneinfo/Africa/Lagos create mode 100644 testdata/zoneinfo/Africa/Libreville create mode 100644 testdata/zoneinfo/Africa/Lome create mode 100644 testdata/zoneinfo/Africa/Luanda create mode 100644 testdata/zoneinfo/Africa/Lubumbashi create mode 100644 testdata/zoneinfo/Africa/Lusaka create mode 100644 testdata/zoneinfo/Africa/Malabo create mode 100644 testdata/zoneinfo/Africa/Maputo create mode 100644 testdata/zoneinfo/Africa/Maseru create mode 100644 testdata/zoneinfo/Africa/Mbabane create mode 100644 testdata/zoneinfo/Africa/Mogadishu create mode 100644 testdata/zoneinfo/Africa/Monrovia create mode 100644 testdata/zoneinfo/Africa/Nairobi create mode 100644 testdata/zoneinfo/Africa/Ndjamena create mode 100644 testdata/zoneinfo/Africa/Niamey create mode 100644 testdata/zoneinfo/Africa/Nouakchott create mode 100644 testdata/zoneinfo/Africa/Ouagadougou create mode 100644 testdata/zoneinfo/Africa/Porto-Novo create mode 100644 testdata/zoneinfo/Africa/Sao_Tome create mode 100644 testdata/zoneinfo/Africa/Timbuktu create mode 100644 testdata/zoneinfo/Africa/Tripoli create mode 100644 testdata/zoneinfo/Africa/Tunis create mode 100644 testdata/zoneinfo/Africa/Windhoek create mode 100644 testdata/zoneinfo/America/Adak create mode 100644 testdata/zoneinfo/America/Anchorage create mode 100644 testdata/zoneinfo/America/Anguilla create mode 100644 testdata/zoneinfo/America/Antigua create mode 100644 testdata/zoneinfo/America/Araguaina create mode 100644 testdata/zoneinfo/America/Argentina/Buenos_Aires create mode 100644 testdata/zoneinfo/America/Argentina/Catamarca create mode 100644 testdata/zoneinfo/America/Argentina/ComodRivadavia create mode 100644 testdata/zoneinfo/America/Argentina/Cordoba create mode 100644 testdata/zoneinfo/America/Argentina/Jujuy create mode 100644 testdata/zoneinfo/America/Argentina/La_Rioja create mode 100644 testdata/zoneinfo/America/Argentina/Mendoza create mode 100644 testdata/zoneinfo/America/Argentina/Rio_Gallegos create mode 100644 testdata/zoneinfo/America/Argentina/Salta create mode 100644 testdata/zoneinfo/America/Argentina/San_Juan create mode 100644 testdata/zoneinfo/America/Argentina/San_Luis create mode 100644 testdata/zoneinfo/America/Argentina/Tucuman create mode 100644 testdata/zoneinfo/America/Argentina/Ushuaia create mode 100644 testdata/zoneinfo/America/Aruba create mode 100644 testdata/zoneinfo/America/Asuncion create mode 100644 testdata/zoneinfo/America/Atikokan create mode 100644 testdata/zoneinfo/America/Atka create mode 100644 testdata/zoneinfo/America/Bahia create mode 100644 testdata/zoneinfo/America/Bahia_Banderas create mode 100644 testdata/zoneinfo/America/Barbados create mode 100644 testdata/zoneinfo/America/Belem create mode 100644 testdata/zoneinfo/America/Belize create mode 100644 testdata/zoneinfo/America/Blanc-Sablon create mode 100644 testdata/zoneinfo/America/Boa_Vista create mode 100644 testdata/zoneinfo/America/Bogota create mode 100644 testdata/zoneinfo/America/Boise create mode 100644 testdata/zoneinfo/America/Buenos_Aires create mode 100644 testdata/zoneinfo/America/Cambridge_Bay create mode 100644 testdata/zoneinfo/America/Campo_Grande create mode 100644 testdata/zoneinfo/America/Cancun create mode 100644 testdata/zoneinfo/America/Caracas create mode 100644 testdata/zoneinfo/America/Catamarca create mode 100644 testdata/zoneinfo/America/Cayenne create mode 100644 testdata/zoneinfo/America/Cayman create mode 100644 testdata/zoneinfo/America/Chicago create mode 100644 testdata/zoneinfo/America/Chihuahua create mode 100644 testdata/zoneinfo/America/Ciudad_Juarez create mode 100644 testdata/zoneinfo/America/Coral_Harbour create mode 100644 testdata/zoneinfo/America/Cordoba create mode 100644 testdata/zoneinfo/America/Costa_Rica create mode 100644 testdata/zoneinfo/America/Coyhaique create mode 100644 testdata/zoneinfo/America/Creston create mode 100644 testdata/zoneinfo/America/Cuiaba create mode 100644 testdata/zoneinfo/America/Curacao create mode 100644 testdata/zoneinfo/America/Danmarkshavn create mode 100644 testdata/zoneinfo/America/Dawson create mode 100644 testdata/zoneinfo/America/Dawson_Creek create mode 100644 testdata/zoneinfo/America/Denver create mode 100644 testdata/zoneinfo/America/Detroit create mode 100644 testdata/zoneinfo/America/Dominica create mode 100644 testdata/zoneinfo/America/Edmonton create mode 100644 testdata/zoneinfo/America/Eirunepe create mode 100644 testdata/zoneinfo/America/El_Salvador create mode 100644 testdata/zoneinfo/America/Ensenada create mode 100644 testdata/zoneinfo/America/Fort_Nelson create mode 100644 testdata/zoneinfo/America/Fort_Wayne create mode 100644 testdata/zoneinfo/America/Fortaleza create mode 100644 testdata/zoneinfo/America/Glace_Bay create mode 100644 testdata/zoneinfo/America/Godthab create mode 100644 testdata/zoneinfo/America/Goose_Bay create mode 100644 testdata/zoneinfo/America/Grand_Turk create mode 100644 testdata/zoneinfo/America/Grenada create mode 100644 testdata/zoneinfo/America/Guadeloupe create mode 100644 testdata/zoneinfo/America/Guatemala create mode 100644 testdata/zoneinfo/America/Guayaquil create mode 100644 testdata/zoneinfo/America/Guyana create mode 100644 testdata/zoneinfo/America/Halifax create mode 100644 testdata/zoneinfo/America/Havana create mode 100644 testdata/zoneinfo/America/Hermosillo create mode 100644 testdata/zoneinfo/America/Indiana/Indianapolis create mode 100644 testdata/zoneinfo/America/Indiana/Knox create mode 100644 testdata/zoneinfo/America/Indiana/Marengo create mode 100644 testdata/zoneinfo/America/Indiana/Petersburg create mode 100644 testdata/zoneinfo/America/Indiana/Tell_City create mode 100644 testdata/zoneinfo/America/Indiana/Vevay create mode 100644 testdata/zoneinfo/America/Indiana/Vincennes create mode 100644 testdata/zoneinfo/America/Indiana/Winamac create mode 100644 testdata/zoneinfo/America/Indianapolis create mode 100644 testdata/zoneinfo/America/Inuvik create mode 100644 testdata/zoneinfo/America/Iqaluit create mode 100644 testdata/zoneinfo/America/Jamaica create mode 100644 testdata/zoneinfo/America/Jujuy create mode 100644 testdata/zoneinfo/America/Juneau create mode 100644 testdata/zoneinfo/America/Kentucky/Louisville create mode 100644 testdata/zoneinfo/America/Kentucky/Monticello create mode 100644 testdata/zoneinfo/America/Knox_IN create mode 100644 testdata/zoneinfo/America/Kralendijk create mode 100644 testdata/zoneinfo/America/La_Paz create mode 100644 testdata/zoneinfo/America/Lima create mode 100644 testdata/zoneinfo/America/Los_Angeles create mode 100644 testdata/zoneinfo/America/Louisville create mode 100644 testdata/zoneinfo/America/Lower_Princes create mode 100644 testdata/zoneinfo/America/Maceio create mode 100644 testdata/zoneinfo/America/Managua create mode 100644 testdata/zoneinfo/America/Manaus create mode 100644 testdata/zoneinfo/America/Marigot create mode 100644 testdata/zoneinfo/America/Martinique create mode 100644 testdata/zoneinfo/America/Matamoros create mode 100644 testdata/zoneinfo/America/Mazatlan create mode 100644 testdata/zoneinfo/America/Mendoza create mode 100644 testdata/zoneinfo/America/Menominee create mode 100644 testdata/zoneinfo/America/Merida create mode 100644 testdata/zoneinfo/America/Metlakatla create mode 100644 testdata/zoneinfo/America/Mexico_City create mode 100644 testdata/zoneinfo/America/Miquelon create mode 100644 testdata/zoneinfo/America/Moncton create mode 100644 testdata/zoneinfo/America/Monterrey create mode 100644 testdata/zoneinfo/America/Montevideo create mode 100644 testdata/zoneinfo/America/Montreal create mode 100644 testdata/zoneinfo/America/Montserrat create mode 100644 testdata/zoneinfo/America/Nassau create mode 100644 testdata/zoneinfo/America/New_York create mode 100644 testdata/zoneinfo/America/Nipigon create mode 100644 testdata/zoneinfo/America/Nome create mode 100644 testdata/zoneinfo/America/Noronha create mode 100644 testdata/zoneinfo/America/North_Dakota/Beulah create mode 100644 testdata/zoneinfo/America/North_Dakota/Center create mode 100644 testdata/zoneinfo/America/North_Dakota/New_Salem create mode 100644 testdata/zoneinfo/America/Nuuk create mode 100644 testdata/zoneinfo/America/Ojinaga create mode 100644 testdata/zoneinfo/America/Panama create mode 100644 testdata/zoneinfo/America/Pangnirtung create mode 100644 testdata/zoneinfo/America/Paramaribo create mode 100644 testdata/zoneinfo/America/Phoenix create mode 100644 testdata/zoneinfo/America/Port-au-Prince create mode 100644 testdata/zoneinfo/America/Port_of_Spain create mode 100644 testdata/zoneinfo/America/Porto_Acre create mode 100644 testdata/zoneinfo/America/Porto_Velho create mode 100644 testdata/zoneinfo/America/Puerto_Rico create mode 100644 testdata/zoneinfo/America/Punta_Arenas create mode 100644 testdata/zoneinfo/America/Rainy_River create mode 100644 testdata/zoneinfo/America/Rankin_Inlet create mode 100644 testdata/zoneinfo/America/Recife create mode 100644 testdata/zoneinfo/America/Regina create mode 100644 testdata/zoneinfo/America/Resolute create mode 100644 testdata/zoneinfo/America/Rio_Branco create mode 100644 testdata/zoneinfo/America/Rosario create mode 100644 testdata/zoneinfo/America/Santa_Isabel create mode 100644 testdata/zoneinfo/America/Santarem create mode 100644 testdata/zoneinfo/America/Santiago create mode 100644 testdata/zoneinfo/America/Santo_Domingo create mode 100644 testdata/zoneinfo/America/Sao_Paulo create mode 100644 testdata/zoneinfo/America/Scoresbysund create mode 100644 testdata/zoneinfo/America/Shiprock create mode 100644 testdata/zoneinfo/America/Sitka create mode 100644 testdata/zoneinfo/America/St_Barthelemy create mode 100644 testdata/zoneinfo/America/St_Johns create mode 100644 testdata/zoneinfo/America/St_Kitts create mode 100644 testdata/zoneinfo/America/St_Lucia create mode 100644 testdata/zoneinfo/America/St_Thomas create mode 100644 testdata/zoneinfo/America/St_Vincent create mode 100644 testdata/zoneinfo/America/Swift_Current create mode 100644 testdata/zoneinfo/America/Tegucigalpa create mode 100644 testdata/zoneinfo/America/Thule create mode 100644 testdata/zoneinfo/America/Thunder_Bay create mode 100644 testdata/zoneinfo/America/Tijuana create mode 100644 testdata/zoneinfo/America/Toronto create mode 100644 testdata/zoneinfo/America/Tortola create mode 100644 testdata/zoneinfo/America/Vancouver create mode 100644 testdata/zoneinfo/America/Virgin create mode 100644 testdata/zoneinfo/America/Whitehorse create mode 100644 testdata/zoneinfo/America/Winnipeg create mode 100644 testdata/zoneinfo/America/Yakutat create mode 100644 testdata/zoneinfo/America/Yellowknife create mode 100644 testdata/zoneinfo/Antarctica/Casey create mode 100644 testdata/zoneinfo/Antarctica/Davis create mode 100644 testdata/zoneinfo/Antarctica/DumontDUrville create mode 100644 testdata/zoneinfo/Antarctica/Macquarie create mode 100644 testdata/zoneinfo/Antarctica/Mawson create mode 100644 testdata/zoneinfo/Antarctica/McMurdo create mode 100644 testdata/zoneinfo/Antarctica/Palmer create mode 100644 testdata/zoneinfo/Antarctica/Rothera create mode 100644 testdata/zoneinfo/Antarctica/South_Pole create mode 100644 testdata/zoneinfo/Antarctica/Syowa create mode 100644 testdata/zoneinfo/Antarctica/Troll create mode 100644 testdata/zoneinfo/Antarctica/Vostok create mode 100644 testdata/zoneinfo/Arctic/Longyearbyen create mode 100644 testdata/zoneinfo/Asia/Aden create mode 100644 testdata/zoneinfo/Asia/Almaty create mode 100644 testdata/zoneinfo/Asia/Amman create mode 100644 testdata/zoneinfo/Asia/Anadyr create mode 100644 testdata/zoneinfo/Asia/Aqtau create mode 100644 testdata/zoneinfo/Asia/Aqtobe create mode 100644 testdata/zoneinfo/Asia/Ashgabat create mode 100644 testdata/zoneinfo/Asia/Ashkhabad create mode 100644 testdata/zoneinfo/Asia/Atyrau create mode 100644 testdata/zoneinfo/Asia/Baghdad create mode 100644 testdata/zoneinfo/Asia/Bahrain create mode 100644 testdata/zoneinfo/Asia/Baku create mode 100644 testdata/zoneinfo/Asia/Bangkok create mode 100644 testdata/zoneinfo/Asia/Barnaul create mode 100644 testdata/zoneinfo/Asia/Beirut create mode 100644 testdata/zoneinfo/Asia/Bishkek create mode 100644 testdata/zoneinfo/Asia/Brunei create mode 100644 testdata/zoneinfo/Asia/Calcutta create mode 100644 testdata/zoneinfo/Asia/Chita create mode 100644 testdata/zoneinfo/Asia/Choibalsan create mode 100644 testdata/zoneinfo/Asia/Chongqing create mode 100644 testdata/zoneinfo/Asia/Chungking create mode 100644 testdata/zoneinfo/Asia/Colombo create mode 100644 testdata/zoneinfo/Asia/Dacca create mode 100644 testdata/zoneinfo/Asia/Damascus create mode 100644 testdata/zoneinfo/Asia/Dhaka create mode 100644 testdata/zoneinfo/Asia/Dili create mode 100644 testdata/zoneinfo/Asia/Dubai create mode 100644 testdata/zoneinfo/Asia/Dushanbe create mode 100644 testdata/zoneinfo/Asia/Famagusta create mode 100644 testdata/zoneinfo/Asia/Gaza create mode 100644 testdata/zoneinfo/Asia/Harbin create mode 100644 testdata/zoneinfo/Asia/Hebron create mode 100644 testdata/zoneinfo/Asia/Ho_Chi_Minh create mode 100644 testdata/zoneinfo/Asia/Hong_Kong create mode 100644 testdata/zoneinfo/Asia/Hovd create mode 100644 testdata/zoneinfo/Asia/Irkutsk create mode 100644 testdata/zoneinfo/Asia/Istanbul create mode 100644 testdata/zoneinfo/Asia/Jakarta create mode 100644 testdata/zoneinfo/Asia/Jayapura create mode 100644 testdata/zoneinfo/Asia/Jerusalem create mode 100644 testdata/zoneinfo/Asia/Kabul create mode 100644 testdata/zoneinfo/Asia/Kamchatka create mode 100644 testdata/zoneinfo/Asia/Karachi create mode 100644 testdata/zoneinfo/Asia/Kashgar create mode 100644 testdata/zoneinfo/Asia/Kathmandu create mode 100644 testdata/zoneinfo/Asia/Katmandu create mode 100644 testdata/zoneinfo/Asia/Khandyga create mode 100644 testdata/zoneinfo/Asia/Kolkata create mode 100644 testdata/zoneinfo/Asia/Krasnoyarsk create mode 100644 testdata/zoneinfo/Asia/Kuala_Lumpur create mode 100644 testdata/zoneinfo/Asia/Kuching create mode 100644 testdata/zoneinfo/Asia/Kuwait create mode 100644 testdata/zoneinfo/Asia/Macao create mode 100644 testdata/zoneinfo/Asia/Macau create mode 100644 testdata/zoneinfo/Asia/Magadan create mode 100644 testdata/zoneinfo/Asia/Makassar create mode 100644 testdata/zoneinfo/Asia/Manila create mode 100644 testdata/zoneinfo/Asia/Muscat create mode 100644 testdata/zoneinfo/Asia/Nicosia create mode 100644 testdata/zoneinfo/Asia/Novokuznetsk create mode 100644 testdata/zoneinfo/Asia/Novosibirsk create mode 100644 testdata/zoneinfo/Asia/Omsk create mode 100644 testdata/zoneinfo/Asia/Oral create mode 100644 testdata/zoneinfo/Asia/Phnom_Penh create mode 100644 testdata/zoneinfo/Asia/Pontianak create mode 100644 testdata/zoneinfo/Asia/Pyongyang create mode 100644 testdata/zoneinfo/Asia/Qatar create mode 100644 testdata/zoneinfo/Asia/Qostanay create mode 100644 testdata/zoneinfo/Asia/Qyzylorda create mode 100644 testdata/zoneinfo/Asia/Rangoon create mode 100644 testdata/zoneinfo/Asia/Riyadh create mode 100644 testdata/zoneinfo/Asia/Saigon create mode 100644 testdata/zoneinfo/Asia/Sakhalin create mode 100644 testdata/zoneinfo/Asia/Samarkand create mode 100644 testdata/zoneinfo/Asia/Seoul create mode 100644 testdata/zoneinfo/Asia/Shanghai create mode 100644 testdata/zoneinfo/Asia/Singapore create mode 100644 testdata/zoneinfo/Asia/Srednekolymsk create mode 100644 testdata/zoneinfo/Asia/Taipei create mode 100644 testdata/zoneinfo/Asia/Tashkent create mode 100644 testdata/zoneinfo/Asia/Tbilisi create mode 100644 testdata/zoneinfo/Asia/Tehran create mode 100644 testdata/zoneinfo/Asia/Tel_Aviv create mode 100644 testdata/zoneinfo/Asia/Thimbu create mode 100644 testdata/zoneinfo/Asia/Thimphu create mode 100644 testdata/zoneinfo/Asia/Tokyo create mode 100644 testdata/zoneinfo/Asia/Tomsk create mode 100644 testdata/zoneinfo/Asia/Ujung_Pandang create mode 100644 testdata/zoneinfo/Asia/Ulaanbaatar create mode 100644 testdata/zoneinfo/Asia/Ulan_Bator create mode 100644 testdata/zoneinfo/Asia/Urumqi create mode 100644 testdata/zoneinfo/Asia/Ust-Nera create mode 100644 testdata/zoneinfo/Asia/Vientiane create mode 100644 testdata/zoneinfo/Asia/Vladivostok create mode 100644 testdata/zoneinfo/Asia/Yakutsk create mode 100644 testdata/zoneinfo/Asia/Yangon create mode 100644 testdata/zoneinfo/Asia/Yekaterinburg create mode 100644 testdata/zoneinfo/Asia/Yerevan create mode 100644 testdata/zoneinfo/Atlantic/Azores create mode 100644 testdata/zoneinfo/Atlantic/Bermuda create mode 100644 testdata/zoneinfo/Atlantic/Canary create mode 100644 testdata/zoneinfo/Atlantic/Cape_Verde create mode 100644 testdata/zoneinfo/Atlantic/Faeroe create mode 100644 testdata/zoneinfo/Atlantic/Faroe create mode 100644 testdata/zoneinfo/Atlantic/Jan_Mayen create mode 100644 testdata/zoneinfo/Atlantic/Madeira create mode 100644 testdata/zoneinfo/Atlantic/Reykjavik create mode 100644 testdata/zoneinfo/Atlantic/South_Georgia create mode 100644 testdata/zoneinfo/Atlantic/St_Helena create mode 100644 testdata/zoneinfo/Atlantic/Stanley create mode 100644 testdata/zoneinfo/Australia/ACT create mode 100644 testdata/zoneinfo/Australia/Adelaide create mode 100644 testdata/zoneinfo/Australia/Brisbane create mode 100644 testdata/zoneinfo/Australia/Broken_Hill create mode 100644 testdata/zoneinfo/Australia/Canberra create mode 100644 testdata/zoneinfo/Australia/Currie create mode 100644 testdata/zoneinfo/Australia/Darwin create mode 100644 testdata/zoneinfo/Australia/Eucla create mode 100644 testdata/zoneinfo/Australia/Hobart create mode 100644 testdata/zoneinfo/Australia/LHI create mode 100644 testdata/zoneinfo/Australia/Lindeman create mode 100644 testdata/zoneinfo/Australia/Lord_Howe create mode 100644 testdata/zoneinfo/Australia/Melbourne create mode 100644 testdata/zoneinfo/Australia/NSW create mode 100644 testdata/zoneinfo/Australia/North create mode 100644 testdata/zoneinfo/Australia/Perth create mode 100644 testdata/zoneinfo/Australia/Queensland create mode 100644 testdata/zoneinfo/Australia/South create mode 100644 testdata/zoneinfo/Australia/Sydney create mode 100644 testdata/zoneinfo/Australia/Tasmania create mode 100644 testdata/zoneinfo/Australia/Victoria create mode 100644 testdata/zoneinfo/Australia/West create mode 100644 testdata/zoneinfo/Australia/Yancowinna create mode 100644 testdata/zoneinfo/Brazil/Acre create mode 100644 testdata/zoneinfo/Brazil/DeNoronha create mode 100644 testdata/zoneinfo/Brazil/East create mode 100644 testdata/zoneinfo/Brazil/West create mode 100644 testdata/zoneinfo/CET create mode 100644 testdata/zoneinfo/CST6CDT create mode 100644 testdata/zoneinfo/Canada/Atlantic create mode 100644 testdata/zoneinfo/Canada/Central create mode 100644 testdata/zoneinfo/Canada/Eastern create mode 100644 testdata/zoneinfo/Canada/Mountain create mode 100644 testdata/zoneinfo/Canada/Newfoundland create mode 100644 testdata/zoneinfo/Canada/Pacific create mode 100644 testdata/zoneinfo/Canada/Saskatchewan create mode 100644 testdata/zoneinfo/Canada/Yukon create mode 100644 testdata/zoneinfo/Chile/Continental create mode 100644 testdata/zoneinfo/Chile/EasterIsland create mode 100644 testdata/zoneinfo/Cuba create mode 100644 testdata/zoneinfo/EET create mode 100644 testdata/zoneinfo/EST create mode 100644 testdata/zoneinfo/EST5EDT create mode 100644 testdata/zoneinfo/Egypt create mode 100644 testdata/zoneinfo/Eire create mode 100644 testdata/zoneinfo/Etc/GMT create mode 100644 testdata/zoneinfo/Etc/GMT+0 create mode 100644 testdata/zoneinfo/Etc/GMT+1 create mode 100644 testdata/zoneinfo/Etc/GMT+10 create mode 100644 testdata/zoneinfo/Etc/GMT+11 create mode 100644 testdata/zoneinfo/Etc/GMT+12 create mode 100644 testdata/zoneinfo/Etc/GMT+2 create mode 100644 testdata/zoneinfo/Etc/GMT+3 create mode 100644 testdata/zoneinfo/Etc/GMT+4 create mode 100644 testdata/zoneinfo/Etc/GMT+5 create mode 100644 testdata/zoneinfo/Etc/GMT+6 create mode 100644 testdata/zoneinfo/Etc/GMT+7 create mode 100644 testdata/zoneinfo/Etc/GMT+8 create mode 100644 testdata/zoneinfo/Etc/GMT+9 create mode 100644 testdata/zoneinfo/Etc/GMT-0 create mode 100644 testdata/zoneinfo/Etc/GMT-1 create mode 100644 testdata/zoneinfo/Etc/GMT-10 create mode 100644 testdata/zoneinfo/Etc/GMT-11 create mode 100644 testdata/zoneinfo/Etc/GMT-12 create mode 100644 testdata/zoneinfo/Etc/GMT-13 create mode 100644 testdata/zoneinfo/Etc/GMT-14 create mode 100644 testdata/zoneinfo/Etc/GMT-2 create mode 100644 testdata/zoneinfo/Etc/GMT-3 create mode 100644 testdata/zoneinfo/Etc/GMT-4 create mode 100644 testdata/zoneinfo/Etc/GMT-5 create mode 100644 testdata/zoneinfo/Etc/GMT-6 create mode 100644 testdata/zoneinfo/Etc/GMT-7 create mode 100644 testdata/zoneinfo/Etc/GMT-8 create mode 100644 testdata/zoneinfo/Etc/GMT-9 create mode 100644 testdata/zoneinfo/Etc/GMT0 create mode 100644 testdata/zoneinfo/Etc/Greenwich create mode 100644 testdata/zoneinfo/Etc/UCT create mode 100644 testdata/zoneinfo/Etc/UTC create mode 100644 testdata/zoneinfo/Etc/Universal create mode 100644 testdata/zoneinfo/Etc/Zulu create mode 100644 testdata/zoneinfo/Europe/Amsterdam create mode 100644 testdata/zoneinfo/Europe/Andorra create mode 100644 testdata/zoneinfo/Europe/Astrakhan create mode 100644 testdata/zoneinfo/Europe/Athens create mode 100644 testdata/zoneinfo/Europe/Belfast create mode 100644 testdata/zoneinfo/Europe/Belgrade create mode 100644 testdata/zoneinfo/Europe/Berlin create mode 100644 testdata/zoneinfo/Europe/Bratislava create mode 100644 testdata/zoneinfo/Europe/Brussels create mode 100644 testdata/zoneinfo/Europe/Bucharest create mode 100644 testdata/zoneinfo/Europe/Budapest create mode 100644 testdata/zoneinfo/Europe/Busingen create mode 100644 testdata/zoneinfo/Europe/Chisinau create mode 100644 testdata/zoneinfo/Europe/Copenhagen create mode 100644 testdata/zoneinfo/Europe/Dublin create mode 100644 testdata/zoneinfo/Europe/Gibraltar create mode 100644 testdata/zoneinfo/Europe/Guernsey create mode 100644 testdata/zoneinfo/Europe/Helsinki create mode 100644 testdata/zoneinfo/Europe/Isle_of_Man create mode 100644 testdata/zoneinfo/Europe/Istanbul create mode 100644 testdata/zoneinfo/Europe/Jersey create mode 100644 testdata/zoneinfo/Europe/Kaliningrad create mode 100644 testdata/zoneinfo/Europe/Kiev create mode 100644 testdata/zoneinfo/Europe/Kirov create mode 100644 testdata/zoneinfo/Europe/Kyiv create mode 100644 testdata/zoneinfo/Europe/Lisbon create mode 100644 testdata/zoneinfo/Europe/Ljubljana create mode 100644 testdata/zoneinfo/Europe/London create mode 100644 testdata/zoneinfo/Europe/Luxembourg create mode 100644 testdata/zoneinfo/Europe/Madrid create mode 100644 testdata/zoneinfo/Europe/Malta create mode 100644 testdata/zoneinfo/Europe/Mariehamn create mode 100644 testdata/zoneinfo/Europe/Minsk create mode 100644 testdata/zoneinfo/Europe/Monaco create mode 100644 testdata/zoneinfo/Europe/Moscow create mode 100644 testdata/zoneinfo/Europe/Nicosia create mode 100644 testdata/zoneinfo/Europe/Oslo create mode 100644 testdata/zoneinfo/Europe/Paris create mode 100644 testdata/zoneinfo/Europe/Podgorica create mode 100644 testdata/zoneinfo/Europe/Prague create mode 100644 testdata/zoneinfo/Europe/Riga create mode 100644 testdata/zoneinfo/Europe/Rome create mode 100644 testdata/zoneinfo/Europe/Samara create mode 100644 testdata/zoneinfo/Europe/San_Marino create mode 100644 testdata/zoneinfo/Europe/Sarajevo create mode 100644 testdata/zoneinfo/Europe/Saratov create mode 100644 testdata/zoneinfo/Europe/Simferopol create mode 100644 testdata/zoneinfo/Europe/Skopje create mode 100644 testdata/zoneinfo/Europe/Sofia create mode 100644 testdata/zoneinfo/Europe/Stockholm create mode 100644 testdata/zoneinfo/Europe/Tallinn create mode 100644 testdata/zoneinfo/Europe/Tirane create mode 100644 testdata/zoneinfo/Europe/Tiraspol create mode 100644 testdata/zoneinfo/Europe/Ulyanovsk create mode 100644 testdata/zoneinfo/Europe/Uzhgorod create mode 100644 testdata/zoneinfo/Europe/Vaduz create mode 100644 testdata/zoneinfo/Europe/Vatican create mode 100644 testdata/zoneinfo/Europe/Vienna create mode 100644 testdata/zoneinfo/Europe/Vilnius create mode 100644 testdata/zoneinfo/Europe/Volgograd create mode 100644 testdata/zoneinfo/Europe/Warsaw create mode 100644 testdata/zoneinfo/Europe/Zagreb create mode 100644 testdata/zoneinfo/Europe/Zaporozhye create mode 100644 testdata/zoneinfo/Europe/Zurich create mode 100644 testdata/zoneinfo/Factory create mode 100644 testdata/zoneinfo/GB create mode 100644 testdata/zoneinfo/GB-Eire create mode 100644 testdata/zoneinfo/GMT create mode 100644 testdata/zoneinfo/GMT+0 create mode 100644 testdata/zoneinfo/GMT-0 create mode 100644 testdata/zoneinfo/GMT0 create mode 100644 testdata/zoneinfo/Greenwich create mode 100644 testdata/zoneinfo/HST create mode 100644 testdata/zoneinfo/Hongkong create mode 100644 testdata/zoneinfo/Iceland create mode 100644 testdata/zoneinfo/Indian/Antananarivo create mode 100644 testdata/zoneinfo/Indian/Chagos create mode 100644 testdata/zoneinfo/Indian/Christmas create mode 100644 testdata/zoneinfo/Indian/Cocos create mode 100644 testdata/zoneinfo/Indian/Comoro create mode 100644 testdata/zoneinfo/Indian/Kerguelen create mode 100644 testdata/zoneinfo/Indian/Mahe create mode 100644 testdata/zoneinfo/Indian/Maldives create mode 100644 testdata/zoneinfo/Indian/Mauritius create mode 100644 testdata/zoneinfo/Indian/Mayotte create mode 100644 testdata/zoneinfo/Indian/Reunion create mode 100644 testdata/zoneinfo/Iran create mode 100644 testdata/zoneinfo/Israel create mode 100644 testdata/zoneinfo/Jamaica create mode 100644 testdata/zoneinfo/Japan create mode 100644 testdata/zoneinfo/Kwajalein create mode 100644 testdata/zoneinfo/Libya create mode 100644 testdata/zoneinfo/MET create mode 100644 testdata/zoneinfo/MST create mode 100644 testdata/zoneinfo/MST7MDT create mode 100644 testdata/zoneinfo/Mexico/BajaNorte create mode 100644 testdata/zoneinfo/Mexico/BajaSur create mode 100644 testdata/zoneinfo/Mexico/General create mode 100644 testdata/zoneinfo/NZ create mode 100644 testdata/zoneinfo/NZ-CHAT create mode 100644 testdata/zoneinfo/Navajo create mode 100644 testdata/zoneinfo/PRC create mode 100644 testdata/zoneinfo/PST8PDT create mode 100644 testdata/zoneinfo/Pacific/Apia create mode 100644 testdata/zoneinfo/Pacific/Auckland create mode 100644 testdata/zoneinfo/Pacific/Bougainville create mode 100644 testdata/zoneinfo/Pacific/Chatham create mode 100644 testdata/zoneinfo/Pacific/Chuuk create mode 100644 testdata/zoneinfo/Pacific/Easter create mode 100644 testdata/zoneinfo/Pacific/Efate create mode 100644 testdata/zoneinfo/Pacific/Enderbury create mode 100644 testdata/zoneinfo/Pacific/Fakaofo create mode 100644 testdata/zoneinfo/Pacific/Fiji create mode 100644 testdata/zoneinfo/Pacific/Funafuti create mode 100644 testdata/zoneinfo/Pacific/Galapagos create mode 100644 testdata/zoneinfo/Pacific/Gambier create mode 100644 testdata/zoneinfo/Pacific/Guadalcanal create mode 100644 testdata/zoneinfo/Pacific/Guam create mode 100644 testdata/zoneinfo/Pacific/Honolulu create mode 100644 testdata/zoneinfo/Pacific/Johnston create mode 100644 testdata/zoneinfo/Pacific/Kanton create mode 100644 testdata/zoneinfo/Pacific/Kiritimati create mode 100644 testdata/zoneinfo/Pacific/Kosrae create mode 100644 testdata/zoneinfo/Pacific/Kwajalein create mode 100644 testdata/zoneinfo/Pacific/Majuro create mode 100644 testdata/zoneinfo/Pacific/Marquesas create mode 100644 testdata/zoneinfo/Pacific/Midway create mode 100644 testdata/zoneinfo/Pacific/Nauru create mode 100644 testdata/zoneinfo/Pacific/Niue create mode 100644 testdata/zoneinfo/Pacific/Norfolk create mode 100644 testdata/zoneinfo/Pacific/Noumea create mode 100644 testdata/zoneinfo/Pacific/Pago_Pago create mode 100644 testdata/zoneinfo/Pacific/Palau create mode 100644 testdata/zoneinfo/Pacific/Pitcairn create mode 100644 testdata/zoneinfo/Pacific/Pohnpei create mode 100644 testdata/zoneinfo/Pacific/Ponape create mode 100644 testdata/zoneinfo/Pacific/Port_Moresby create mode 100644 testdata/zoneinfo/Pacific/Rarotonga create mode 100644 testdata/zoneinfo/Pacific/Saipan create mode 100644 testdata/zoneinfo/Pacific/Samoa create mode 100644 testdata/zoneinfo/Pacific/Tahiti create mode 100644 testdata/zoneinfo/Pacific/Tarawa create mode 100644 testdata/zoneinfo/Pacific/Tongatapu create mode 100644 testdata/zoneinfo/Pacific/Truk create mode 100644 testdata/zoneinfo/Pacific/Wake create mode 100644 testdata/zoneinfo/Pacific/Wallis create mode 100644 testdata/zoneinfo/Pacific/Yap create mode 100644 testdata/zoneinfo/Poland create mode 100644 testdata/zoneinfo/Portugal create mode 100644 testdata/zoneinfo/ROC create mode 100644 testdata/zoneinfo/ROK create mode 100644 testdata/zoneinfo/Singapore create mode 100644 testdata/zoneinfo/Turkey create mode 100644 testdata/zoneinfo/UCT create mode 100644 testdata/zoneinfo/US/Alaska create mode 100644 testdata/zoneinfo/US/Aleutian create mode 100644 testdata/zoneinfo/US/Arizona create mode 100644 testdata/zoneinfo/US/Central create mode 100644 testdata/zoneinfo/US/East-Indiana create mode 100644 testdata/zoneinfo/US/Eastern create mode 100644 testdata/zoneinfo/US/Hawaii create mode 100644 testdata/zoneinfo/US/Indiana-Starke create mode 100644 testdata/zoneinfo/US/Michigan create mode 100644 testdata/zoneinfo/US/Mountain create mode 100644 testdata/zoneinfo/US/Pacific create mode 100644 testdata/zoneinfo/US/Samoa create mode 100644 testdata/zoneinfo/UTC create mode 100644 testdata/zoneinfo/Universal create mode 100644 testdata/zoneinfo/W-SU create mode 100644 testdata/zoneinfo/WET create mode 100644 testdata/zoneinfo/Zulu create mode 100644 testdata/zoneinfo/iso3166.tab create mode 100644 testdata/zoneinfo/zone1970.tab create mode 100644 testdata/zoneinfo/zonenow.tab diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 000000000..bf1f06ce2 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,167 @@ +name: ci + +on: + push: + pull_request: + +env: + BAZEL_CXXOPTS: -std=c++17 + USE_BAZEL_VERSION: 8.5.1 + +jobs: + Linux-GCC: + runs-on: ubuntu-latest + steps: + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Tests + run: > + bazel test ... + --build_tag_filters=-fuzztest + --copt=-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1 + --copt=-Werror + --cxxopt=-Wall + --cxxopt=-Wextra + --cxxopt=-Wcast-qual + --cxxopt=-Wconversion-null + --cxxopt=-Wformat-security + --cxxopt=-Wmissing-declarations + --cxxopt=-Wnon-virtual-dtor + --cxxopt=-Woverlength-strings + --cxxopt=-Wpointer-arith + --cxxopt=-Wundef + --cxxopt=-Wunused-local-typedefs + --cxxopt=-Wunused-result + --cxxopt=-Wvarargs + --cxxopt=-Wvla + --cxxopt=-Wwrite-strings + --cxxopt=-Wno-missing-declarations + --cxxopt=-Wno-undef + --features=external_include_paths + --keep_going + --show_timestamps + --test_env="TZDIR=${GITHUB_WORKSPACE}/testdata/zoneinfo" + --test_output=errors + --test_tag_filters=-benchmark,-fuzztest + + Linux-Clang: + runs-on: ubuntu-latest + steps: + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Tests + run: > + bazel test ... + --build_tag_filters=-fuzztest + --copt=-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1 + --copt=-Werror + --cxxopt=-Wall + --cxxopt=-Wextra + --cxxopt=-Wc++98-compat-extra-semi + --cxxopt=-Wcast-qual + --cxxopt=-Wconversion + --cxxopt=-Wdeprecated-pragma + --cxxopt=-Wfloat-overflow-conversion + --cxxopt=-Wfloat-zero-conversion + --cxxopt=-Wfor-loop-analysis + --cxxopt=-Wformat-security + --cxxopt=-Wgnu-redeclared-enum + --cxxopt=-Winfinite-recursion + --cxxopt=-Winvalid-constexpr + --cxxopt=-Wliteral-conversion + --cxxopt=-Wmissing-declarations + --cxxopt=-Woverlength-strings + --cxxopt=-Wpointer-arith + --cxxopt=-Wself-assign + --cxxopt=-Wshadow-all + --cxxopt=-Wshorten-64-to-32 + --cxxopt=-Wsign-conversion + --cxxopt=-Wstring-conversion + --cxxopt=-Wtautological-overlap-compare + --cxxopt=-Wtautological-unsigned-zero-compare + --cxxopt=-Wuninitialized + --cxxopt=-Wunreachable-code + --cxxopt=-Wunused-comparison + --cxxopt=-Wunused-local-typedefs + --cxxopt=-Wunused-result + --cxxopt=-Wvla + --cxxopt=-Wwrite-strings + --cxxopt=-Wno-unknown-warning-option + --cxxopt=-Wno-undef + --features=external_include_paths + --keep_going + --repo_env=CC=clang + --show_timestamps + --test_env="TZDIR=${GITHUB_WORKSPACE}/testdata/zoneinfo" + --test_output=errors + --test_tag_filters=-benchmark,-fuzztest + + Linux-FuzzTest: + runs-on: ubuntu-latest + steps: + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Configure Fuzztest + run: bazel run @fuzztest//bazel:setup_configs > fuzztest.bazelrc + - name: Fuzz + run: > + bazel --bazelrc=fuzztest.bazelrc test ... + --build_tag_filters=fuzztest + --config=fuzztest + --copt=-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1 + --define=absl=1 + --features=external_include_paths + --keep_going + --repo_env=CC=clang + --show_timestamps + --test_arg=--fuzz_for=30s + --test_env="TZDIR=${GITHUB_WORKSPACE}/testdata/zoneinfo" + --test_output=errors + --test_tag_filters=fuzztest + + macOS: + runs-on: macos-latest + steps: + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Tests + run: > + bazel test ... + --build_tag_filters=-fuzztest + --cxxopt="-std=c++17" + --features=external_include_paths + --keep_going + --show_timestamps + --test_env="TZDIR=${GITHUB_WORKSPACE}/testdata/zoneinfo" + --test_output=errors + --test_tag_filters=-benchmark,-fuzztest + + Windows: + runs-on: windows-latest + steps: + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Tests + run: > + bazel test ... + --build_tag_filters="-fuzztest" + --keep_going + --show_timestamps + --test_env="TZDIR=$env:GITHUB_WORKSPACE\testdata\zoneinfo" + --test_output=errors + --test_tag_filters="-benchmark,-fuzztest" diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml new file mode 100644 index 000000000..56a2472cc --- /dev/null +++ b/.github/workflows/cifuzz.yml @@ -0,0 +1,24 @@ +name: CIFuzz +on: [pull_request] +jobs: + Fuzzing: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + id: build + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: 'cctz' + dry-run: false + - name: Run Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + oss-fuzz-project-name: 'cctz' + fuzz-seconds: 300 + dry-run: false + - name: Upload Crash + uses: actions/upload-artifact@v4 + if: failure() && steps.build.outcome == 'success' + with: + name: artifacts + path: ./out/artifacts diff --git a/.gitignore b/.gitignore index 96d1e7496..d1b6d112c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # ignore all files in the bazel directories /bazel-* +MODULE.bazel.lock # ignore non-bazel build products /build diff --git a/BUILD b/BUILD index 5d9cdc3c5..14d6b9716 100644 --- a/BUILD +++ b/BUILD @@ -4,7 +4,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,21 +12,38 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@rules_cc//cc:cc_binary.bzl", "cc_binary") +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") + +package( + features = [ + "header_modules", + "layering_check", + "parse_headers", + ], +) + +licenses(["notice"]) + ### libraries cc_library( name = "civil_time", + srcs = ["src/civil_time_detail.cc"], hdrs = [ - "include/civil_time.h", + "include/cctz/civil_time.h", ], includes = ["include"], - textual_hdrs = ["include/civil_time_detail.h"], + textual_hdrs = ["include/cctz/civil_time_detail.h"], visibility = ["//visibility:public"], ) cc_library( name = "time_zone", srcs = [ + "src/time_zone_fixed.cc", + "src/time_zone_fixed.h", "src/time_zone_format.cc", "src/time_zone_if.cc", "src/time_zone_if.h", @@ -40,56 +57,36 @@ cc_library( "src/time_zone_posix.cc", "src/time_zone_posix.h", "src/tzfile.h", - ], + "src/zone_info_source.cc", + ] + select({ + "@platforms//os:windows": [ + "src/time_zone_name_win.cc", + "src/time_zone_name_win.h", + ], + "//conditions:default": [], + }), hdrs = [ - "include/time_zone.h", + "include/cctz/time_zone.h", + "include/cctz/zone_info_source.h", ], includes = ["include"], - linkopts = [ - "-lm", - "-lpthread", - ], + linkopts = select({ + "@platforms//os:osx": ["-Wl,-framework,CoreFoundation"], + "@platforms//os:ios": ["-Wl,-framework,CoreFoundation"], + "//conditions:default": [], + }), visibility = ["//visibility:public"], deps = [":civil_time"], ) -cc_library( - name = "cctz_v1", - hdrs = [ - "src/cctz.h", - ], - includes = ["include"], - visibility = ["//visibility:public"], - deps = [ - ":civil_time", - ":time_zone", - ], -) - ### tests -# Builds the Google Test source that was fetched from another repository. cc_library( - name = "gtest", - srcs = glob( - [ - "google*/src/*.cc", - ], - exclude = glob([ - "google*/src/*-all.cc", - "googlemock/src/gmock_main.cc", - ]), - ), - hdrs = glob(["*/include/**/*.h"]), - includes = [ - "googlemock/", - "googlemock/include", - "googletest/", - "googletest/include", - ], - linkopts = ["-pthread"], - textual_hdrs = ["googletest/src/gtest-internal-inl.h"], - visibility = ["//visibility:public"], + name = "test_time_zone_names", + testonly = True, + srcs = ["src/test_time_zone_names.cc"], + hdrs = ["src/test_time_zone_names.h"], + visibility = ["//visibility:private"], ) cc_test( @@ -97,8 +94,9 @@ cc_test( size = "small", srcs = ["src/civil_time_test.cc"], deps = [ - "@gtest//:gtest", ":civil_time", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -107,9 +105,10 @@ cc_test( size = "small", srcs = ["src/time_zone_format_test.cc"], deps = [ - "@gtest//:gtest", ":civil_time", ":time_zone", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) @@ -118,20 +117,54 @@ cc_test( size = "small", srcs = ["src/time_zone_lookup_test.cc"], deps = [ - "@gtest//:gtest", ":civil_time", + ":test_time_zone_names", ":time_zone", + "@googletest//:gtest", + "@googletest//:gtest_main", ], ) cc_test( - name = "cctz_v1_test", - size = "small", - srcs = ["src/cctz_v1_test.cc"], - defines = ["CCTZ_ACK_V1_DEPRECATION=1"], + name = "time_zone_fuzz_test", + srcs = [ + "src/time_zone_fuzz_test.cc", + "src/time_zone_if.h", + "src/time_zone_impl.h", + "src/time_zone_info.h", + "src/tzfile.h", + ], + tags = [ + "fuzztest", + ], deps = [ - "@gtest//:gtest", - ":cctz_v1", + ":civil_time", + ":test_time_zone_names", + ":time_zone", + "@fuzztest//fuzztest", + "@fuzztest//fuzztest:fuzztest_gtest_main", + "@googletest//:gtest", + ], +) + +### benchmarks + +cc_test( + name = "cctz_benchmark", + srcs = [ + "src/cctz_benchmark.cc", + "src/time_zone_if.h", + "src/time_zone_impl.h", + "src/time_zone_info.h", + "src/tzfile.h", + ], + linkstatic = 1, + tags = ["benchmark"], + deps = [ + ":civil_time", + ":test_time_zone_names", + ":time_zone", + "@google_benchmark//:benchmark_main", ], ) @@ -145,10 +178,6 @@ cc_binary( cc_binary( name = "epoch_shift", srcs = ["examples/epoch_shift.cc"], - deps = [ - ":civil_time", - ":time_zone", - ], ) cc_binary( @@ -163,10 +192,7 @@ cc_binary( cc_binary( name = "example2", srcs = ["examples/example2.cc"], - deps = [ - ":civil_time", - ":time_zone", - ], + deps = [":time_zone"], ) cc_binary( @@ -200,7 +226,13 @@ cc_binary( cc_binary( name = "time_tool", - srcs = ["src/time_tool.cc"], + srcs = [ + "src/time_tool.cc", + "src/time_zone_if.h", + "src/time_zone_impl.h", + "src/time_zone_info.h", + "src/tzfile.h", + ], deps = [ ":civil_time", ":time_zone", diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..f8bfbdda2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,198 @@ +# https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md +# As of 2024-07-01, CMake 3.16 is the minimum supported version. +cmake_minimum_required(VERSION 3.16) + +project(cctz) + +set(CMAKE_MODULE_PATH + ${PROJECT_SOURCE_DIR}/cmake + ${PROJECT_SOURCE_DIR}/cmake/modules + ${CMAKE_MODULE_PATH}) + +include(CTest) +include(FeatureSummary) + +option(BUILD_TOOLS "Whether or not to build tools" ON) +option(BUILD_EXAMPLES "Whether or not to build examples" ON) +option(BUILD_BENCHMARK "Whether or not to build the benchmark application (has no effect if BUILD_TESTING is disabled)" ON) + +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ${BUILD_SHARED_LIBS}) + +if (BUILD_TESTING) + if (BUILD_BENCHMARK) + find_package(benchmark QUIET) + set_package_properties(benchmark PROPERTIES + TYPE REQUIRED + DESCRIPTION "a microbenchmark support library" + URL "https://github.com/google/benchmark" + ) + endif() + + find_package(GMock) + set_package_properties(GMock PROPERTIES + TYPE REQUIRED + DESCRIPTION "the Google C++ mocking framework" + URL "https://github.com/google/googletest" + ) + + find_package(GTest) + set_package_properties(GTest PROPERTIES + TYPE REQUIRED + DESCRIPTION "the Google C++ test framework" + URL "https://github.com/google/googletest" + ) + + find_package(Threads) + set_package_properties(Threads PROPERTIES + TYPE REQUIRED + DESCRIPTION "the system thread library" + ) +endif() + +# If a specific standard is required, +# it can be set from the command line with: +# cmake -DCMAKE_CXX_STANDARD=[11|14|17|20|23] +function(cctz_target_set_cxx_standard target) + set(cxx_standard 11) + target_compile_features(${target} PUBLIC cxx_std_${cxx_standard}) +endfunction() + +if(APPLE) + find_library(CoreFoundation CoreFoundation) +endif() + +set(CCTZ_HDRS + include/cctz/time_zone.h + include/cctz/civil_time_detail.h + include/cctz/zone_info_source.h + include/cctz/civil_time.h + ) +add_library(cctz + src/civil_time_detail.cc + src/time_zone_fixed.cc + src/time_zone_fixed.h + src/time_zone_format.cc + src/time_zone_if.cc + src/time_zone_if.h + src/time_zone_impl.cc + src/time_zone_impl.h + src/time_zone_info.cc + src/time_zone_info.h + src/time_zone_libc.cc + src/time_zone_libc.h + src/time_zone_lookup.cc + src/time_zone_posix.cc + src/time_zone_posix.h + src/tzfile.h + src/zone_info_source.cc + $<$:src/time_zone_name_win.cc> + $<$:src/time_zone_name_win.h> + ${CCTZ_HDRS} + ) +cctz_target_set_cxx_standard(cctz) +target_include_directories(cctz PUBLIC + $ + $ + ) +set_target_properties(cctz PROPERTIES + PUBLIC_HEADER "${CCTZ_HDRS}" + ) +if(APPLE) + target_link_libraries(cctz PUBLIC ${CoreFoundation}) +endif() +add_library(cctz::cctz ALIAS cctz) + +if (BUILD_TOOLS) + add_executable(time_tool src/time_tool.cc) + cctz_target_set_cxx_standard(time_tool) + target_link_libraries(time_tool cctz::cctz) +endif() + +if (BUILD_EXAMPLES) + add_subdirectory(examples) +endif() + +if (BUILD_TESTING) + add_library(test_time_zone_names + "src/test_time_zone_names.cc" + "src/test_time_zone_names.h" + ) + + add_executable(civil_time_test src/civil_time_test.cc) + cctz_target_set_cxx_standard(civil_time_test) + target_include_directories(civil_time_test PRIVATE ${GTEST_INCLUDE_DIRS}) + target_link_libraries(civil_time_test + cctz::cctz + ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ) + add_test(civil_time_test civil_time_test) + + add_executable(time_zone_lookup_test src/time_zone_lookup_test.cc) + cctz_target_set_cxx_standard(time_zone_lookup_test) + target_include_directories(time_zone_lookup_test PRIVATE ${GTEST_INCLUDE_DIRS}) + target_link_libraries(time_zone_lookup_test + cctz::cctz + test_time_zone_names + ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ) + add_test(time_zone_lookup_test time_zone_lookup_test) + + add_executable(time_zone_format_test src/time_zone_format_test.cc) + cctz_target_set_cxx_standard(time_zone_format_test) + target_link_libraries(time_zone_format_test + cctz::cctz + ${CMAKE_THREAD_LIBS_INIT} + GMock::Main + ) + add_test(time_zone_format_test time_zone_format_test) + + # tests runs on testdata + set_property( + TEST + civil_time_test + time_zone_format_test + time_zone_lookup_test + PROPERTY + ENVIRONMENT "TZDIR=${CMAKE_CURRENT_SOURCE_DIR}/testdata/zoneinfo" + ) + + if (BUILD_BENCHMARK) + add_executable(cctz_benchmark src/cctz_benchmark.cc) + cctz_target_set_cxx_standard(cctz_benchmark) + target_link_libraries(cctz_benchmark + cctz::cctz + test_time_zone_names + benchmark::benchmark_main + ) + endif() +endif() + +# Install +include(GNUInstallDirs) +install(TARGETS cctz + EXPORT ${PROJECT_NAME}-targets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cctz + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) +if (BUILD_TOOLS) + install(TARGETS time_tool + EXPORT ${PROJECT_NAME}-targets + DESTINATION ${CMAKE_INSTALL_BINDIR} + ) +endif() +set(CMAKE_INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) +install(EXPORT ${PROJECT_NAME}-targets + NAMESPACE cctz:: + DESTINATION ${CMAKE_INSTALL_CONFIGDIR} + ) +install(FILES cmake/${PROJECT_NAME}-config.cmake + DESTINATION ${CMAKE_INSTALL_CONFIGDIR} + ) + +set(quiet_on_empty QUIET_ON_EMPTY) + +feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES ${quiet_on_empty}) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 94abbcece..cf0912ea8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,19 +4,19 @@ the end). ### Before you contribute Before we can use your code, you must sign the [Google Individual Contributor -License Agreement] -(https://developers.google.com/open-source/cla/individual?csw=1) (CLA), which -you can do online. The CLA is necessary mainly because you own the copyright to -your changes, even after your contribution becomes part of our codebase, so we -need your permission to use and distribute your code. We also need to be sure of -various other things—for instance that you'll tell us if you know that -your code infringes on other people's patents. You don't have to sign the CLA -until after you've submitted your code for review and a member has approved it, -but you must do it before we can put your code into our codebase. Before you -start working on a larger contribution, you should get in touch with us first -through the issue tracker with your idea so that we can help out and possibly -guide you. Coordinating up front makes it much easier to avoid frustration later -on. +License +Agreement](https://developers.google.com/open-source/cla/individual?csw=1) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us +if you know that your code infringes on other people's patents. You don't have +to sign the CLA until after you've submitted your code for review and a member +has approved it, but you must do it before we can put your code into our +codebase. Before you start working on a larger contribution, you should get in +touch with us first through the issue tracker with your idea so that we can help +out and possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. ### Code reviews diff --git a/LICENSE.txt b/LICENSE.txt index d64569567..ccd61dcfe 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,7 +1,7 @@ Apache License Version 2.0, January 2004 - http://www.apache.org/licenses/ + https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -193,10 +193,11 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 000000000..dccf97327 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,41 @@ +# Copyright 2024 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# https://bazel.build/external/overview#bzlmod + +module( + name = "cctz", + version = "head", + compatibility_level = 1, +) + +# Only direct dependencies need to be listed below. + +bazel_dep(name = "fuzztest", + version = "20250728.0", + dev_dependency = True) + +bazel_dep(name = "google_benchmark", + version = "1.9.4", + dev_dependency = True) + +bazel_dep(name = "googletest", + version = "1.17.0", + dev_dependency = True) + +bazel_dep(name = "platforms", + version = "1.0.0") + +bazel_dep(name = "rules_cc", + version = "0.1.4") diff --git a/Makefile b/Makefile index b97feded3..650496be1 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -12,47 +12,60 @@ # See the License for the specific language governing permissions and # limitations under the License. -# While Bazel (http://bazel.io) is the primary build system used by cctz, +# While Bazel (https://bazel.io) is the primary build system used by cctz, # this Makefile is provided as a convenience for those who can't use Bazel # and can't compile the sources in their own build system. # # Suggested usage: -# make -C build -f ../Makefile SRC=../ -j `nproc` +# +# To build locally: +# make -C build -f ../Makefile SRC=../ -j `nproc` +# +# To build/install a versioned shared library on Linux: +# make -C build -f ../Makefile SRC=../ -j `nproc` \ +# SHARED_LDFLAGS='-shared -Wl,-soname,libcctz.so.2' \ +# CCTZ_SHARED_LIB=libcctz.so.2.0 \ +# install install_shared_lib # local configuration -CXX = g++ -STD = c++11 -OPT = -O -PREFIX = /usr/local +CXX ?= g++ +CXXFLAGS ?= -O3 +STD ?= c++11 +LDFLAGS ?= -O3 +PREFIX ?= /usr/local +DESTDIR ?= # possible support for googletest ## TESTS = civil_time_test time_zone_lookup_test time_zone_format_test ## TEST_FLAGS = ... ## TEST_LIBS = ... -VPATH = $(SRC)include:$(SRC)src:$(SRC)examples -CC = $(CXX) -CPPFLAGS = -Wall -I$(SRC)include -std=$(STD) -pthread \ - $(TEST_FLAGS) $(OPT) -fPIC -MMD +VPATH = $(SRC)src:$(SRC)examples +CXXFLAGS += -g -Wall -I$(SRC)include -std=$(STD) \ + $(TEST_FLAGS) -fPIC -MMD ARFLAGS = rcs -LDFLAGS = -pthread -LDLIBS = $(TEST_LIBS) +LINK.o = $(LINK.cc) +LDLIBS += $(TEST_LIBS) +SHARED_LDFLAGS = -shared +INSTALL = install -CCTZ_LIB = libcctz.a +CCTZ = cctz +CCTZ_LIB = lib$(CCTZ).a +CCTZ_SHARED_LIB = lib$(CCTZ).so -CCTZ_HDRS = \ - civil_time.h \ - civil_time_detail.h \ - time_zone.h +CCTZ_HDRS = $(SRC)include/cctz/*.h CCTZ_OBJS = \ + civil_time_detail.o \ + time_zone_fixed.o \ time_zone_format.o \ time_zone_if.o \ time_zone_impl.o \ time_zone_info.o \ time_zone_libc.o \ time_zone_lookup.o \ - time_zone_posix.o + time_zone_posix.o \ + zone_info_source.o TOOLS = time_tool EXAMPLES = classic epoch_shift hello example1 example2 example3 example4 @@ -61,17 +74,32 @@ all: $(TESTS) $(TOOLS) $(EXAMPLES) $(TESTS) $(TOOLS) $(EXAMPLES): $(CCTZ_LIB) +$(TESTS:=.o) $(TOOLS:=.o) $(EXAMPLES:=.o): + $(CCTZ_LIB): $(CCTZ_OBJS) $(AR) $(ARFLAGS) $@ $(CCTZ_OBJS) -install: $(CCTZ_HDRS) $(CCTZ_LIB) - sudo cp -p $(CCTZ_HDRS) $(PREFIX)/include - sudo cp -p $(CCTZ_LIB) $(PREFIX)/lib +$(CCTZ_SHARED_LIB): $(CCTZ_OBJS) + $(LINK.o) $(LDFLAGS) $(SHARED_LDFLAGS) -o $@ $(CCTZ_OBJS) + +install: install_hdrs install_lib + +install_hdrs: $(CCTZ_HDRS) + $(INSTALL) -d $(DESTDIR)$(PREFIX)/include/cctz + $(INSTALL) -m 644 -p $? $(DESTDIR)$(PREFIX)/include/cctz + +install_lib: $(CCTZ_LIB) + $(INSTALL) -d $(DESTDIR)$(PREFIX)/lib + $(INSTALL) -m 644 -p $? $(DESTDIR)$(PREFIX)/lib + +install_shared_lib: $(CCTZ_SHARED_LIB) + $(INSTALL) -d $(DESTDIR)$(PREFIX)/lib + $(INSTALL) -m 644 -p $? $(DESTDIR)$(PREFIX)/lib clean: - @$(RM) -r $(EXAMPLES:=.dSYM) $(EXAMPLES:=.o) $(EXAMPLES:=.d) $(EXAMPLES) - @$(RM) -r $(TOOLS:=.dSYM) $(TOOLS:=.o) $(TOOLS:=.d) $(TOOLS) - @$(RM) -r $(TESTS:=.dSYM) $(TESTS:=.o) $(TESTS:=.d) $(TESTS) - @$(RM) $(CCTZ_OBJS) $(CCTZ_OBJS:.o=.d) $(CCTZ_LIB) + @$(RM) $(EXAMPLES:=.dSYM) $(EXAMPLES:=.o) $(EXAMPLES:=.d) $(EXAMPLES) + @$(RM) $(TOOLS:=.dSYM) $(TOOLS:=.o) $(TOOLS:=.d) $(TOOLS) + @$(RM) $(TESTS:=.dSYM) $(TESTS:=.o) $(TESTS:=.d) $(TESTS) + @$(RM) $(CCTZ_OBJS) $(CCTZ_OBJS:.o=.d) $(CCTZ_LIB) $(CCTZ_SHARED_LIB) -include $(CCTZ_OBJS:.o=.d) $(TESTS:=.d) $(TOOLS:=.d) $(EXAMPLES:=.d) diff --git a/README.md b/README.md index d40325fbc..eeaa01608 100644 --- a/README.md +++ b/README.md @@ -6,39 +6,74 @@ CCTZ contains two libraries that cooperate with `` to give C++ programmers all the necessary tools for computing with dates, times, and time zones in a simple and correct manner. The libraries in CCTZ are: -* **The Civil-Time Library** — This is a header-only library that supports - computing with human-scale time, such as dates (which are represented by the - `cctz::civil_day` class). This library is declared in `include/civil_time.h`. -* **The Time-Zone Library** — This library uses the IANA time zone - database that is installed on the system to convert between *absolute time* - and *civil time*. This library is declared in `include/time_zone.h`. - -These libraries are currently known to work on **Linux** and **Mac OS X**. We -are actively interested in help getting them working on Windows. Please contact -us if you're interested in contributing. +* **The Civil-Time Library** — This is a header-only library that + supports computing with human-scale time, such as dates (which are + represented by the `cctz::civil_day` class). This library is declared in + [`include/cctz/civil_time.h`](https://github.com/google/cctz/blob/master/include/cctz/civil_time.h). +* **The Time-Zone Library** — This library uses the IANA time zone + database that is installed on the system to convert between *absolute time* + and *civil time*. This library is declared in + [`include/cctz/time_zone.h`](https://github.com/google/cctz/blob/master/include/cctz/time_zone.h). + +These libraries are currently known to work on **Linux**, **Mac OS X**, and +**Android**. + +They will also work on **Windows** if you install the zoneinfo files. We are +interested, though, in an implementation of the cctz::TimeZoneIf interface that +calls the Windows time APIs instead. Please contact us if you're interested in +contributing. # Getting Started -CCTZ is best built and tested using the [Bazel](http://bazel.io) build system -and the [Google Test](https://github.com/google/googletest) framework. (There -is also a simple `Makefile` that should work if you're unable to use Bazel.) +CCTZ is best built and tested using the [Bazel](https://bazel.io) build system +and the [Google Test](https://github.com/google/googletest) framework. (There is +also a simple [`Makefile`](https://github.com/google/cctz/blob/master/Makefile) +and a +[`CMakeLists.txt`](https://github.com/google/cctz/blob/master/CMakeLists.txt) +that should work if you're unable to use Bazel.) -1. Download/install Bazel http://bazel.io/docs/install.html +1. Download/install + [Bazel](https://docs.bazel.build/versions/master/install.html) 2. Get the cctz source: `git clone https://github.com/google/cctz.git` then `cd cctz` 3. Build cctz and run the tests: `bazel test :all` +With CMake: + +1. Make sure you have CMake >= 3.16 installed. +2. Get the cctz source: `git clone https://github.com/google/cctz.git` then `cd + cctz`. +3. Build cctz so that is can be used by shared libraries and run the tests (use + `-DBUILD_TESTING=OFF` to skip the tests): + + mkdir mybuild + cd mybuild + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. + cmake --build . --config Release + ctest + cmake --build . --config Release --target install + +4. Use in your CMake-based project with: + + ```cmake + find_package(cctz REQUIRED) + add_executable(mytarget file.cc) + target_link_libraries(mytarget cctz::cctz) + ``` + Note: When using CCTZ in your own project, you might find it easiest to compile the sources using your existing build system. Next Steps: 1. See the documentation for the libraries in CCTZ: - * Civil Time: `include/civil_time.h` - * Time Zone: `include/time_zone.h` + * Civil Time: + [`include/cctz/civil_time.h`](https://github.com/google/cctz/blob/master/include/cctz/civil_time.h) + * Time Zone: + [`include/cctz/time_zone.h`](https://github.com/google/cctz/blob/master/include/cctz/time_zone.h) 2. Look at the examples in https://github.com/google/cctz/tree/master/examples -3. Join our mailing list to ask questions and keep informed of changes: - * https://groups.google.com/forum/#!forum/cctz +3. Join our mailing list to ask questions and keep informed of changes: + * https://groups.google.com/forum/#!forum/cctz # Fundamental Concepts @@ -63,15 +98,14 @@ types exist to represent absolute times, classically `time_t` and more recently `std::chrono::time_point`. *Civil time* is the legally recognized representation of time for ordinary -affairs (cf. http://www.merriam-webster.com/dictionary/civil). It is a -human-scale representation of time that consists of the six fields — -year, month, day, hour, minute, and second (sometimes shortened to "YMDHMS") -— and it follows the rules of the Proleptic Gregorian Calendar, with -24-hour days divided into 60-minute hours and 60-second minutes. Like absolute -times, civil times are also independent of all time zones and their related -complexities (e.g., DST). While `std::tm` contains the six civil-time fields -(YMDHMS), plus a few more, it does not have behavior to enforce the rules of -civil time. +affairs (cf. https://www.merriam-webster.com/dictionary/civil). It is a +human-scale representation of time that consists of the six fields — year, +month, day, hour, minute, and second (sometimes shortened to "YMDHMS") — +and it follows the rules of the Proleptic Gregorian Calendar, with 24-hour days +divided into 60-minute hours and 60-second minutes. Like absolute times, civil +times are also independent of all time zones and their related complexities +(e.g., DST). While `std::tm` contains the six civil-time fields (YMDHMS), plus a +few more, it does not have behavior to enforce the rules of civil time. *Time zones* are geo-political regions within which human-defined rules are shared to convert between the absolute-time and civil-time domains. A time @@ -88,15 +122,18 @@ deal with these concepts, they must have a library that correctly implements the above concepts. CCTZ adds to the existing C++11 `` library to fully implement the above concepts. -* Absolute time — This is implemented by the existing C++11 `` - library without modification. For example, an absolute point in time is - represented by a `std::chrono::time_point`. -* Civil time — This is implemented by the `include/civil_time.h` library - that is provided as part of CCTZ. For example, a "date" is represented by a - `cctz::civil_day`. -* Time zone — This is implemented by the `include/time_zone.h` library - that is provided as part of CCTZ. For example, a time zone is represented by - an instance of the class `cctz::time_zone`. +* Absolute time — This is implemented by the existing C++11 + [``](https://en.cppreference.com/w/cpp/chrono) library without + modification. For example, an absolute point in time is represented by a + `std::chrono::time_point`. +* Civil time — This is implemented by the + [`include/cctz/civil_time.h`](https://github.com/google/cctz/blob/master/include/cctz/civil_time.h) + library that is provided as part of CCTZ. For example, a "date" is + represented by a `cctz::civil_day`. +* Time zone — This is implemented by the + [`include/cctz/time_zone.h`](https://github.com/google/cctz/blob/master/include/cctz/time_zone.h) + library that is provided as part of CCTZ. For example, a time zone is + represented by an instance of the class `cctz::time_zone`. # Examples @@ -108,7 +145,7 @@ day happens to be the 29th, we also output the day of the week. ``` #include -#include "civil_time.h" +#include "cctz/civil_time.h" int main() { for (cctz::civil_day d(2016, 2, 1); d < cctz::civil_month(2016, 3); ++d) { @@ -137,13 +174,13 @@ Hello 2016-02-29 <- leap day is a Monday This example shows how to use all three libraries (``, civil time, and time zone) together. In this example, we know that viewers in New York watched -Neil Armstrong first walk on the moon on July 20, 1969 at 10:56 PM. But we'd -like to see what time it was for our friend watching in Sydney Australia. +Neil Armstrong's first walk on the moon on July 20, 1969 at 10:56 PM. But we'd +like to see what time it was for our friend watching in Sydney, Australia. ``` #include -#include "civil_time.h" -#include "time_zone.h" +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" int main() { cctz::time_zone nyc; @@ -179,11 +216,12 @@ historic event. # References -* CCTZ [FAQ](https://github.com/google/cctz/wiki/FAQ) -* See also the [Time Programming Fundamentals](https://youtu.be/2rnIHsqABfM) - talk from CppCon 2015 ([slides available here](http://goo.gl/ofof4N)). This - talk mostly describes the older CCTZ v1 API, but the *concepts* are the same. -* ISO C++ proposal to standardize the Civil-Time Library: - https://github.com/devjgm/papers/blob/master/d0215r1.md -* ISO C++ proposal to standardize the Time-Zone Library: - https://github.com/devjgm/papers/blob/master/d0216r1.md +* CCTZ [FAQ](https://github.com/google/cctz/wiki/FAQ) +* See also the [Time Programming Fundamentals](https://youtu.be/2rnIHsqABfM) + talk from CppCon 2015 ([slides available here](https://goo.gl/ofof4N)). This + talk mostly describes the older CCTZ v1 API, but the *concepts* are the + same. +* ISO C++ proposal to standardize the Civil-Time Library: + https://github.com/devjgm/papers/blob/master/d0215r1.md +* ISO C++ proposal to standardize the Time-Zone Library: + https://github.com/devjgm/papers/blob/master/d0216r1.md diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index 953aa2538..000000000 --- a/WORKSPACE +++ /dev/null @@ -1,6 +0,0 @@ -new_git_repository( - name = "gtest", - remote = "https://github.com/google/googletest.git", - commit = "de411c3e80120f8dcc2a3f4f62f3ca692c0431d7", - build_file = "BUILD", -) diff --git a/cmake/cctz-config.cmake b/cmake/cctz-config.cmake new file mode 100644 index 000000000..31877e43d --- /dev/null +++ b/cmake/cctz-config.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/cctz-targets.cmake") diff --git a/cmake/modules/FindGMock.cmake b/cmake/modules/FindGMock.cmake new file mode 100644 index 000000000..26864b299 --- /dev/null +++ b/cmake/modules/FindGMock.cmake @@ -0,0 +1,41 @@ +# Find the GMock libraries +# +# This module defines the following variable: +# GMOCK_FOUND - true if GMock has been found and can be used +# +# This module defines the following IMPORTED targets: +# GMock::GMock +# The Google Mock gmock library, if found; +# the GTest libraries are automatically added +# GMock::Main +# The Google Mock gmock_main library, if found + +find_path(GMOCK_INCLUDE_DIR gmock/gmock.h) +find_library(GMOCK_LIBRARY gmock) +find_library(GMOCK_MAIN_LIBRARY gmock_main) + +find_package(GTest) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GMock DEFAULT_MSG + GMOCK_LIBRARY GMOCK_MAIN_LIBRARY + GMOCK_INCLUDE_DIR + GTEST_FOUND +) +mark_as_advanced(GMOCK_INCLUDE_DIR GMOCK_LIBRARY GMOCK_MAIN_LIBRARY) + +if (GMOCK_FOUND AND NOT TARGET GMock::GMock) + add_library(GMock::GMock UNKNOWN IMPORTED) + set_target_properties(GMock::GMock PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${GTEST_INCLUDE_DIRS};${GMOCK_INCLUDE_DIR}") + set_target_properties(GMock::GMock PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" + IMPORTED_LOCATION "${GMOCK_LIBRARY}" + INTERFACE_LINK_LIBRARIES "${GTEST_LIBRARIES}") + + add_library(GMock::Main UNKNOWN IMPORTED) + set_target_properties(GMock::Main PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" + IMPORTED_LOCATION "${GMOCK_MAIN_LIBRARY}" + INTERFACE_LINK_LIBRARIES GMock::GMock) +endif() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 000000000..a3851d17c --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,27 @@ +add_executable(classic classic.cc) +cctz_target_set_cxx_standard(classic) +target_link_libraries(classic) + +add_executable(hello hello.cc) +cctz_target_set_cxx_standard(hello) +target_link_libraries(hello cctz::cctz) + +add_executable(epoch_shift epoch_shift.cc) +cctz_target_set_cxx_standard(epoch_shift) +target_link_libraries(epoch_shift cctz::cctz) + +add_executable(example1 example1.cc) +cctz_target_set_cxx_standard(example1) +target_link_libraries(example1 cctz::cctz) + +add_executable(example2 example2.cc) +cctz_target_set_cxx_standard(example2) +target_link_libraries(example2 cctz::cctz) + +add_executable(example3 example3.cc) +cctz_target_set_cxx_standard(example3) +target_link_libraries(example3 cctz::cctz) + +add_executable(example4 example4.cc) +cctz_target_set_cxx_standard(example4) +target_link_libraries(example4 cctz::cctz) diff --git a/examples/classic.cc b/examples/classic.cc index b8f289585..3a3a76c64 100644 --- a/examples/classic.cc +++ b/examples/classic.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,11 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include #include -#include #include -#include #include std::string format(const std::string& fmt, const std::tm& tm) { @@ -29,10 +26,18 @@ int main() { const std::time_t now = std::time(nullptr); std::tm tm_utc; +#if defined(_WIN32) || defined(_WIN64) + gmtime_s(&tm_utc, &now); +#else gmtime_r(&now, &tm_utc); - std::cout << format("UTC: %F %T\n", tm_utc); +#endif + std::cout << format("UTC: %Y-%m-%d %H:%M:%S\n", tm_utc); std::tm tm_local; +#if defined(_WIN32) || defined(_WIN64) + localtime_s(&tm_local, &now); +#else localtime_r(&now, &tm_local); - std::cout << format("Local: %F %T\n", tm_local); +#endif + std::cout << format("Local: %Y-%m-%d %H:%M:%S\n", tm_local); } diff --git a/examples/epoch_shift.cc b/examples/epoch_shift.cc index 080a2c992..b4e383f48 100644 --- a/examples/epoch_shift.cc +++ b/examples/epoch_shift.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include #include -#include #include +#include std::string format(const std::string& fmt, const std::tm& tm) { char buf[100]; @@ -35,8 +34,12 @@ int main() { int off = GetOffset(now, "America/New_York"); const std::time_t now_nyc = now + off; std::tm tm_nyc; +#if defined(_WIN32) || defined(_WIN64) + gmtime_s(&tm_nyc, &now_nyc); +#else gmtime_r(&now_nyc, &tm_nyc); - std::cout << format("NYC: %F %T\n", tm_nyc); +#endif + std::cout << format("NYC: %Y-%m-%d %H:%M:%S\n", tm_nyc); // Shift back: "local time_t" to UTC off = GetOffset(now_nyc, "America/New_York"); diff --git a/examples/example1.cc b/examples/example1.cc index 25896d39e..135854e99 100644 --- a/examples/example1.cc +++ b/examples/example1.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -15,8 +15,8 @@ #include #include -#include "civil_time.h" -#include "time_zone.h" +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" int main() { cctz::time_zone lax; @@ -28,6 +28,6 @@ int main() { cctz::time_zone nyc; load_time_zone("America/New_York", &nyc); - std::cout << cctz::format("Talk starts at %T %z (%Z)\n", tp, lax); - std::cout << cctz::format("Talk starts at %T %z (%Z)\n", tp, nyc); + std::cout << cctz::format("Talk starts at %H:%M:%S %z (%Z)\n", tp, lax); + std::cout << cctz::format("Talk starts at %H:%M:%S %z (%Z)\n", tp, nyc); } diff --git a/examples/example2.cc b/examples/example2.cc index 6f9196b44..e992d0b22 100644 --- a/examples/example2.cc +++ b/examples/example2.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -16,7 +16,7 @@ #include #include -#include "time_zone.h" +#include "cctz/time_zone.h" int main() { const std::string civil_string = "2015-09-22 09:35:00"; diff --git a/examples/example3.cc b/examples/example3.cc index 216acca46..71e0a6282 100644 --- a/examples/example3.cc +++ b/examples/example3.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include -#include "civil_time.h" -#include "time_zone.h" +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" int main() { cctz::time_zone lax; @@ -28,6 +29,6 @@ int main() { // First day of month, 6 months from now. const auto then = cctz::convert(cctz::civil_month(cs) + 6, lax); - std::cout << cctz::format("Now: %F %T %z\n", now, lax); - std::cout << cctz::format("6mo: %F %T %z\n", then, lax); + std::cout << cctz::format("Now: %Y-%m-%d %H:%M:%S %z\n", now, lax); + std::cout << cctz::format("6mo: %Y-%m-%d %H:%M:%S %z\n", then, lax); } diff --git a/examples/example4.cc b/examples/example4.cc index 7e43f727e..6a4cf7e60 100644 --- a/examples/example4.cc +++ b/examples/example4.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,15 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include -#include "civil_time.h" -#include "time_zone.h" +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" template -cctz::time_point FloorDay(cctz::time_point tp, - cctz::time_zone tz) { +cctz::time_point FloorDay(cctz::time_point tp, + cctz::time_zone tz) { return cctz::convert(cctz::civil_day(cctz::convert(tp, tz)), tz); } @@ -29,6 +30,6 @@ int main() { load_time_zone("America/Los_Angeles", &lax); const auto now = std::chrono::system_clock::now(); const auto day = FloorDay(now, lax); - std::cout << cctz::format("Now: %F %T %z\n", now, lax); - std::cout << cctz::format("Day: %F %T %z\n", day, lax); + std::cout << cctz::format("Now: %Y-%m-%d %H:%M:%S %z\n", now, lax); + std::cout << cctz::format("Day: %Y-%m-%d %H:%M:%S %z\n", day, lax); } diff --git a/examples/hello.cc b/examples/hello.cc index 52882b7db..357bc9ff0 100644 --- a/examples/hello.cc +++ b/examples/hello.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include #include +#include #include -#include "civil_time.h" -#include "time_zone.h" +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" int main() { cctz::time_zone syd; @@ -27,7 +27,7 @@ int main() { const auto tp1 = cctz::convert(cctz::civil_second(1969, 7, 21, 12, 56, 0), syd); - const std::string s = cctz::format("%F %T %z", tp1, syd); + const std::string s = cctz::format("%Y-%m-%d %H:%M:%S %z", tp1, syd); std::cout << s << "\n"; cctz::time_zone nyc; diff --git a/include/civil_time.h b/include/cctz/civil_time.h similarity index 97% rename from include/civil_time.h rename to include/cctz/civil_time.h index 4071822e8..57bd86cc0 100644 --- a/include/civil_time.h +++ b/include/cctz/civil_time.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -15,7 +15,7 @@ #ifndef CCTZ_CIVIL_TIME_H_ #define CCTZ_CIVIL_TIME_H_ -#include "civil_time_detail.h" +#include "cctz/civil_time_detail.h" namespace cctz { @@ -148,7 +148,7 @@ namespace cctz { // // All civil-time types have accessors for all six of the civil-time fields: // year, month, day, hour, minute, and second. Recall that fields inferior to -// the type's aligment will be set to their minimum valid value. +// the type's alignment will be set to their minimum valid value. // // civil_day d(2015, 6, 28); // // d.year() == 2015 @@ -277,7 +277,7 @@ using civil_second = detail::civil_second; // using detail::weekday; -// Returns the weekday for the given civil_day. +// Returns the weekday for the given civil-time value. // // civil_day a(2015, 8, 13); // weekday wd = get_weekday(a); // wd == weekday::thursday @@ -304,14 +304,14 @@ using detail::get_weekday; // // civil_day d = ... // // Gets the following Thursday if d is not already Thursday -// civil_day thurs1 = prev_weekday(d, weekday::thursday) + 7; +// civil_day thurs1 = next_weekday(d - 1, weekday::thursday); // // Gets the previous Thursday if d is not already Thursday -// civil_day thurs2 = next_weekday(d, weekday::thursday) - 7; +// civil_day thurs2 = prev_weekday(d + 1, weekday::thursday); // using detail::next_weekday; using detail::prev_weekday; -// Returns the day-of-year for the given civil_day. +// Returns the day-of-year for the given civil-time value. // // civil_day a(2015, 1, 1); // int yd_jan_1 = get_yearday(a); // yd_jan_1 = 1 diff --git a/include/cctz/civil_time_detail.h b/include/cctz/civil_time_detail.h new file mode 100644 index 000000000..c94daaf74 --- /dev/null +++ b/include/cctz/civil_time_detail.h @@ -0,0 +1,606 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CCTZ_CIVIL_TIME_DETAIL_H_ +#define CCTZ_CIVIL_TIME_DETAIL_H_ + +#include +#include +#include +#include + +// Disable constexpr support unless we are in C++14 mode. +#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) +#define CONSTEXPR_D constexpr // data +#define CONSTEXPR_F constexpr // function +#define CONSTEXPR_M constexpr // member +#else +#define CONSTEXPR_D const +#define CONSTEXPR_F inline +#define CONSTEXPR_M +#endif + +namespace cctz { + +// Support years that at least span the range of 64-bit time_t values. +using year_t = std::int_fast64_t; + +// Type alias that indicates an argument is not normalized (e.g., the +// constructor parameters and operands/results of addition/subtraction). +using diff_t = std::int_fast64_t; + +namespace detail { + +// Type aliases that indicate normalized argument values. +using month_t = std::int_fast8_t; // [1:12] +using day_t = std::int_fast8_t; // [1:31] +using hour_t = std::int_fast8_t; // [0:23] +using minute_t = std::int_fast8_t; // [0:59] +using second_t = std::int_fast8_t; // [0:59] + +// Normalized civil-time fields: Y-M-D HH:MM:SS. +struct fields { + CONSTEXPR_M fields(year_t year, month_t month, day_t day, + hour_t hour, minute_t minute, second_t second) + : y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {} + std::int_least64_t y; + std::int_least8_t m; + std::int_least8_t d; + std::int_least8_t hh; + std::int_least8_t mm; + std::int_least8_t ss; +}; + +struct second_tag {}; +struct minute_tag : second_tag {}; +struct hour_tag : minute_tag {}; +struct day_tag : hour_tag {}; +struct month_tag : day_tag {}; +struct year_tag : month_tag {}; + +//////////////////////////////////////////////////////////////////////// + +// Field normalization (without avoidable overflow). + +namespace impl { + +CONSTEXPR_F bool is_leap_year(year_t y) noexcept { + return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); +} +CONSTEXPR_F int year_index(year_t y, month_t m) noexcept { + const int yi = static_cast((y + (m > 2)) % 400); + return yi < 0 ? yi + 400 : yi; +} +CONSTEXPR_F int days_per_century(int yi) noexcept { + return 36524 + (yi == 0 || yi > 300); +} +CONSTEXPR_F int days_per_4years(int yi) noexcept { + return 1460 + (yi == 0 || yi > 300 || (yi - 1) % 100 < 96); +} +CONSTEXPR_F int days_per_year(year_t y, month_t m) noexcept { + return is_leap_year(y + (m > 2)) ? 366 : 365; +} +// The compiler cannot optimize away the check if we use +// -fsanitize=array-bounds. +// m is guaranteed to be in [1:12] in the caller, but the compiler cannot +// optimize away the check even when this function is inlined into BreakTime. +// To reduce the overhead, we use no_sanitize to skip the unnecessary +// -fsanitize=array-bounds check. Remove no_sanitize once the missed +// optimization is fixed. +#if defined(__clang__) && defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::no_sanitize) +[[clang::no_sanitize("array-bounds")]] +#endif +#endif +CONSTEXPR_F int days_per_month(year_t y, month_t m) noexcept { + CONSTEXPR_D int k_days_per_month[1 + 12] = { + -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 // non leap year + }; + return k_days_per_month[m] + (m == 2 && is_leap_year(y)); +} + +CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, + hour_t hh, minute_t mm, second_t ss) noexcept { + year_t ey = y % 400; + const year_t oey = ey; + ey += (cd / 146097) * 400; + cd %= 146097; + if (cd < 0) { + ey -= 400; + cd += 146097; + } + ey += (d / 146097) * 400; + d = d % 146097 + cd; + if (d > 0) { + if (d > 146097) { + ey += 400; + d -= 146097; + } + } else { + if (d > -365) { + // We often hit the previous year when stepping a civil time backwards, + // so special case it to avoid counting up by 100/4/1-year chunks. + ey -= 1; + d += days_per_year(ey, m); + } else { + ey -= 400; + d += 146097; + } + } + if (d > 365) { + int yi = year_index(ey, m); // Index into Gregorian 400 year cycle. + for (;;) { + int n = days_per_century(yi); + if (d <= n) break; + d -= n; + ey += 100; + yi += 100; + if (yi >= 400) yi -= 400; + } + for (;;) { + int n = days_per_4years(yi); + if (d <= n) break; + d -= n; + ey += 4; + yi += 4; + if (yi >= 400) yi -= 400; + } + for (;;) { + int n = days_per_year(ey, m); + if (d <= n) break; + d -= n; + ++ey; + } + } + if (d > 28) { + for (;;) { + int n = days_per_month(ey, m); + if (d <= n) break; + d -= n; + if (++m > 12) { + ++ey; + m = 1; + } + } + } + return fields(y + (ey - oey), m, static_cast(d), hh, mm, ss); +} +CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, + hour_t hh, minute_t mm, second_t ss) noexcept { + if (m != 12) { + y += m / 12; + m %= 12; + if (m <= 0) { + y -= 1; + m += 12; + } + } + return n_day(y, static_cast(m), d, cd, hh, mm, ss); +} +CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, + diff_t hh, minute_t mm, second_t ss) noexcept { + cd += hh / 24; + hh %= 24; + if (hh < 0) { + cd -= 1; + hh += 24; + } + return n_mon(y, m, d, cd, static_cast(hh), mm, ss); +} +CONSTEXPR_F fields n_min(year_t y, diff_t m, diff_t d, diff_t hh, diff_t ch, + diff_t mm, second_t ss) noexcept { + ch += mm / 60; + mm %= 60; + if (mm < 0) { + ch -= 1; + mm += 60; + } + return n_hour(y, m, d, hh / 24 + ch / 24, hh % 24 + ch % 24, + static_cast(mm), ss); +} +CONSTEXPR_F fields n_sec(year_t y, diff_t m, diff_t d, diff_t hh, diff_t mm, + diff_t ss) noexcept { + // Optimization for when (non-constexpr) fields are already normalized. + if (0 <= ss && ss < 60) { + const second_t nss = static_cast(ss); + if (0 <= mm && mm < 60) { + const minute_t nmm = static_cast(mm); + if (0 <= hh && hh < 24) { + const hour_t nhh = static_cast(hh); + if (1 <= d && d <= 28 && 1 <= m && m <= 12) { + const day_t nd = static_cast(d); + const month_t nm = static_cast(m); + return fields(y, nm, nd, nhh, nmm, nss); + } + return n_mon(y, m, d, 0, nhh, nmm, nss); + } + return n_hour(y, m, d, hh / 24, hh % 24, nmm, nss); + } + return n_min(y, m, d, hh, mm / 60, mm % 60, nss); + } + diff_t cm = ss / 60; + ss %= 60; + if (ss < 0) { + cm -= 1; + ss += 60; + } + return n_min(y, m, d, hh, mm / 60 + cm / 60, mm % 60 + cm % 60, + static_cast(ss)); +} + +} // namespace impl + +//////////////////////////////////////////////////////////////////////// + +// Increments the indicated (normalized) field by "n". +CONSTEXPR_F fields step(second_tag, fields f, diff_t n) noexcept { + return impl::n_sec(f.y, f.m, f.d, f.hh, f.mm + n / 60, f.ss + n % 60); +} +CONSTEXPR_F fields step(minute_tag, fields f, diff_t n) noexcept { + return impl::n_min(f.y, f.m, f.d, f.hh + n / 60, 0, f.mm + n % 60, f.ss); +} +CONSTEXPR_F fields step(hour_tag, fields f, diff_t n) noexcept { + return impl::n_hour(f.y, f.m, f.d + n / 24, 0, f.hh + n % 24, f.mm, f.ss); +} +CONSTEXPR_F fields step(day_tag, fields f, diff_t n) noexcept { + return impl::n_day(f.y, f.m, f.d, n, f.hh, f.mm, f.ss); +} +CONSTEXPR_F fields step(month_tag, fields f, diff_t n) noexcept { + return impl::n_mon(f.y + n / 12, f.m + n % 12, f.d, 0, f.hh, f.mm, f.ss); +} +CONSTEXPR_F fields step(year_tag, fields f, diff_t n) noexcept { + return fields(f.y + n, f.m, f.d, f.hh, f.mm, f.ss); +} + +//////////////////////////////////////////////////////////////////////// + +namespace impl { + +// Returns (v * f + a) but avoiding intermediate overflow when possible. +CONSTEXPR_F diff_t scale_add(diff_t v, diff_t f, diff_t a) noexcept { + return (v < 0) ? ((v + 1) * f + a) - f : ((v - 1) * f + a) + f; +} + +// Map a (normalized) Y/M/D to the number of days before/after 1970-01-01. +// Probably overflows for years outside [-292277022656:292277026595]. +CONSTEXPR_F diff_t ymd_ord(year_t y, month_t m, day_t d) noexcept { + const diff_t eyear = (m <= 2) ? y - 1 : y; + const diff_t era = (eyear >= 0 ? eyear : eyear - 399) / 400; + const diff_t yoe = eyear - era * 400; + const diff_t doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; + const diff_t doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; + return era * 146097 + doe - 719468; +} + +// Returns the difference in days between two normalized Y-M-D tuples. +// ymd_ord() will encounter integer overflow given extreme year values, +// yet the difference between two such extreme values may actually be +// small, so we take a little care to avoid overflow when possible by +// exploiting the 146097-day cycle. +CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, + year_t y2, month_t m2, day_t d2) noexcept { + const diff_t a_c4_off = y1 % 400; + const diff_t b_c4_off = y2 % 400; + diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off); + diff_t delta = ymd_ord(a_c4_off, m1, d1) - ymd_ord(b_c4_off, m2, d2); + if (c4_diff > 0 && delta < 0) { + delta += 2 * 146097; + c4_diff -= 2 * 400; + } else if (c4_diff < 0 && delta > 0) { + delta -= 2 * 146097; + c4_diff += 2 * 400; + } + return (c4_diff / 400 * 146097) + delta; +} + +} // namespace impl + +// Returns the difference between fields structs using the indicated unit. +CONSTEXPR_F diff_t difference(year_tag, fields f1, fields f2) noexcept { + return f1.y - f2.y; +} +CONSTEXPR_F diff_t difference(month_tag, fields f1, fields f2) noexcept { + return impl::scale_add(difference(year_tag{}, f1, f2), 12, (f1.m - f2.m)); +} +CONSTEXPR_F diff_t difference(day_tag, fields f1, fields f2) noexcept { + return impl::day_difference(f1.y, f1.m, f1.d, f2.y, f2.m, f2.d); +} +CONSTEXPR_F diff_t difference(hour_tag, fields f1, fields f2) noexcept { + return impl::scale_add(difference(day_tag{}, f1, f2), 24, (f1.hh - f2.hh)); +} +CONSTEXPR_F diff_t difference(minute_tag, fields f1, fields f2) noexcept { + return impl::scale_add(difference(hour_tag{}, f1, f2), 60, (f1.mm - f2.mm)); +} +CONSTEXPR_F diff_t difference(second_tag, fields f1, fields f2) noexcept { + return impl::scale_add(difference(minute_tag{}, f1, f2), 60, f1.ss - f2.ss); +} + +//////////////////////////////////////////////////////////////////////// + +// Aligns the (normalized) fields struct to the indicated field. +CONSTEXPR_F fields align(second_tag, fields f) noexcept { + return f; +} +CONSTEXPR_F fields align(minute_tag, fields f) noexcept { + return fields{f.y, f.m, f.d, f.hh, f.mm, 0}; +} +CONSTEXPR_F fields align(hour_tag, fields f) noexcept { + return fields{f.y, f.m, f.d, f.hh, 0, 0}; +} +CONSTEXPR_F fields align(day_tag, fields f) noexcept { + return fields{f.y, f.m, f.d, 0, 0, 0}; +} +CONSTEXPR_F fields align(month_tag, fields f) noexcept { + return fields{f.y, f.m, 1, 0, 0, 0}; +} +CONSTEXPR_F fields align(year_tag, fields f) noexcept { + return fields{f.y, 1, 1, 0, 0, 0}; +} + +//////////////////////////////////////////////////////////////////////// + +template +class civil_time { + public: + explicit CONSTEXPR_M civil_time(year_t y, diff_t m = 1, diff_t d = 1, + diff_t hh = 0, diff_t mm = 0, + diff_t ss = 0) noexcept + : civil_time(impl::n_sec(y, m, d, hh, mm, ss)) {} + + CONSTEXPR_M civil_time() noexcept : f_{1970, 1, 1, 0, 0, 0} {} + civil_time(const civil_time&) = default; + civil_time& operator=(const civil_time&) = default; + + // Conversion between civil times of different alignment. Conversion to + // a more precise alignment is allowed implicitly (e.g., day -> hour), + // but conversion where information is discarded must be explicit + // (e.g., second -> minute). + template + using preserves_data = + typename std::enable_if::value>::type; + template + CONSTEXPR_M civil_time(const civil_time& ct, + preserves_data* = nullptr) noexcept + : civil_time(ct.f_) {} + template + explicit CONSTEXPR_M civil_time(const civil_time& ct, + preserves_data* = nullptr) noexcept + : civil_time(ct.f_) {} + + // Factories for the maximum/minimum representable civil_time. + static CONSTEXPR_F auto (max)() -> civil_time { + const auto max_year = (std::numeric_limits::max)(); + return civil_time(max_year, 12, 31, 23, 59, 59); + } + static CONSTEXPR_F auto (min)() -> civil_time { + const auto min_year = (std::numeric_limits::min)(); + return civil_time(min_year, 1, 1, 0, 0, 0); + } + + // Field accessors. Note: All but year() return an int. + CONSTEXPR_M year_t year() const noexcept { return f_.y; } + CONSTEXPR_M int month() const noexcept { return f_.m; } + CONSTEXPR_M int day() const noexcept { return f_.d; } + CONSTEXPR_M int hour() const noexcept { return f_.hh; } + CONSTEXPR_M int minute() const noexcept { return f_.mm; } + CONSTEXPR_M int second() const noexcept { return f_.ss; } + + // Assigning arithmetic. + CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept { + return *this = *this + n; + } + CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept { + return *this = *this - n; + } + CONSTEXPR_M civil_time& operator++() noexcept { + return *this += 1; + } + CONSTEXPR_M civil_time operator++(int) noexcept { + const civil_time a = *this; + ++*this; + return a; + } + CONSTEXPR_M civil_time& operator--() noexcept { + return *this -= 1; + } + CONSTEXPR_M civil_time operator--(int) noexcept { + const civil_time a = *this; + --*this; + return a; + } + + // Binary arithmetic operators. + friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept { + return civil_time(step(T{}, a.f_, n)); + } + friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept { + return a + n; + } + friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept { + return n != (std::numeric_limits::min)() + ? civil_time(step(T{}, a.f_, -n)) + : civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1)); + } + friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept { + return difference(T{}, lhs.f_, rhs.f_); + } + + private: + // All instantiations of this template are allowed to call the following + // private constructor and access the private fields member. + template + friend class civil_time; + + // The designated constructor that all others eventually call. + explicit CONSTEXPR_M civil_time(fields f) noexcept : f_(align(T{}, f)) {} + + fields f_; +}; + +// Disallows difference between differently aligned types. +// auto n = civil_day(...) - civil_hour(...); // would be confusing. +template +CONSTEXPR_F diff_t operator-(civil_time, civil_time) = delete; + +using civil_year = civil_time; +using civil_month = civil_time; +using civil_day = civil_time; +using civil_hour = civil_time; +using civil_minute = civil_time; +using civil_second = civil_time; + +//////////////////////////////////////////////////////////////////////// + +// Relational operators that work with differently aligned objects. +// Always compares all six fields. +template +CONSTEXPR_F bool operator<(const civil_time& lhs, + const civil_time& rhs) noexcept { + return (lhs.year() < rhs.year() || + (lhs.year() == rhs.year() && + (lhs.month() < rhs.month() || + (lhs.month() == rhs.month() && + (lhs.day() < rhs.day() || + (lhs.day() == rhs.day() && + (lhs.hour() < rhs.hour() || + (lhs.hour() == rhs.hour() && + (lhs.minute() < rhs.minute() || + (lhs.minute() == rhs.minute() && + (lhs.second() < rhs.second()))))))))))); +} +template +CONSTEXPR_F bool operator<=(const civil_time& lhs, + const civil_time& rhs) noexcept { + return !(rhs < lhs); +} +template +CONSTEXPR_F bool operator>=(const civil_time& lhs, + const civil_time& rhs) noexcept { + return !(lhs < rhs); +} +template +CONSTEXPR_F bool operator>(const civil_time& lhs, + const civil_time& rhs) noexcept { + return rhs < lhs; +} +template +CONSTEXPR_F bool operator==(const civil_time& lhs, + const civil_time& rhs) noexcept { + return lhs.year() == rhs.year() && lhs.month() == rhs.month() && + lhs.day() == rhs.day() && lhs.hour() == rhs.hour() && + lhs.minute() == rhs.minute() && lhs.second() == rhs.second(); +} +template +CONSTEXPR_F bool operator!=(const civil_time& lhs, + const civil_time& rhs) noexcept { + return !(lhs == rhs); +} + +//////////////////////////////////////////////////////////////////////// + +enum class weekday { + monday, + tuesday, + wednesday, + thursday, + friday, + saturday, + sunday, +}; + +CONSTEXPR_F weekday get_weekday(const civil_second& cs) noexcept { + CONSTEXPR_D weekday k_weekday_by_mon_off[13] = { + weekday::monday, weekday::tuesday, weekday::wednesday, + weekday::thursday, weekday::friday, weekday::saturday, + weekday::sunday, weekday::monday, weekday::tuesday, + weekday::wednesday, weekday::thursday, weekday::friday, + weekday::saturday, + }; + CONSTEXPR_D int k_weekday_offsets[1 + 12] = { + -1, 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4, + }; + year_t wd = 2400 + (cs.year() % 400) - (cs.month() < 3); + wd += wd / 4 - wd / 100 + wd / 400; + wd += k_weekday_offsets[cs.month()] + cs.day(); + return k_weekday_by_mon_off[wd % 7 + 6]; +} + +//////////////////////////////////////////////////////////////////////// + +CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept { + CONSTEXPR_D weekday k_weekdays_forw[14] = { + weekday::monday, weekday::tuesday, weekday::wednesday, + weekday::thursday, weekday::friday, weekday::saturday, + weekday::sunday, weekday::monday, weekday::tuesday, + weekday::wednesday, weekday::thursday, weekday::friday, + weekday::saturday, weekday::sunday, + }; + weekday base = get_weekday(cd); + for (int i = 0;; ++i) { + if (base == k_weekdays_forw[i]) { + for (int j = i + 1;; ++j) { + if (wd == k_weekdays_forw[j]) { + return cd + (j - i); + } + } + } + } +} + +CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept { + CONSTEXPR_D weekday k_weekdays_back[14] = { + weekday::sunday, weekday::saturday, weekday::friday, + weekday::thursday, weekday::wednesday, weekday::tuesday, + weekday::monday, weekday::sunday, weekday::saturday, + weekday::friday, weekday::thursday, weekday::wednesday, + weekday::tuesday, weekday::monday, + }; + weekday base = get_weekday(cd); + for (int i = 0;; ++i) { + if (base == k_weekdays_back[i]) { + for (int j = i + 1;; ++j) { + if (wd == k_weekdays_back[j]) { + return cd - (j - i); + } + } + } + } +} + +CONSTEXPR_F int get_yearday(const civil_second& cs) noexcept { + CONSTEXPR_D int k_month_offsets[1 + 12] = { + -1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, + }; + const int feb29 = (cs.month() > 2 && impl::is_leap_year(cs.year())); + return k_month_offsets[cs.month()] + feb29 + cs.day(); +} + +//////////////////////////////////////////////////////////////////////// + +std::ostream& operator<<(std::ostream& os, const civil_year& y); +std::ostream& operator<<(std::ostream& os, const civil_month& m); +std::ostream& operator<<(std::ostream& os, const civil_day& d); +std::ostream& operator<<(std::ostream& os, const civil_hour& h); +std::ostream& operator<<(std::ostream& os, const civil_minute& m); +std::ostream& operator<<(std::ostream& os, const civil_second& s); +std::ostream& operator<<(std::ostream& os, weekday wd); + +} // namespace detail +} // namespace cctz + +#undef CONSTEXPR_M +#undef CONSTEXPR_F +#undef CONSTEXPR_D + +#endif // CCTZ_CIVIL_TIME_DETAIL_H_ diff --git a/include/cctz/time_zone.h b/include/cctz/time_zone.h new file mode 100644 index 000000000..2d4495ca6 --- /dev/null +++ b/include/cctz/time_zone.h @@ -0,0 +1,452 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// A library for translating between absolute times (represented by +// std::chrono::time_points of the std::chrono::system_clock) and civil +// times (represented by cctz::civil_second) using the rules defined by +// a time zone (cctz::time_zone). + +#ifndef CCTZ_TIME_ZONE_H_ +#define CCTZ_TIME_ZONE_H_ + +#include +#include +#include +#include +#include +#include + +#include "cctz/civil_time.h" + +namespace cctz { + +// Convenience aliases. Not intended as public API points. +template +using time_point = std::chrono::time_point; +using seconds = std::chrono::duration; +using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead. + +namespace detail { +template +std::pair, D> split_seconds(const time_point& tp); +std::pair, seconds> split_seconds( + const time_point& tp); +} // namespace detail + +// cctz::time_zone is an opaque, small, value-type class representing a +// geo-political region within which particular rules are used for mapping +// between absolute and civil times. Time zones are named using the TZ +// identifiers from the IANA Time Zone Database, such as "America/Los_Angeles" +// or "Australia/Sydney". Time zones are created from factory functions such +// as load_time_zone(). Note: strings like "PST" and "EDT" are not valid TZ +// identifiers. +// +// Example: +// cctz::time_zone utc = cctz::utc_time_zone(); +// cctz::time_zone pst = cctz::fixed_time_zone(std::chrono::hours(-8)); +// cctz::time_zone loc = cctz::local_time_zone(); +// cctz::time_zone lax; +// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } +// +// See also: +// - http://www.iana.org/time-zones +// - https://en.wikipedia.org/wiki/Zoneinfo +class time_zone { + public: + time_zone() : time_zone(nullptr) {} // Equivalent to UTC + time_zone(const time_zone&) = default; + time_zone& operator=(const time_zone&) = default; + + std::string name() const; + + // An absolute_lookup represents the civil time (cctz::civil_second) within + // this time_zone at the given absolute time (time_point). There are + // additionally a few other fields that may be useful when working with + // older APIs, such as std::tm. + // + // Example: + // const cctz::time_zone tz = ... + // const auto tp = std::chrono::system_clock::now(); + // const cctz::time_zone::absolute_lookup al = tz.lookup(tp); + struct absolute_lookup { + civil_second cs; + // Note: The following fields exist for backward compatibility with older + // APIs. Accessing these fields directly is a sign of imprudent logic in + // the calling code. Modern time-related code should only access this data + // indirectly by way of cctz::format(). + int offset; // civil seconds east of UTC + bool is_dst; // is offset non-standard? + const char* abbr; // time-zone abbreviation (e.g., "PST") + }; + absolute_lookup lookup(const time_point& tp) const; + template + absolute_lookup lookup(const time_point& tp) const { + return lookup(detail::split_seconds(tp).first); + } + + // A civil_lookup represents the absolute time(s) (time_point) that + // correspond to the given civil time (cctz::civil_second) within this + // time_zone. Usually the given civil time represents a unique instant + // in time, in which case the conversion is unambiguous. However, + // within this time zone, the given civil time may be skipped (e.g., + // during a positive UTC offset shift), or repeated (e.g., during a + // negative UTC offset shift). To account for these possibilities, + // civil_lookup is richer than just a single time_point. + // + // In all cases the civil_lookup::kind enum will indicate the nature + // of the given civil-time argument, and the pre, trans, and post + // members will give the absolute time answers using the pre-transition + // offset, the transition point itself, and the post-transition offset, + // respectively (all three times are equal if kind == UNIQUE). If any + // of these three absolute times is outside the representable range of a + // time_point the field is set to its maximum/minimum value. + // + // Example: + // cctz::time_zone lax; + // if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } + // + // // A unique civil time. + // auto jan01 = lax.lookup(cctz::civil_second(2011, 1, 1, 0, 0, 0)); + // // jan01.kind == cctz::time_zone::civil_lookup::UNIQUE + // // jan01.pre is 2011/01/01 00:00:00 -0800 + // // jan01.trans is 2011/01/01 00:00:00 -0800 + // // jan01.post is 2011/01/01 00:00:00 -0800 + // + // // A Spring DST transition, when there is a gap in civil time. + // auto mar13 = lax.lookup(cctz::civil_second(2011, 3, 13, 2, 15, 0)); + // // mar13.kind == cctz::time_zone::civil_lookup::SKIPPED + // // mar13.pre is 2011/03/13 03:15:00 -0700 + // // mar13.trans is 2011/03/13 03:00:00 -0700 + // // mar13.post is 2011/03/13 01:15:00 -0800 + // + // // A Fall DST transition, when civil times are repeated. + // auto nov06 = lax.lookup(cctz::civil_second(2011, 11, 6, 1, 15, 0)); + // // nov06.kind == cctz::time_zone::civil_lookup::REPEATED + // // nov06.pre is 2011/11/06 01:15:00 -0700 + // // nov06.trans is 2011/11/06 01:00:00 -0800 + // // nov06.post is 2011/11/06 01:15:00 -0800 + struct civil_lookup { + enum civil_kind { + UNIQUE, // the civil time was singular (pre == trans == post) + SKIPPED, // the civil time did not exist (pre >= trans > post) + REPEATED, // the civil time was ambiguous (pre < trans <= post) + } kind; + time_point pre; // uses the pre-transition offset + time_point trans; // instant of civil-offset change + time_point post; // uses the post-transition offset + }; + civil_lookup lookup(const civil_second& cs) const; + + // Finds the time of the next/previous offset change in this time zone. + // + // By definition, next_transition(tp, &trans) returns false when tp has + // its maximum value, and prev_transition(tp, &trans) returns false + // when tp has its minimum value. If the zone has no transitions, the + // result will also be false no matter what the argument. + // + // Otherwise, when tp has its minimum value, next_transition(tp, &trans) + // returns true and sets trans to the first recorded transition. Chains + // of calls to next_transition()/prev_transition() will eventually return + // false, but it is unspecified exactly when next_transition(tp, &trans) + // jumps to false, or what time is set by prev_transition(tp, &trans) for + // a very distant tp. + // + // Note: Enumeration of time-zone transitions is for informational purposes + // only. Modern time-related code should not care about when offset changes + // occur. + // + // Example: + // cctz::time_zone nyc; + // if (!cctz::load_time_zone("America/New_York", &nyc)) { ... } + // const auto now = std::chrono::system_clock::now(); + // auto tp = cctz::time_point::min(); + // cctz::time_zone::civil_transition trans; + // while (tp <= now && nyc.next_transition(tp, &trans)) { + // // transition: trans.from -> trans.to + // tp = nyc.lookup(trans.to).trans; + // } + struct civil_transition { + civil_second from; // the civil time we jump from + civil_second to; // the civil time we jump to + }; + bool next_transition(const time_point& tp, + civil_transition* trans) const; + template + bool next_transition(const time_point& tp, + civil_transition* trans) const { + return next_transition(detail::split_seconds(tp).first, trans); + } + bool prev_transition(const time_point& tp, + civil_transition* trans) const; + template + bool prev_transition(const time_point& tp, + civil_transition* trans) const { + return prev_transition(detail::split_seconds(tp).first, trans); + } + + // version() and description() provide additional information about the + // time zone. The content of each of the returned strings is unspecified, + // however, when the IANA Time Zone Database is the underlying data source + // the version() string will be in the familiar form (e.g, "2018e") or + // empty when unavailable. + // + // Note: These functions are for informational or testing purposes only. + std::string version() const; // empty when unknown + std::string description() const; + + // Relational operators. + friend bool operator==(time_zone lhs, time_zone rhs) { + return &lhs.effective_impl() == &rhs.effective_impl(); + } + friend bool operator!=(time_zone lhs, time_zone rhs) { + return !(lhs == rhs); + } + + class Impl; + + private: + explicit time_zone(const Impl* impl) : impl_(impl) {} + const Impl& effective_impl() const; // handles implicit UTC + const Impl* impl_; +}; + +// Loads the named time zone. May perform I/O on the initial load. +// If the name is invalid, or some other kind of error occurs, returns +// false and "*tz" is set to the UTC time zone. +bool load_time_zone(const std::string& name, time_zone* tz); + +// Returns a time_zone representing UTC. Cannot fail. +time_zone utc_time_zone(); + +// Returns a time zone that is a fixed offset (seconds east) from UTC. +// Note: If the absolute value of the offset is greater than 24 hours +// you'll get UTC (i.e., zero offset) instead. +time_zone fixed_time_zone(const seconds& offset); + +// Returns a time zone representing the local time zone. Falls back to UTC. +// Note: local_time_zone.name() may only be something like "localtime". +time_zone local_time_zone(); + +// Returns the civil time (cctz::civil_second) within the given time zone at +// the given absolute time (time_point). Since the additional fields provided +// by the time_zone::absolute_lookup struct should rarely be needed in modern +// code, this convert() function is simpler and should be preferred. +template +inline civil_second convert(const time_point& tp, const time_zone& tz) { + return tz.lookup(tp).cs; +} + +// Returns the absolute time (time_point) that corresponds to the given civil +// time within the given time zone. If the civil time is not unique (i.e., if +// it was either repeated or non-existent), then the returned time_point is +// the best estimate that preserves relative order. That is, this function +// guarantees that if cs1 < cs2, then convert(cs1, tz) <= convert(cs2, tz). +inline time_point convert(const civil_second& cs, + const time_zone& tz) { + const time_zone::civil_lookup cl = tz.lookup(cs); + if (cl.kind == time_zone::civil_lookup::SKIPPED) return cl.trans; + return cl.pre; +} + +namespace detail { +using femtoseconds = std::chrono::duration; +std::string format(const std::string&, const time_point&, + const femtoseconds&, const time_zone&); +bool parse(const std::string&, const std::string&, const time_zone&, + time_point*, femtoseconds*, std::string* err = nullptr); +template +bool join_seconds( + const time_point& sec, const femtoseconds& fs, + time_point>>* tpp); +template +bool join_seconds( + const time_point& sec, const femtoseconds& fs, + time_point>>* tpp); +template +bool join_seconds( + const time_point& sec, const femtoseconds& fs, + time_point>>* tpp); +bool join_seconds(const time_point& sec, const femtoseconds&, + time_point* tpp); +} // namespace detail + +// Formats the given time_point in the given cctz::time_zone according to +// the provided format string. Uses strftime()-like formatting options, +// with the following extensions: +// +// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) +// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) +// - %E#S - Seconds with # digits of fractional precision +// - %E*S - Seconds with full fractional precision (a literal '*') +// - %E#f - Fractional seconds with # digits of precision +// - %E*f - Fractional seconds with full precision (a literal '*') +// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) +// - %ET - The RFC3339 "date-time" separator "T" +// +// Note that %E0S behaves like %S, and %E0f produces no characters. In +// contrast %E*f always produces at least one digit, which may be '0'. +// +// Note that %Y produces as many characters as it takes to fully render the +// year. A year outside of [-999:9999] when formatted with %E4Y will produce +// more than four characters, just like %Y. +// +// Tip: Format strings should include the UTC offset (e.g., %z, %Ez, or %E*z) +// so that the resulting string uniquely identifies an absolute time. +// +// Example: +// cctz::time_zone lax; +// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } +// auto tp = cctz::convert(cctz::civil_second(2013, 1, 2, 3, 4, 5), lax); +// std::string f = cctz::format("%H:%M:%S", tp, lax); // "03:04:05" +// f = cctz::format("%H:%M:%E3S", tp, lax); // "03:04:05.000" +template +inline std::string format(const std::string& fmt, const time_point& tp, + const time_zone& tz) { + const auto p = detail::split_seconds(tp); + const auto n = std::chrono::duration_cast(p.second); + return detail::format(fmt, p.first, n, tz); +} + +// Parses an input string according to the provided format string and +// returns the corresponding time_point. Uses strftime()-like formatting +// options, with the same extensions as cctz::format(), but with the +// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez +// and %E*z also accept the same inputs, which (along with %z) includes +// 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'. +// +// %Y consumes as many numeric characters as it can, so the matching data +// should always be terminated with a non-numeric. %E4Y always consumes +// exactly four characters, including any sign. +// +// Unspecified fields are taken from the default date and time of ... +// +// "1970-01-01 00:00:00.0 +0000" +// +// For example, parsing a string of "15:45" (%H:%M) will return a time_point +// that represents "1970-01-01 15:45:00.0 +0000". +// +// Note that parse() returns time instants, so it makes most sense to parse +// fully-specified date/time strings that include a UTC offset (%z, %Ez, or +// %E*z). +// +// Note also that parse() only heeds the fields year, month, day, hour, +// minute, (fractional) second, and UTC offset. Other fields, like weekday (%a +// or %A), while parsed for syntactic validity, are ignored in the conversion. +// +// Date and time fields that are out-of-range will be treated as errors rather +// than normalizing them like cctz::civil_second() would do. For example, it +// is an error to parse the date "Oct 32, 2013" because 32 is out of range. +// +// A second of ":60" is normalized to ":00" of the following minute with +// fractional seconds discarded. The following table shows how the given +// seconds and subseconds will be parsed: +// +// "59.x" -> 59.x // exact +// "60.x" -> 00.0 // normalized +// "00.x" -> 00.x // exact +// +// Errors are indicated by returning false. +// +// Example: +// const cctz::time_zone tz = ... +// std::chrono::system_clock::time_point tp; +// if (cctz::parse("%Y-%m-%d", "2015-10-09", tz, &tp)) { +// ... +// } +template +inline bool parse(const std::string& fmt, const std::string& input, + const time_zone& tz, time_point* tpp) { + time_point sec; + detail::femtoseconds fs; + return detail::parse(fmt, input, tz, &sec, &fs) && + detail::join_seconds(sec, fs, tpp); +} + +namespace detail { + +// Split a time_point into a time_point and a D subseconds. +// Undefined behavior if time_point is not of sufficient range. +// Note that this means it is UB to call cctz::time_zone::lookup(tp) or +// cctz::format(fmt, tp, tz) with a time_point that is outside the range +// of a 64-bit std::time_t. +template +std::pair, D> split_seconds(const time_point& tp) { + auto sec = std::chrono::time_point_cast(tp); + auto sub = tp - sec; + if (sub.count() < 0) { + sec -= seconds(1); + sub += seconds(1); + } + return {sec, std::chrono::duration_cast(sub)}; +} + +inline std::pair, seconds> split_seconds( + const time_point& tp) { + return {tp, seconds::zero()}; +} + +// Join a time_point and femto subseconds into a time_point. +// Floors to the resolution of time_point. Returns false if time_point +// is not of sufficient range. +template +bool join_seconds( + const time_point& sec, const femtoseconds& fs, + time_point>>* tpp) { + using D = std::chrono::duration>; + // TODO(#199): Return false if result unrepresentable as a time_point. + *tpp = std::chrono::time_point_cast(sec); + *tpp += std::chrono::duration_cast(fs); + return true; +} + +template +bool join_seconds( + const time_point& sec, const femtoseconds&, + time_point>>* tpp) { + using D = std::chrono::duration>; + auto count = sec.time_since_epoch().count(); + if (count >= 0 || count % Num == 0) { + count /= Num; + } else { + count /= Num; + count -= 1; + } + if (count > (std::numeric_limits::max)()) return false; + if (count < (std::numeric_limits::min)()) return false; + *tpp = time_point() + D{static_cast(count)}; + return true; +} + +template +bool join_seconds( + const time_point& sec, const femtoseconds&, + time_point>>* tpp) { + using D = std::chrono::duration>; + auto count = sec.time_since_epoch().count(); + if (count > (std::numeric_limits::max)()) return false; + if (count < (std::numeric_limits::min)()) return false; + *tpp = time_point() + D{static_cast(count)}; + return true; +} + +inline bool join_seconds(const time_point& sec, const femtoseconds&, + time_point* tpp) { + *tpp = sec; + return true; +} + +} // namespace detail +} // namespace cctz + +#endif // CCTZ_TIME_ZONE_H_ diff --git a/include/cctz/zone_info_source.h b/include/cctz/zone_info_source.h new file mode 100644 index 000000000..08e91b3c1 --- /dev/null +++ b/include/cctz/zone_info_source.h @@ -0,0 +1,88 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CCTZ_ZONE_INFO_SOURCE_H_ +#define CCTZ_ZONE_INFO_SOURCE_H_ + +#include +#include +#include +#include + +namespace cctz { + +// A stdio-like interface for providing zoneinfo data for a particular zone. +class ZoneInfoSource { + public: + virtual ~ZoneInfoSource(); + + virtual std::size_t Read(void* ptr, std::size_t size) = 0; // like fread() + virtual int Skip(std::size_t offset) = 0; // like fseek() + + // Until the zoneinfo data supports versioning information, we provide + // a way for a ZoneInfoSource to indicate it out-of-band. The default + // implementation returns an empty string. + virtual std::string Version() const; +}; + +} // namespace cctz + +namespace cctz_extension { + +// A function-pointer type for a factory that returns a ZoneInfoSource +// given the name of a time zone and a fallback factory. Returns null +// when the data for the named zone cannot be found. +using ZoneInfoSourceFactory = + std::unique_ptr (*)( + const std::string&, + const std::function( + const std::string&)>&); + +// The user can control the mapping of zone names to zoneinfo data by +// providing a definition for cctz_extension::zone_info_source_factory. +// For example, given functions my_factory() and my_other_factory() that +// can return a ZoneInfoSource for a named zone, we could inject them into +// cctz::load_time_zone() with: +// +// namespace cctz_extension { +// namespace { +// std::unique_ptr CustomFactory( +// const std::string& name, +// const std::function( +// const std::string& name)>& fallback_factory) { +// if (auto zip = my_factory(name)) return zip; +// if (auto zip = fallback_factory(name)) return zip; +// if (auto zip = my_other_factory(name)) return zip; +// return nullptr; +// } +// } // namespace +// ZoneInfoSourceFactory zone_info_source_factory = CustomFactory; +// } // namespace cctz_extension +// +// This might be used, say, to use zoneinfo data embedded in the program, +// or read from a (possibly compressed) file archive, or both. +// +// cctz_extension::zone_info_source_factory() will be called: +// (1) from the same thread as the cctz::load_time_zone() call, +// (2) only once for any zone name, and +// (3) serially (i.e., no concurrent execution). +// +// The fallback factory obtains zoneinfo data by reading files in ${TZDIR}, +// and it is used automatically when no zone_info_source_factory definition +// is linked into the program. +extern ZoneInfoSourceFactory zone_info_source_factory; + +} // namespace cctz_extension + +#endif // CCTZ_ZONE_INFO_SOURCE_H_ diff --git a/include/civil_time_detail.h b/include/civil_time_detail.h deleted file mode 100644 index 976b39d48..000000000 --- a/include/civil_time_detail.h +++ /dev/null @@ -1,511 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include -#include - -// Disable constexpr support unless we are using clang in C++14 mode. -#if __clang__ && __cpp_constexpr >= 201304 -#define CONSTEXPR_D constexpr // data -#define CONSTEXPR_F constexpr // function -#define CONSTEXPR_M constexpr // member -#define CONSTEXPR_T constexpr // template -#else -#define CONSTEXPR_D const -#define CONSTEXPR_F inline -#define CONSTEXPR_M -#define CONSTEXPR_T -#endif - -namespace cctz { -namespace detail { - -// Normalized civil-time fields: Y-M-D HH:MM:SS. -struct fields { - int y; - int m; - int d; - int hh; - int mm; - int ss; -}; - -struct second_tag {}; -struct minute_tag : second_tag {}; -struct hour_tag : minute_tag {}; -struct day_tag : hour_tag {}; -struct month_tag : day_tag {}; -struct year_tag : month_tag {}; - -//////////////////////////////////////////////////////////////////////// - -// Field normalization (without avoidable overflow). - -namespace impl { - -CONSTEXPR_F bool is_leap_year(int y) noexcept { - return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); -} -CONSTEXPR_F int year_index(int y, int m) noexcept { - return (((y + (m > 2)) % 400) + 400) % 400; -} -CONSTEXPR_F int days_per_century(int y, int m) noexcept { - const int yi = year_index(y, m); - return 36524 + (yi == 0 || yi > 300); -} -CONSTEXPR_F int days_per_4years(int y, int m) noexcept { - const int yi = year_index(y, m); - return 1460 + (yi == 0 || yi > 300 || (yi - 1) % 100 < 96); -} -CONSTEXPR_F int days_per_year(int y, int m) noexcept { - return is_leap_year(y + (m > 2)) ? 366 : 365; -} -CONSTEXPR_F int days_per_month(int y, int m) noexcept { - CONSTEXPR_D signed char k_days_per_month[12] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 // non leap year - }; - return k_days_per_month[m - 1] + (m == 2 && is_leap_year(y)); -} - -CONSTEXPR_F fields n_day(int y, int m, int d, int cd, int hh, int mm, - int ss) noexcept { - y += (cd / 146097) * 400; - cd %= 146097; - if (cd < 0) { - y -= 400; - cd += 146097; - } - y += (d / 146097) * 400; - d = d % 146097 + cd; - if (d <= 0) { - y -= 400; - d += 146097; - } else if (d > 146097) { - y += 400; - d -= 146097; - } - if (d > 365) { - for (int n = days_per_century(y, m); d > n; n = days_per_century(y, m)) { - d -= n; - y += 100; - } - for (int n = days_per_4years(y, m); d > n; n = days_per_4years(y, m)) { - d -= n; - y += 4; - } - for (int n = days_per_year(y, m); d > n; n = days_per_year(y, m)) { - d -= n; - ++y; - } - } - if (d > 28) { - for (int n = days_per_month(y, m); d > n; n = days_per_month(y, m)) { - d -= n; - if (++m > 12) { - ++y; - m = 1; - } - } - } - return fields{y, m, d, hh, mm, ss}; -} -CONSTEXPR_F fields n_mon(int y, int m, int d, int cd, int hh, int mm, - int ss) noexcept { - y += m / 12; - m %= 12; - if (m <= 0) { - y -= 1; - m += 12; - } - return n_day(y, m, d, cd, hh, mm, ss); -} -CONSTEXPR_F fields n_hour(int y, int m, int d, int cd, int hh, int mm, - int ss) noexcept { - cd += hh / 24; - hh %= 24; - if (hh < 0) { - cd -= 1; - hh += 24; - } - return n_mon(y, m, d, cd, hh, mm, ss); -} -CONSTEXPR_F fields n_min(int y, int m, int d, int hh, int ch, int mm, - int ss) noexcept { - ch += mm / 60; - mm %= 60; - if (mm < 0) { - ch -= 1; - mm += 60; - } - return n_hour(y, m, d, hh / 24 + ch / 24, hh % 24 + ch % 24, mm, ss); -} -CONSTEXPR_F fields n_sec(int y, int m, int d, int hh, int mm, int ss) noexcept { - int cm = ss / 60; - ss %= 60; - if (ss < 0) { - cm -= 1; - ss += 60; - } - return n_min(y, m, d, hh, mm / 60 + cm / 60, mm % 60 + cm % 60, ss); -} - -} // namespace impl - -//////////////////////////////////////////////////////////////////////// - -// Increments the indicated (normalized) field by "n". -CONSTEXPR_F fields step(second_tag, fields f, int n) noexcept { - return impl::n_sec(f.y, f.m, f.d, f.hh, f.mm + n / 60, f.ss + n % 60); -} -CONSTEXPR_F fields step(minute_tag, fields f, int n) noexcept { - return impl::n_min(f.y, f.m, f.d, f.hh + n / 60, 0, f.mm + n % 60, f.ss); -} -CONSTEXPR_F fields step(hour_tag, fields f, int n) noexcept { - return impl::n_hour(f.y, f.m, f.d + n / 24, 0, f.hh + n % 24, f.mm, f.ss); -} -CONSTEXPR_F fields step(day_tag, fields f, int n) noexcept { - return impl::n_day(f.y, f.m, f.d, n, f.hh, f.mm, f.ss); -} -CONSTEXPR_F fields step(month_tag, fields f, int n) noexcept { - return impl::n_mon(f.y + n / 12, f.m + n % 12, f.d, 0, f.hh, f.mm, f.ss); -} -CONSTEXPR_F fields step(year_tag, fields f, int n) noexcept { - return fields{f.y + n, f.m, f.d, f.hh, f.mm, f.ss}; -} - -//////////////////////////////////////////////////////////////////////// - -// Aligns the (normalized) fields struct to the indicated field. -CONSTEXPR_F fields align(second_tag, fields f) noexcept { - return f; -} -CONSTEXPR_F fields align(minute_tag, fields f) noexcept { - return fields{f.y, f.m, f.d, f.hh, f.mm, 0}; -} -CONSTEXPR_F fields align(hour_tag, fields f) noexcept { - return fields{f.y, f.m, f.d, f.hh, 0, 0}; -} -CONSTEXPR_F fields align(day_tag, fields f) noexcept { - return fields{f.y, f.m, f.d, 0, 0, 0}; -} -CONSTEXPR_F fields align(month_tag, fields f) noexcept { - return fields{f.y, f.m, 1, 0, 0, 0}; -} -CONSTEXPR_F fields align(year_tag, fields f) noexcept { - return fields{f.y, 1, 1, 0, 0, 0}; -} - -//////////////////////////////////////////////////////////////////////// - -namespace impl { - -// Map a (normalized) Y/M/D to the number of days before/after 1970-01-01. -// Will overflow outside of the range [-5877641-06-23 ... 5881580-07-11]. -CONSTEXPR_F int ymd_ord(int y, int m, int d) noexcept { - const int eyear = (m <= 2) ? y - 1 : y; - const int era = (eyear >= 0 ? eyear : eyear - 399) / 400; - const int yoe = eyear - era * 400; - const int doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; - const int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; - return era * 146097 + doe - 719468; -} - -} // namespace impl - -// Returns the difference between fields structs using the indicated unit. -CONSTEXPR_F int difference(year_tag, fields f1, fields f2) noexcept { - return f1.y - f2.y; -} -CONSTEXPR_F int difference(month_tag, fields f1, fields f2) noexcept { - return difference(year_tag{}, f1, f2) * 12 + (f1.m - f2.m); -} -CONSTEXPR_F int difference(day_tag, fields f1, fields f2) noexcept { - return impl::ymd_ord(f1.y, f1.m, f1.d) - impl::ymd_ord(f2.y, f2.m, f2.d); -} -CONSTEXPR_F int difference(hour_tag, fields f1, fields f2) noexcept { - return difference(day_tag{}, f1, f2) * 24 + (f1.hh - f2.hh); -} -CONSTEXPR_F int difference(minute_tag, fields f1, fields f2) noexcept { - return difference(hour_tag{}, f1, f2) * 60 + (f1.mm - f2.mm); -} -CONSTEXPR_F int difference(second_tag, fields f1, fields f2) noexcept { - return difference(minute_tag{}, f1, f2) * 60 + (f1.ss - f2.ss); -} - -//////////////////////////////////////////////////////////////////////// - -template -class civil_time { - public: - explicit CONSTEXPR_M civil_time(int y, int m = 1, int d = 1, int hh = 0, - int mm = 0, int ss = 0) noexcept - : civil_time(impl::n_sec(y, m, d, hh, mm, ss)) {} - - CONSTEXPR_M civil_time() noexcept : civil_time(1970) {} - civil_time(const civil_time&) = default; - civil_time& operator=(const civil_time&) = default; - - // Conversion between civil times of different alignment. Conversion to - // a more precise alignment is allowed implicitly (e.g., day -> hour), - // but conversion where information is discarded must be explicit - // (e.g., second -> minute). - template - using preserves_data = - typename std::enable_if::value>::type; - template - CONSTEXPR_M civil_time(const civil_time& ct, - preserves_data* = nullptr) noexcept - : civil_time(ct.f_) {} - template - explicit CONSTEXPR_M civil_time(const civil_time& ct, - preserves_data* = nullptr) noexcept - : civil_time(ct.f_) {} - - // Factories for the maximum/minimum representable civil_time. - static civil_time max() { - return civil_time(std::numeric_limits::max(), 12, 31, 23, 59, 59); - } - static civil_time min() { - return civil_time(std::numeric_limits::min(), 1, 1, 0, 0, 0); - } - - // Field accessors. - CONSTEXPR_M int year() const noexcept { return f_.y; } - CONSTEXPR_M int month() const noexcept { return f_.m; } - CONSTEXPR_M int day() const noexcept { return f_.d; } - CONSTEXPR_M int hour() const noexcept { return f_.hh; } - CONSTEXPR_M int minute() const noexcept { return f_.mm; } - CONSTEXPR_M int second() const noexcept { return f_.ss; } - - // Assigning arithmetic. - CONSTEXPR_M civil_time& operator+=(int n) noexcept { - f_ = step(T{}, f_, n); - return *this; - } - CONSTEXPR_M civil_time& operator-=(int n) noexcept { - if (n != std::numeric_limits::min()) { - f_ = step(T{}, f_, -n); - } else { - f_ = step(T(), step(T{}, f_, -(n + 1)), 1); - } - return *this; - } - CONSTEXPR_M civil_time& operator++() noexcept { - return *this += 1; - } - CONSTEXPR_M civil_time operator++(int) noexcept { - const civil_time a = *this; - ++*this; - return a; - } - CONSTEXPR_M civil_time& operator--() noexcept { - return *this -= 1; - } - CONSTEXPR_M civil_time operator--(int) noexcept { - const civil_time a = *this; - --*this; - return a; - } - - // Binary arithmetic operators. - inline friend CONSTEXPR_M civil_time operator+(const civil_time& a, - int n) noexcept { - return civil_time(step(T{}, a.f_, n)); - } - inline friend CONSTEXPR_M civil_time operator+(int n, - const civil_time& a) noexcept { - return civil_time(step(T{}, a.f_, n)); - } - inline friend CONSTEXPR_M civil_time operator-(const civil_time& a, - int n) noexcept { - return civil_time(step(T{}, a.f_, -n)); - } - inline friend CONSTEXPR_M int operator-(const civil_time& lhs, - const civil_time& rhs) noexcept { - return difference(T{}, lhs.f_, rhs.f_); - } - - private: - // All instantiations of this template are allowed to call the following - // private constructor and access the private fields member. - template - friend class civil_time; - - // The designated constructor that all others eventually call. - explicit CONSTEXPR_M civil_time(fields f) noexcept : f_(align(T{}, f)) {} - - fields f_; -}; - -using civil_year = civil_time; -using civil_month = civil_time; -using civil_day = civil_time; -using civil_hour = civil_time; -using civil_minute = civil_time; -using civil_second = civil_time; - -//////////////////////////////////////////////////////////////////////// - -// Relational operators that work with differently aligned objects. -// Always compares all six fields. -template -CONSTEXPR_T bool operator<(const civil_time& lhs, - const civil_time& rhs) noexcept { - return (lhs.year() < rhs.year() || - (lhs.year() == rhs.year() && - (lhs.month() < rhs.month() || - (lhs.month() == rhs.month() && - (lhs.day() < rhs.day() || - (lhs.day() == rhs.day() && - (lhs.hour() < rhs.hour() || - (lhs.hour() == rhs.hour() && - (lhs.minute() < rhs.minute() || - (lhs.minute() == rhs.minute() && - (lhs.second() < rhs.second()))))))))))); -} -template -CONSTEXPR_T bool operator<=(const civil_time& lhs, - const civil_time& rhs) noexcept { - return !(rhs < lhs); -} -template -CONSTEXPR_T bool operator>=(const civil_time& lhs, - const civil_time& rhs) noexcept { - return !(lhs < rhs); -} -template -CONSTEXPR_T bool operator>(const civil_time& lhs, - const civil_time& rhs) noexcept { - return rhs < lhs; -} -template -CONSTEXPR_T bool operator==(const civil_time& lhs, - const civil_time& rhs) noexcept { - return lhs.year() == rhs.year() && lhs.month() == rhs.month() && - lhs.day() == rhs.day() && lhs.hour() == rhs.hour() && - lhs.minute() == rhs.minute() && lhs.second() == rhs.second(); -} -template -CONSTEXPR_T bool operator!=(const civil_time& lhs, - const civil_time& rhs) noexcept { - return !(lhs == rhs); -} - -//////////////////////////////////////////////////////////////////////// - -// Output stream operators output a format matching YYYY-MM-DDThh:mm:ss, -// while omitting fields inferior to the type's alignment. For example, -// civil_day is formatted only as YYYY-MM-DD. -inline std::ostream& operator<<(std::ostream& os, const civil_year& y) { - std::stringstream ss; - ss << y.year(); // No padding. - return os << ss.str(); -} -inline std::ostream& operator<<(std::ostream& os, const civil_month& m) { - std::stringstream ss; - ss << civil_year(m) << '-'; - ss << std::setfill('0') << std::setw(2) << m.month(); - return os << ss.str(); -} -inline std::ostream& operator<<(std::ostream& os, const civil_day& d) { - std::stringstream ss; - ss << civil_month(d) << '-'; - ss << std::setfill('0') << std::setw(2) << d.day(); - return os << ss.str(); -} -inline std::ostream& operator<<(std::ostream& os, const civil_hour& h) { - std::stringstream ss; - ss << civil_day(h) << 'T'; - ss << std::setfill('0') << std::setw(2) << h.hour(); - return os << ss.str(); -} -inline std::ostream& operator<<(std::ostream& os, const civil_minute& m) { - std::stringstream ss; - ss << civil_hour(m) << ':'; - ss << std::setfill('0') << std::setw(2) << m.minute(); - return os << ss.str(); -} -inline std::ostream& operator<<(std::ostream& os, const civil_second& s) { - std::stringstream ss; - ss << civil_minute(s) << ':'; - ss << std::setfill('0') << std::setw(2) << s.second(); - return os << ss.str(); -} - -//////////////////////////////////////////////////////////////////////// - -enum class weekday { - monday, - tuesday, - wednesday, - thursday, - friday, - saturday, - sunday, -}; - -inline std::ostream& operator<<(std::ostream& os, weekday wd) { - switch (wd) { - case weekday::monday: - return os << "Monday"; - case weekday::tuesday: - return os << "Tuesday"; - case weekday::wednesday: - return os << "Wednesday"; - case weekday::thursday: - return os << "Thursday"; - case weekday::friday: - return os << "Friday"; - case weekday::saturday: - return os << "Saturday"; - case weekday::sunday: - return os << "Sunday"; - } -} - -CONSTEXPR_F weekday get_weekday(const civil_day& cd) noexcept { - CONSTEXPR_D weekday k_weekday_by_thu_off[] = { - weekday::thursday, weekday::friday, weekday::saturday, - weekday::sunday, weekday::monday, weekday::tuesday, - weekday::wednesday, - }; - return k_weekday_by_thu_off[((cd - civil_day()) % 7 + 7) % 7]; -} - -//////////////////////////////////////////////////////////////////////// - -CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept { - do { cd += 1; } while (get_weekday(cd) != wd); - return cd; -} - -CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept { - do { cd -= 1; } while (get_weekday(cd) != wd); - return cd; -} - -CONSTEXPR_F int get_yearday(const civil_day& cd) noexcept { - return cd - civil_day(civil_year(cd)) + 1; -} - -} // namespace detail -} // namespace cctz - -#undef CONSTEXPR_T -#undef CONSTEXPR_M -#undef CONSTEXPR_F -#undef CONSTEXPR_D diff --git a/include/time_zone.h b/include/time_zone.h deleted file mode 100644 index 3bd3a0126..000000000 --- a/include/time_zone.h +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// A library for translating between absolute times (represented by -// std::chrono::time_points of the std::chrono::system_clock) and civil -// times (represented by cctz::civil_second) using the rules defined by -// a time zone (cctz::time_zone). - -#ifndef CCTZ_TIME_ZONE_H_ -#define CCTZ_TIME_ZONE_H_ - -#include -#include - -#include "civil_time.h" - -namespace cctz { - -// Convenience aliases. Not intended as public API points. -template -using time_point = std::chrono::time_point; -using sys_seconds = std::chrono::duration; - -// cctz::time_zone is an opaque, small, value-type class representing a -// geo-political region within which particular rules are used for mapping -// between absolute and civil times. Time zones are named using the TZ -// identifiers from the IANA Time Zone Database, such as "America/Los_Angeles" -// or "Australia/Sydney". Time zones are created from factory functions such -// as load_time_zone(). Note: strings like "PST" and "EDT" are not valid TZ -// identifiers. -// -// Example: -// cctz::time_zone utc = cctz::utc_time_zone(); -// cctz::time_zone loc = cctz::local_time_zone(); -// cctz::time_zone lax; -// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } -// -// See also: -// - http://www.iana.org/time-zones -// - http://en.wikipedia.org/wiki/Zoneinfo -class time_zone { - public: - time_zone() = default; // Equivalent to UTC - time_zone(const time_zone&) = default; - time_zone& operator=(const time_zone&) = default; - - // An absolute_lookup represents the civil time (cctz::civil_second) within - // this time_zone at the given absolute time (time_point). There are - // additionally a few other fields that may be useful when working with - // older APIs, such as std::tm. - // - // Example: - // const cctz::time_zone tz = ... - // const auto tp = std::chrono::system_clock::now(); - // const cctz::time_zone::absolute_lookup al = tz.lookup(tp); - struct absolute_lookup { - civil_second cs; - // Note: The following fields exist for backward compatibility with older - // APIs. Accessing these fields directly is a sign of imprudent logic in - // the calling code. Modern time-related code should only access this data - // indirectly by way of cctz::format(). - int offset; // civil seconds east of UTC - bool is_dst; // is offset non-standard? - std::string abbr; // time-zone abbreviation (e.g., "PST") - }; - absolute_lookup lookup(const time_point& tp) const; - template - absolute_lookup lookup(const time_point& tp) const { - return lookup(std::chrono::time_point_cast(tp)); - } - - // A civil_lookup represents the absolute time(s) (time_point) that - // correspond to the given civil time (cctz::civil_second) within this - // time_zone. Usually the given civil time represents a unique instant in - // time, in which case the conversion is unambiguous and correct. However, - // within this time zone, the given civil time may be skipped (e.g., during - // a positive UTC offset shift), or repeated (e.g., during a negative UTC - // offset shift). To account for these possibilities, civil_lookup is richer - // than just a single output time_point. - // - // In all cases the civil_lookup::kind enum will indicate the nature of the - // given civil-time argument, and the pre, trans, and post, members will - // give the absolute time answers using the pre-transition offset, the - // transition point itself, and the post-transition offset, respectively - // (these are all equal if kind == UNIQUE). - // - // Example: - // cctz::time_zone lax; - // if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } - // - // // A unique civil time. - // auto jan01 = lax.lookup(cctz::civil_second(2011, 1, 1, 0, 0, 0)); - // // jan01.kind == cctz::time_zone::civil_lookup::UNIQUE - // // jan01.pre is 2011/01/01 00:00:00 -0800 - // // jan01.trans is 2011/01/01 00:00:00 -0800 - // // jan01.post is 2011/01/01 00:00:00 -0800 - // - // // A Spring DST transition, when there is a gap in civil time. - // auto mar13 = lax.lookup(cctz::civil_second(2011, 3, 13, 2, 15, 0)); - // // mar13.kind == cctz::time_zone::civil_lookup::SKIPPED - // // mar13.pre is 2011/03/13 03:15:00 -0700 - // // mar13.trans is 2011/03/13 03:00:00 -0700 - // // mar13.post is 2011/03/13 01:15:00 -0800 - // - // // A Fall DST transition, when civil times are repeated. - // auto nov06 = lax.lookup(cctz::civil_second(2011, 11, 6, 1, 15, 0)); - // // nov06.kind == cctz::time_zone::civil_lookup::REPEATED - // // nov06.pre is 2011/11/06 01:15:00 -0700 - // // nov06.trans is 2011/11/06 01:00:00 -0800 - // // nov06.post is 2011/11/06 01:15:00 -0800 - struct civil_lookup { - enum civil_kind { - UNIQUE, // the civil time was singular (pre == trans == post) - SKIPPED, // the civil time did not exist - REPEATED, // the civil time was ambiguous - } kind; - time_point pre; // Uses the pre-transition offset - time_point trans; // Instant of civil-offset change - time_point post; // Uses the post-transition offset - }; - civil_lookup lookup(const civil_second& cs) const; - - class Impl; - - private: - explicit time_zone(const Impl* impl) : impl_(impl) {} - const Impl* impl_ = nullptr; -}; - -// Loads the named time zone. May perform I/O on the initial load. -// If the name is invalid, or some other kind of error occurs, returns -// false and "*tz" is set to the UTC time zone. -bool load_time_zone(const std::string& name, time_zone* tz); - -// Returns a time_zone representing UTC. Cannot fail. -time_zone utc_time_zone(); - -// Returns a time zone representing the local time zone. Falls back to UTC. -time_zone local_time_zone(); - -// Returns the civil time (cctz::civil_second) within the given time zone at -// the given absolute time (time_point). Since the additional fields provided -// by the time_zone::absolute_lookup struct should rarely be needed in modern -// code, this convert() function is simpler and should be preferred. -template -inline civil_second convert(const time_point& tp, const time_zone& tz) { - return tz.lookup(tp).cs; -} - -// Returns the absolute time (time_point) that corresponds to the given civil -// time within the given time zone. If the civil time is not unique (i.e., if -// it was either repeated or non-existent), then the returned time_point is -// the best estimate that preserves relative order. That is, this function -// guarantees that if cs1 < cs2, then convert(cs1, tz) <= convert(cs2, tz). -inline time_point convert(const civil_second& cs, - const time_zone& tz) { - const time_zone::civil_lookup cl = tz.lookup(cs); - if (cl.kind == time_zone::civil_lookup::SKIPPED) return cl.trans; - return cl.pre; -} - -namespace detail { -template -inline std::pair, D> -split_seconds(const time_point& tp) { - auto sec = std::chrono::time_point_cast(tp); - auto sub = tp - sec; - if (sub.count() < 0) { - sec -= sys_seconds(1); - sub += sys_seconds(1); - } - return {sec, std::chrono::duration_cast(sub)}; -} -inline std::pair, sys_seconds> -split_seconds(const time_point& tp) { - return {tp, sys_seconds(0)}; -} -std::string format(const std::string&, const time_point&, - const std::chrono::nanoseconds&, const time_zone&); -bool parse(const std::string&, const std::string&, const time_zone&, - time_point*, std::chrono::nanoseconds*); -} // namespace detail - -// Formats the given time_point in the given cctz::time_zone according to -// the provided format string. Uses strftime()-like formatting options, -// with the following extensions: -// -// - %Ez - RFC3339-compatible numeric time zone (+hh:mm or -hh:mm) -// - %E#S - Seconds with # digits of fractional precision -// - %E*S - Seconds with full fractional precision (a literal '*') -// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) -// -// Note that %Y produces as many characters as it takes to fully render the -// year. A year outside of [-999:9999] when formatted with %E4Y will produce -// more than four characters, just like %Y. -// -// Tip: Format strings should include the UTC offset (e.g., %z or %Ez) so that -// the resultng string uniquely identifies an absolute time. -// -// Example: -// cctz::time_zone lax; -// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } -// auto tp = cctz::convert(cctz::civil_second(2013, 1, 2, 3, 4, 5), lax); -// std::string f = cctz::format("%H:%M:%S", tp, lax); // "03:04:05" -// f = cctz::format("%H:%M:%E3S", tp, lax); // "03:04:05.000" -template -inline std::string format(const std::string& fmt, const time_point& tp, - const time_zone& tz) { - const auto p = detail::split_seconds(tp); - const auto n = std::chrono::duration_cast(p.second); - return detail::format(fmt, p.first, n, tz); -} - -// Parses an input string according to the provided format string and -// returns the corresponding time_point. Uses strftime()-like formatting -// options, with the same extensions as cctz::format(). -// -// %Y consumes as many numeric characters as it can, so the matching data -// should always be terminated with a non-numeric. %E4Y always consumes -// exactly four characters, including any sign. -// -// Unspecified fields are taken from the default date and time of ... -// -// "1970-01-01 00:00:00.0 +0000" -// -// For example, parsing a string of "15:45" (%H:%M) will return a time_point -// that represents "1970-01-01 15:45:00.0 +0000". -// -// Note that parse() returns time instants, so it makes most sense to parse -// fully-specified date/time strings that include a UTC offset (%z or %Ez). -// -// Note also that parse() only heeds the fields year, month, day, hour, -// minute, (fractional) second, and UTC offset. Other fields, like weekday (%a -// or %A), while parsed for syntactic validity, are ignored in the conversion. -// -// Date and time fields that are out-of-range will be treated as errors rather -// than normalizing them like cctz::civil_second() would do. For example, it -// is an error to parse the date "Oct 32, 2013" because 32 is out of range. -// -// A second of ":60" is normalized to ":00" of the following minute with -// fractional seconds discarded. The following table shows how the given -// seconds and subseconds will be parsed: -// -// "59.x" -> 59.x // exact -// "60.x" -> 00.0 // normalized -// "00.x" -> 00.x // exact -// -// Errors are indicated by returning false. -// -// Example: -// const cctz::time_zone tz = ... -// std::chrono::system_clock::time_point tp; -// if (cctz::parse("%Y-%m-%d", "2015-10-09", tz, &tp)) { -// ... -// } -template -inline bool parse(const std::string& fmt, const std::string& input, - const time_zone& tz, time_point* tpp) { - time_point tp{}; - std::chrono::nanoseconds ns{0}; - const bool b = detail::parse(fmt, input, tz, &tp, &ns); - if (b) { - *tpp = std::chrono::time_point_cast(tp); - *tpp += std::chrono::duration_cast(ns); - } - return b; -} - -} // namespace cctz - -#endif // CCTZ_TIME_ZONE_H_ diff --git a/src/cctz.h b/src/cctz.h deleted file mode 100644 index 650a1fe75..000000000 --- a/src/cctz.h +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CCTZ_H_ -#define CCTZ_H_ - -#include -#include -#include - -#include "civil_time.h" -#include "time_zone.h" - -namespace cctz { -inline namespace deprecated_v1_api { -// DEPRECATED: Will be deleted on 2016-10-01. -// -// This header defines the CCTZ v1 API, as it was when originally announced in -// September 2015. The v2 API is declared in two headers: include/civil_time.h -// and include/time_zone.h. For help migrating to the v2 API, see -// https://github.com/google/cctz/wiki/Migrating-from-V1-to-V2-interface -#if CCTZ_ACK_V1_DEPRECATION != 1 -#pragma message \ - "This CCTZ v1 API is depreated and will be deleted 2016-10-01. See " \ - "https://github.com/google/cctz/wiki/Migrating-from-V1-to-V2-interface " \ - "for details about migrating to the v2 API. " \ - "To disable this warning, define CCTZ_ACK_V1_DEPRECATION=1" -#endif - -using TimeZone = ::cctz::time_zone; -inline TimeZone UTCTimeZone() { return utc_time_zone(); } -inline TimeZone LocalTimeZone() { return local_time_zone(); } -inline bool LoadTimeZone(const std::string& s, TimeZone* tz) { - return load_time_zone(s, tz); -} - -struct Breakdown { - int64_t year; - int month; - int day; - int hour; - int minute; - int second; - int weekday; - int yearday; - int offset; - bool is_dst; - std::string abbr; -}; -template -inline Breakdown BreakTime(const time_point& tp, const TimeZone& tz) { - // Assert that the time point does not require a civil year beyond - // the limits of a signed 32-bit value, as dictated by the v2 API. - // -67768100567884800 == -2147483648-01-02 00:00:00 +00:00 - // 67767976233446399 == 2147483647-12-30 23:59:59 +00:00 - assert(std::chrono::time_point_cast(tp) >= - std::chrono::time_point_cast( - std::chrono::system_clock::from_time_t(0)) + - sys_seconds(-67768100567884800)); - assert(std::chrono::time_point_cast(tp) <= - std::chrono::time_point_cast( - std::chrono::system_clock::from_time_t(0)) + - sys_seconds(67767976233446399)); - - const auto al = tz.lookup(tp); - const auto cs = al.cs; - const auto yd = get_yearday(civil_day(cs)); - int wd{}; - switch (get_weekday(civil_day(cs))) { - case weekday::monday: - wd = 1; - break; - case weekday::tuesday: - wd = 2; - break; - case weekday::wednesday: - wd = 3; - break; - case weekday::thursday: - wd = 4; - break; - case weekday::friday: - wd = 5; - break; - case weekday::saturday: - wd = 6; - break; - case weekday::sunday: - wd = 7; - break; - } - return {cs.year(), cs.month(), cs.day(), cs.hour(), cs.minute(), cs.second(), - wd, yd, al.offset, al.is_dst, al.abbr}; -} - -using seconds64 = std::chrono::duration; -inline time_point MakeTime(int64_t year, int mon, int day, int hour, - int min, int sec, const TimeZone& tz) { - assert(year < std::numeric_limits::max()); - return tz.lookup(civil_second(year, mon, day, hour, min, sec)).pre; -} - -struct TimeInfo { - enum class Kind { - UNIQUE, - SKIPPED, - REPEATED, - } kind; - time_point pre; - time_point trans; - time_point post; - bool normalized; -}; -inline TimeInfo MakeTimeInfo(int64_t y, int m, int d, int hh, int mm, int ss, - const TimeZone& tz) { - assert(y < std::numeric_limits::max()); - const civil_second cs(y, m, d, hh, mm, ss); - const bool norm = cs.year() != y || cs.month() != m || cs.day() != d || - cs.hour() != hh || cs.minute() != mm || cs.second() != ss; - const auto cl = tz.lookup(cs); - TimeInfo::Kind kind; - switch (cl.kind) { - case time_zone::civil_lookup::civil_kind::UNIQUE: - kind = TimeInfo::Kind::UNIQUE; - break; - case time_zone::civil_lookup::civil_kind::SKIPPED: - kind = TimeInfo::Kind::SKIPPED; - break; - case time_zone::civil_lookup::civil_kind::REPEATED: - kind = TimeInfo::Kind::REPEATED; - break; - } - return {kind, cl.pre, cl.trans, cl.post, norm}; -} - -template -inline std::string Format(const std::string& fmt, const time_point& tp, - const TimeZone& tz) { - return format(fmt, tp, tz); -} - -template -inline bool Parse(const std::string& fmt, const std::string& input, - const TimeZone& tz, time_point* tpp) { - return parse(fmt, input, tz, tpp); -} - -} // namespace deprecated_v1_api -} // namespace cctz - -#endif // CCTZ_H_ diff --git a/src/cctz_benchmark.cc b/src/cctz_benchmark.cc new file mode 100644 index 000000000..a70101ec0 --- /dev/null +++ b/src/cctz_benchmark.cc @@ -0,0 +1,434 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" +#include "test_time_zone_names.h" +#include "time_zone_impl.h" + +namespace { + +void BM_Difference_Days(benchmark::State& state) { + const cctz::civil_day c(2014, 8, 22); + const cctz::civil_day epoch(1970, 1, 1); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(c - epoch); + } +} +BENCHMARK(BM_Difference_Days); + +void BM_Step_Days(benchmark::State& state) { + const cctz::civil_day kStart(2014, 8, 22); + cctz::civil_day c = kStart; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(++c); + } +} +BENCHMARK(BM_Step_Days); + +void BM_GetWeekday(benchmark::State& state) { + const cctz::civil_day c(2014, 8, 22); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(cctz::get_weekday(c)); + } +} +BENCHMARK(BM_GetWeekday); + +void BM_NextWeekday(benchmark::State& state) { + const cctz::civil_day kStart(2014, 8, 22); + const cctz::civil_day kDays[7] = { + kStart + 0, kStart + 1, kStart + 2, kStart + 3, + kStart + 4, kStart + 5, kStart + 6, + }; + const cctz::weekday kWeekdays[7] = { + cctz::weekday::monday, cctz::weekday::tuesday, cctz::weekday::wednesday, + cctz::weekday::thursday, cctz::weekday::friday, cctz::weekday::saturday, + cctz::weekday::sunday, + }; + while (state.KeepRunningBatch(7 * 7)) { + for (const auto from : kDays) { + for (const auto to : kWeekdays) { + benchmark::DoNotOptimize(cctz::next_weekday(from, to)); + } + } + } +} +BENCHMARK(BM_NextWeekday); + +void BM_PrevWeekday(benchmark::State& state) { + const cctz::civil_day kStart(2014, 8, 22); + const cctz::civil_day kDays[7] = { + kStart + 0, kStart + 1, kStart + 2, kStart + 3, + kStart + 4, kStart + 5, kStart + 6, + }; + const cctz::weekday kWeekdays[7] = { + cctz::weekday::monday, cctz::weekday::tuesday, cctz::weekday::wednesday, + cctz::weekday::thursday, cctz::weekday::friday, cctz::weekday::saturday, + cctz::weekday::sunday, + }; + while (state.KeepRunningBatch(7 * 7)) { + for (const auto from : kDays) { + for (const auto to : kWeekdays) { + benchmark::DoNotOptimize(cctz::prev_weekday(from, to)); + } + } + } +} +BENCHMARK(BM_PrevWeekday); + +const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez"; +const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez"; + +const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z"; +const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z"; + +std::vector AllTimeZoneNames() { + std::vector names; + for (const char* const* namep = cctz::kTimeZoneNames; *namep != nullptr; + ++namep) { + names.push_back(std::string("file:") + *namep); + } + assert(!names.empty()); + + std::mt19937 urbg(42); // a UniformRandomBitGenerator with fixed seed + std::shuffle(names.begin(), names.end(), urbg); + return names; +} + +cctz::time_zone TestTimeZone() { + cctz::time_zone tz; + cctz::load_time_zone("America/Los_Angeles", &tz); + return tz; +} + +void BM_Zone_LoadUTCTimeZoneFirst(benchmark::State& state) { + cctz::time_zone tz; + cctz::load_time_zone("UTC", &tz); // in case we're first + cctz::time_zone::Impl::ClearTimeZoneMapTestOnly(); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(cctz::load_time_zone("UTC", &tz)); + } +} +BENCHMARK(BM_Zone_LoadUTCTimeZoneFirst); + +void BM_Zone_LoadUTCTimeZoneLast(benchmark::State& state) { + cctz::time_zone tz; + for (const auto& name : AllTimeZoneNames()) { + cctz::load_time_zone(name, &tz); // prime cache + } + while (state.KeepRunning()) { + benchmark::DoNotOptimize(cctz::load_time_zone("UTC", &tz)); + } +} +BENCHMARK(BM_Zone_LoadUTCTimeZoneLast); + +void BM_Zone_LoadTimeZoneFirst(benchmark::State& state) { + cctz::time_zone tz = cctz::utc_time_zone(); // in case we're first + const std::string name = "file:America/Los_Angeles"; + while (state.KeepRunning()) { + state.PauseTiming(); + cctz::time_zone::Impl::ClearTimeZoneMapTestOnly(); + state.ResumeTiming(); + benchmark::DoNotOptimize(cctz::load_time_zone(name, &tz)); + } +} +BENCHMARK(BM_Zone_LoadTimeZoneFirst); + +void BM_Zone_LoadTimeZoneCached(benchmark::State& state) { + cctz::time_zone tz = cctz::utc_time_zone(); // in case we're first + cctz::time_zone::Impl::ClearTimeZoneMapTestOnly(); + const std::string name = "file:America/Los_Angeles"; + cctz::load_time_zone(name, &tz); // prime cache + while (state.KeepRunning()) { + benchmark::DoNotOptimize(cctz::load_time_zone(name, &tz)); + } +} +BENCHMARK(BM_Zone_LoadTimeZoneCached); + +void BM_Zone_LoadLocalTimeZoneCached(benchmark::State& state) { + cctz::utc_time_zone(); // in case we're first + cctz::time_zone::Impl::ClearTimeZoneMapTestOnly(); + cctz::local_time_zone(); // prime cache + while (state.KeepRunning()) { + benchmark::DoNotOptimize(cctz::local_time_zone()); + } +} +BENCHMARK(BM_Zone_LoadLocalTimeZoneCached); + +void BM_Zone_LoadAllTimeZonesFirst(benchmark::State& state) { + cctz::time_zone tz; + const std::vector names = AllTimeZoneNames(); + for (auto index = names.size(); state.KeepRunning(); ++index) { + if (index == names.size()) { + index = 0; + } + if (index == 0) { + state.PauseTiming(); + cctz::time_zone::Impl::ClearTimeZoneMapTestOnly(); + state.ResumeTiming(); + } + benchmark::DoNotOptimize(cctz::load_time_zone(names[index], &tz)); + } +} +BENCHMARK(BM_Zone_LoadAllTimeZonesFirst); + +void BM_Zone_LoadAllTimeZonesCached(benchmark::State& state) { + cctz::time_zone tz; + const std::vector names = AllTimeZoneNames(); + for (const auto& name : names) { + cctz::load_time_zone(name, &tz); // prime cache + } + for (auto index = names.size(); state.KeepRunning(); ++index) { + if (index == names.size()) { + index = 0; + } + benchmark::DoNotOptimize(cctz::load_time_zone(names[index], &tz)); + } +} +BENCHMARK(BM_Zone_LoadAllTimeZonesCached); + +void BM_Zone_TimeZoneEqualityImplicit(benchmark::State& state) { + cctz::time_zone tz; // implicit UTC + while (state.KeepRunning()) { + benchmark::DoNotOptimize(tz == tz); + } +} +BENCHMARK(BM_Zone_TimeZoneEqualityImplicit); + +void BM_Zone_TimeZoneEqualityExplicit(benchmark::State& state) { + cctz::time_zone tz = cctz::utc_time_zone(); // explicit UTC + while (state.KeepRunning()) { + benchmark::DoNotOptimize(tz == tz); + } +} +BENCHMARK(BM_Zone_TimeZoneEqualityExplicit); + +void BM_Zone_UTCTimeZone(benchmark::State& state) { + cctz::time_zone tz; + while (state.KeepRunning()) { + benchmark::DoNotOptimize(cctz::utc_time_zone()); + } +} +BENCHMARK(BM_Zone_UTCTimeZone); + +// In each "ToCivil" benchmark we switch between two instants separated +// by at least one transition in order to defeat any internal caching of +// previous results (e.g., see local_time_hint_). +// +// The "UTC" variants use UTC instead of the Google/local time zone. + +void BM_Time_ToCivil_CCTZ(benchmark::State& state) { + const cctz::time_zone tz = TestTimeZone(); + std::chrono::system_clock::time_point tp = + std::chrono::system_clock::from_time_t(1384569027); + std::chrono::system_clock::time_point tp2 = + std::chrono::system_clock::from_time_t(1418962578); + while (state.KeepRunning()) { + std::swap(tp, tp2); + tp += std::chrono::seconds(1); + benchmark::DoNotOptimize(cctz::convert(tp, tz)); + } +} +BENCHMARK(BM_Time_ToCivil_CCTZ); + +void BM_Time_ToCivil_Libc(benchmark::State& state) { + // No timezone support, so just use localtime. + time_t t = 1384569027; + time_t t2 = 1418962578; + struct tm tm; + while (state.KeepRunning()) { + std::swap(t, t2); + t += 1; +#if defined(_WIN32) || defined(_WIN64) + benchmark::DoNotOptimize(localtime_s(&tm, &t)); +#else + benchmark::DoNotOptimize(localtime_r(&t, &tm)); +#endif + } +} +BENCHMARK(BM_Time_ToCivil_Libc); + +void BM_Time_ToCivilUTC_CCTZ(benchmark::State& state) { + const cctz::time_zone tz = cctz::utc_time_zone(); + std::chrono::system_clock::time_point tp = + std::chrono::system_clock::from_time_t(1384569027); + while (state.KeepRunning()) { + tp += std::chrono::seconds(1); + benchmark::DoNotOptimize(cctz::convert(tp, tz)); + } +} +BENCHMARK(BM_Time_ToCivilUTC_CCTZ); + +void BM_Time_ToCivilUTC_Libc(benchmark::State& state) { + time_t t = 1384569027; + struct tm tm; + while (state.KeepRunning()) { + t += 1; +#if defined(_WIN32) || defined(_WIN64) + benchmark::DoNotOptimize(gmtime_s(&tm, &t)); +#else + benchmark::DoNotOptimize(gmtime_r(&t, &tm)); +#endif + } +} +BENCHMARK(BM_Time_ToCivilUTC_Libc); + +// In each "FromCivil" benchmark we switch between two YMDhms values +// separated by at least one transition in order to defeat any internal +// caching of previous results (e.g., see time_local_hint_). +// +// The "UTC" variants use UTC instead of the Google/local time zone. +// The "Day0" variants require normalization of the day of month. + +void BM_Time_FromCivil_CCTZ(benchmark::State& state) { + const cctz::time_zone tz = TestTimeZone(); + int i = 0; + while (state.KeepRunning()) { + if ((i++ & 1) == 0) { + benchmark::DoNotOptimize( + cctz::convert(cctz::civil_second(2014, 12, 18, 20, 16, 18), tz)); + } else { + benchmark::DoNotOptimize( + cctz::convert(cctz::civil_second(2013, 11, 15, 18, 30, 27), tz)); + } + } +} +BENCHMARK(BM_Time_FromCivil_CCTZ); + +void BM_Time_FromCivil_Libc(benchmark::State& state) { + // No timezone support, so just use localtime. + int i = 0; + while (state.KeepRunning()) { + struct tm tm; + if ((i++ & 1) == 0) { + tm.tm_year = 2014 - 1900; + tm.tm_mon = 12 - 1; + tm.tm_mday = 18; + tm.tm_hour = 20; + tm.tm_min = 16; + tm.tm_sec = 18; + } else { + tm.tm_year = 2013 - 1900; + tm.tm_mon = 11 - 1; + tm.tm_mday = 15; + tm.tm_hour = 18; + tm.tm_min = 30; + tm.tm_sec = 27; + } + tm.tm_isdst = -1; + benchmark::DoNotOptimize(mktime(&tm)); + } +} +BENCHMARK(BM_Time_FromCivil_Libc); + +void BM_Time_FromCivilUTC_CCTZ(benchmark::State& state) { + const cctz::time_zone tz = cctz::utc_time_zone(); + while (state.KeepRunning()) { + benchmark::DoNotOptimize( + cctz::convert(cctz::civil_second(2014, 12, 18, 20, 16, 18), tz)); + } +} +BENCHMARK(BM_Time_FromCivilUTC_CCTZ); + +// There is no BM_Time_FromCivilUTC_Libc. + +void BM_Time_FromCivilDay0_CCTZ(benchmark::State& state) { + const cctz::time_zone tz = TestTimeZone(); + int i = 0; + while (state.KeepRunning()) { + if ((i++ & 1) == 0) { + benchmark::DoNotOptimize( + cctz::convert(cctz::civil_second(2014, 12, 0, 20, 16, 18), tz)); + } else { + benchmark::DoNotOptimize( + cctz::convert(cctz::civil_second(2013, 11, 0, 18, 30, 27), tz)); + } + } +} +BENCHMARK(BM_Time_FromCivilDay0_CCTZ); + +void BM_Time_FromCivilDay0_Libc(benchmark::State& state) { + // No timezone support, so just use localtime. + int i = 0; + while (state.KeepRunning()) { + struct tm tm; + if ((i++ & 1) == 0) { + tm.tm_year = 2014 - 1900; + tm.tm_mon = 12 - 1; + tm.tm_mday = 0; + tm.tm_hour = 20; + tm.tm_min = 16; + tm.tm_sec = 18; + } else { + tm.tm_year = 2013 - 1900; + tm.tm_mon = 11 - 1; + tm.tm_mday = 0; + tm.tm_hour = 18; + tm.tm_min = 30; + tm.tm_sec = 27; + } + tm.tm_isdst = -1; + benchmark::DoNotOptimize(mktime(&tm)); + } +} +BENCHMARK(BM_Time_FromCivilDay0_Libc); + +const char* const kFormats[] = { + RFC1123_full, // 0 + RFC1123_no_wday, // 1 + RFC3339_full, // 2 + RFC3339_sec, // 3 + "%Y-%m-%d%ET%H:%M:%S", // 4 + "%Y-%m-%d", // 5 + "%F%ET%T", // 6 +}; +const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]); + +void BM_Format_FormatTime(benchmark::State& state) { + const std::string fmt = kFormats[state.range(0)]; + state.SetLabel(fmt); + const cctz::time_zone tz = TestTimeZone(); + const std::chrono::system_clock::time_point tp = + cctz::convert(cctz::civil_second(1977, 6, 28, 9, 8, 7), tz) + + std::chrono::microseconds(1); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(cctz::format(fmt, tp, tz)); + } +} +BENCHMARK(BM_Format_FormatTime)->DenseRange(0, kNumFormats - 1); + +void BM_Format_ParseTime(benchmark::State& state) { + const std::string fmt = kFormats[state.range(0)]; + state.SetLabel(fmt); + const cctz::time_zone tz = TestTimeZone(); + std::chrono::system_clock::time_point tp = + cctz::convert(cctz::civil_second(1977, 6, 28, 9, 8, 7), tz) + + std::chrono::microseconds(1); + const std::string when = cctz::format(fmt, tp, tz); + while (state.KeepRunning()) { + benchmark::DoNotOptimize(cctz::parse(fmt, when, tz, &tp)); + } +} +BENCHMARK(BM_Format_ParseTime)->DenseRange(0, kNumFormats - 1); + +} // namespace diff --git a/src/cctz_v1_test.cc b/src/cctz_v1_test.cc deleted file mode 100644 index 0705dbd28..000000000 --- a/src/cctz_v1_test.cc +++ /dev/null @@ -1,1135 +0,0 @@ -// Copyright 2015 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -// implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "src/cctz.h" - -#include -#include -#include -#include -#include -#include - -#include "gtest/gtest.h" - -using std::chrono::system_clock; - -namespace cctz { - -namespace { - -// A list of known time-zone names. -const char* const kTimeZoneNames[] = { - "Africa/Abidjan", - "Africa/Accra", - "Africa/Addis_Ababa", - "Africa/Algiers", - "Africa/Asmara", - "Africa/Asmera", - "Africa/Bamako", - "Africa/Bangui", - "Africa/Banjul", - "Africa/Bissau", - "Africa/Blantyre", - "Africa/Brazzaville", - "Africa/Bujumbura", - "Africa/Cairo", - "Africa/Casablanca", - "Africa/Ceuta", - "Africa/Conakry", - "Africa/Dakar", - "Africa/Dar_es_Salaam", - "Africa/Djibouti", - "Africa/Douala", - "Africa/El_Aaiun", - "Africa/Freetown", - "Africa/Gaborone", - "Africa/Harare", - "Africa/Johannesburg", - "Africa/Juba", - "Africa/Kampala", - "Africa/Khartoum", - "Africa/Kigali", - "Africa/Kinshasa", - "Africa/Lagos", - "Africa/Libreville", - "Africa/Lome", - "Africa/Luanda", - "Africa/Lubumbashi", - "Africa/Lusaka", - "Africa/Malabo", - "Africa/Maputo", - "Africa/Maseru", - "Africa/Mbabane", - "Africa/Mogadishu", - "Africa/Monrovia", - "Africa/Nairobi", - "Africa/Ndjamena", - "Africa/Niamey", - "Africa/Nouakchott", - "Africa/Ouagadougou", - "Africa/Porto-Novo", - "Africa/Sao_Tome", - "Africa/Timbuktu", - "Africa/Tripoli", - "Africa/Tunis", - "Africa/Windhoek", - "America/Adak", - "America/Anchorage", - "America/Anguilla", - "America/Antigua", - "America/Araguaina", - "America/Argentina/Buenos_Aires", - "America/Argentina/Catamarca", - "America/Argentina/ComodRivadavia", - "America/Argentina/Cordoba", - "America/Argentina/Jujuy", - "America/Argentina/La_Rioja", - "America/Argentina/Mendoza", - "America/Argentina/Rio_Gallegos", - "America/Argentina/Salta", - "America/Argentina/San_Juan", - "America/Argentina/San_Luis", - "America/Argentina/Tucuman", - "America/Argentina/Ushuaia", - "America/Aruba", - "America/Asuncion", - "America/Atikokan", - "America/Atka", - "America/Bahia", - "America/Bahia_Banderas", - "America/Barbados", - "America/Belem", - "America/Belize", - "America/Blanc-Sablon", - "America/Boa_Vista", - "America/Bogota", - "America/Boise", - "America/Buenos_Aires", - "America/Cambridge_Bay", - "America/Campo_Grande", - "America/Cancun", - "America/Caracas", - "America/Catamarca", - "America/Cayenne", - "America/Cayman", - "America/Chicago", - "America/Chihuahua", - "America/Coral_Harbour", - "America/Cordoba", - "America/Costa_Rica", - "America/Creston", - "America/Cuiaba", - "America/Curacao", - "America/Danmarkshavn", - "America/Dawson", - "America/Dawson_Creek", - "America/Denver", - "America/Detroit", - "America/Dominica", - "America/Edmonton", - "America/Eirunepe", - "America/El_Salvador", - "America/Ensenada", - "America/Fort_Wayne", - "America/Fortaleza", - "America/Glace_Bay", - "America/Godthab", - "America/Goose_Bay", - "America/Grand_Turk", - "America/Grenada", - "America/Guadeloupe", - "America/Guatemala", - "America/Guayaquil", - "America/Guyana", - "America/Halifax", - "America/Havana", - "America/Hermosillo", - "America/Indiana/Indianapolis", - "America/Indiana/Knox", - "America/Indiana/Marengo", - "America/Indiana/Petersburg", - "America/Indiana/Tell_City", - "America/Indiana/Vevay", - "America/Indiana/Vincennes", - "America/Indiana/Winamac", - "America/Indianapolis", - "America/Inuvik", - "America/Iqaluit", - "America/Jamaica", - "America/Jujuy", - "America/Juneau", - "America/Kentucky/Louisville", - "America/Kentucky/Monticello", - "America/Knox_IN", - "America/Kralendijk", - "America/La_Paz", - "America/Lima", - "America/Los_Angeles", - "America/Louisville", - "America/Lower_Princes", - "America/Maceio", - "America/Managua", - "America/Manaus", - "America/Marigot", - "America/Martinique", - "America/Matamoros", - "America/Mazatlan", - "America/Mendoza", - "America/Menominee", - "America/Merida", - "America/Metlakatla", - "America/Mexico_City", - "America/Miquelon", - "America/Moncton", - "America/Monterrey", - "America/Montevideo", - "America/Montreal", - "America/Montserrat", - "America/Nassau", - "America/New_York", - "America/Nipigon", - "America/Nome", - "America/Noronha", - "America/North_Dakota/Beulah", - "America/North_Dakota/Center", - "America/North_Dakota/New_Salem", - "America/Ojinaga", - "America/Panama", - "America/Pangnirtung", - "America/Paramaribo", - "America/Phoenix", - "America/Port-au-Prince", - "America/Port_of_Spain", - "America/Porto_Acre", - "America/Porto_Velho", - "America/Puerto_Rico", - "America/Rainy_River", - "America/Rankin_Inlet", - "America/Recife", - "America/Regina", - "America/Resolute", - "America/Rio_Branco", - "America/Rosario", - "America/Santa_Isabel", - "America/Santarem", - "America/Santiago", - "America/Santo_Domingo", - "America/Sao_Paulo", - "America/Scoresbysund", - "America/Shiprock", - "America/Sitka", - "America/St_Barthelemy", - "America/St_Johns", - "America/St_Kitts", - "America/St_Lucia", - "America/St_Thomas", - "America/St_Vincent", - "America/Swift_Current", - "America/Tegucigalpa", - "America/Thule", - "America/Thunder_Bay", - "America/Tijuana", - "America/Toronto", - "America/Tortola", - "America/Vancouver", - "America/Virgin", - "America/Whitehorse", - "America/Winnipeg", - "America/Yakutat", - "America/Yellowknife", - "Antarctica/Casey", - "Antarctica/Davis", - "Antarctica/DumontDUrville", - "Antarctica/Macquarie", - "Antarctica/Mawson", - "Antarctica/McMurdo", - "Antarctica/Palmer", - "Antarctica/Rothera", - "Antarctica/South_Pole", - "Antarctica/Syowa", - "Antarctica/Troll", - "Antarctica/Vostok", - "Arctic/Longyearbyen", - "Asia/Aden", - "Asia/Almaty", - "Asia/Amman", - "Asia/Anadyr", - "Asia/Aqtau", - "Asia/Aqtobe", - "Asia/Ashgabat", - "Asia/Ashkhabad", - "Asia/Baghdad", - "Asia/Bahrain", - "Asia/Baku", - "Asia/Bangkok", - "Asia/Beirut", - "Asia/Bishkek", - "Asia/Brunei", - "Asia/Calcutta", - "Asia/Chita", - "Asia/Choibalsan", - "Asia/Chongqing", - "Asia/Chungking", - "Asia/Colombo", - "Asia/Dacca", - "Asia/Damascus", - "Asia/Dhaka", - "Asia/Dili", - "Asia/Dubai", - "Asia/Dushanbe", - "Asia/Gaza", - "Asia/Harbin", - "Asia/Hebron", - "Asia/Ho_Chi_Minh", - "Asia/Hong_Kong", - "Asia/Hovd", - "Asia/Irkutsk", - "Asia/Istanbul", - "Asia/Jakarta", - "Asia/Jayapura", - "Asia/Jerusalem", - "Asia/Kabul", - "Asia/Kamchatka", - "Asia/Karachi", - "Asia/Kashgar", - "Asia/Kathmandu", - "Asia/Katmandu", - "Asia/Khandyga", - "Asia/Kolkata", - "Asia/Krasnoyarsk", - "Asia/Kuala_Lumpur", - "Asia/Kuching", - "Asia/Kuwait", - "Asia/Macao", - "Asia/Macau", - "Asia/Magadan", - "Asia/Makassar", - "Asia/Manila", - "Asia/Muscat", - "Asia/Nicosia", - "Asia/Novokuznetsk", - "Asia/Novosibirsk", - "Asia/Omsk", - "Asia/Oral", - "Asia/Phnom_Penh", - "Asia/Pontianak", - "Asia/Pyongyang", - "Asia/Qatar", - "Asia/Qyzylorda", - "Asia/Rangoon", - "Asia/Riyadh", - "Asia/Saigon", - "Asia/Sakhalin", - "Asia/Samarkand", - "Asia/Seoul", - "Asia/Shanghai", - "Asia/Singapore", - "Asia/Srednekolymsk", - "Asia/Taipei", - "Asia/Tashkent", - "Asia/Tbilisi", - "Asia/Tehran", - "Asia/Tel_Aviv", - "Asia/Thimbu", - "Asia/Thimphu", - "Asia/Tokyo", - "Asia/Ujung_Pandang", - "Asia/Ulaanbaatar", - "Asia/Ulan_Bator", - "Asia/Urumqi", - "Asia/Ust-Nera", - "Asia/Vientiane", - "Asia/Vladivostok", - "Asia/Yakutsk", - "Asia/Yekaterinburg", - "Asia/Yerevan", - "Atlantic/Azores", - "Atlantic/Bermuda", - "Atlantic/Canary", - "Atlantic/Cape_Verde", - "Atlantic/Faeroe", - "Atlantic/Faroe", - "Atlantic/Jan_Mayen", - "Atlantic/Madeira", - "Atlantic/Reykjavik", - "Atlantic/South_Georgia", - "Atlantic/St_Helena", - "Atlantic/Stanley", - "Australia/ACT", - "Australia/Adelaide", - "Australia/Brisbane", - "Australia/Broken_Hill", - "Australia/Canberra", - "Australia/Currie", - "Australia/Darwin", - "Australia/Eucla", - "Australia/Hobart", - "Australia/LHI", - "Australia/Lindeman", - "Australia/Lord_Howe", - "Australia/Melbourne", - "Australia/NSW", - "Australia/North", - "Australia/Perth", - "Australia/Queensland", - "Australia/South", - "Australia/Sydney", - "Australia/Tasmania", - "Australia/Victoria", - "Australia/West", - "Australia/Yancowinna", - "Brazil/Acre", - "Brazil/DeNoronha", - "Brazil/East", - "Brazil/West", - "CET", - "CST6CDT", - "Canada/Atlantic", - "Canada/Central", - "Canada/East-Saskatchewan", - "Canada/Eastern", - "Canada/Mountain", - "Canada/Newfoundland", - "Canada/Pacific", - "Canada/Saskatchewan", - "Canada/Yukon", - "Chile/Continental", - "Chile/EasterIsland", - "Cuba", - "EET", - "EST", - "EST5EDT", - "Egypt", - "Eire", - "Etc/GMT", - "Etc/GMT+0", - "Etc/GMT+1", - "Etc/GMT+10", - "Etc/GMT+11", - "Etc/GMT+12", - "Etc/GMT+2", - "Etc/GMT+3", - "Etc/GMT+4", - "Etc/GMT+5", - "Etc/GMT+6", - "Etc/GMT+7", - "Etc/GMT+8", - "Etc/GMT+9", - "Etc/GMT-0", - "Etc/GMT-1", - "Etc/GMT-10", - "Etc/GMT-11", - "Etc/GMT-12", - "Etc/GMT-13", - "Etc/GMT-14", - "Etc/GMT-2", - "Etc/GMT-3", - "Etc/GMT-4", - "Etc/GMT-5", - "Etc/GMT-6", - "Etc/GMT-7", - "Etc/GMT-8", - "Etc/GMT-9", - "Etc/GMT0", - "Etc/Greenwich", - "Etc/UCT", - "Etc/UTC", - "Etc/Universal", - "Etc/Zulu", - "Europe/Amsterdam", - "Europe/Andorra", - "Europe/Athens", - "Europe/Belfast", - "Europe/Belgrade", - "Europe/Berlin", - "Europe/Bratislava", - "Europe/Brussels", - "Europe/Bucharest", - "Europe/Budapest", - "Europe/Busingen", - "Europe/Chisinau", - "Europe/Copenhagen", - "Europe/Dublin", - "Europe/Gibraltar", - "Europe/Guernsey", - "Europe/Helsinki", - "Europe/Isle_of_Man", - "Europe/Istanbul", - "Europe/Jersey", - "Europe/Kaliningrad", - "Europe/Kiev", - "Europe/Lisbon", - "Europe/Ljubljana", - "Europe/London", - "Europe/Luxembourg", - "Europe/Madrid", - "Europe/Malta", - "Europe/Mariehamn", - "Europe/Minsk", - "Europe/Monaco", - "Europe/Moscow", - "Europe/Nicosia", - "Europe/Oslo", - "Europe/Paris", - "Europe/Podgorica", - "Europe/Prague", - "Europe/Riga", - "Europe/Rome", - "Europe/Samara", - "Europe/San_Marino", - "Europe/Sarajevo", - "Europe/Simferopol", - "Europe/Skopje", - "Europe/Sofia", - "Europe/Stockholm", - "Europe/Tallinn", - "Europe/Tirane", - "Europe/Tiraspol", - "Europe/Uzhgorod", - "Europe/Vaduz", - "Europe/Vatican", - "Europe/Vienna", - "Europe/Vilnius", - "Europe/Volgograd", - "Europe/Warsaw", - "Europe/Zagreb", - "Europe/Zaporozhye", - "Europe/Zurich", - "GB", - "GB-Eire", - "GMT", - "GMT+0", - "GMT-0", - "GMT0", - "Greenwich", - "HST", - "Hongkong", - "Iceland", - "Indian/Antananarivo", - "Indian/Chagos", - "Indian/Christmas", - "Indian/Cocos", - "Indian/Comoro", - "Indian/Kerguelen", - "Indian/Mahe", - "Indian/Maldives", - "Indian/Mauritius", - "Indian/Mayotte", - "Indian/Reunion", - "Iran", - "Israel", - "Jamaica", - "Japan", - "Kwajalein", - "Libya", - "MET", - "MST", - "MST7MDT", - "Mexico/BajaNorte", - "Mexico/BajaSur", - "Mexico/General", - "NZ", - "NZ-CHAT", - "Navajo", - "PRC", - "PST8PDT", - "Pacific/Apia", - "Pacific/Auckland", - "Pacific/Bougainville", - "Pacific/Chatham", - "Pacific/Chuuk", - "Pacific/Easter", - "Pacific/Efate", - "Pacific/Enderbury", - "Pacific/Fakaofo", - "Pacific/Fiji", - "Pacific/Funafuti", - "Pacific/Galapagos", - "Pacific/Gambier", - "Pacific/Guadalcanal", - "Pacific/Guam", - "Pacific/Honolulu", - "Pacific/Johnston", - "Pacific/Kiritimati", - "Pacific/Kosrae", - "Pacific/Kwajalein", - "Pacific/Majuro", - "Pacific/Marquesas", - "Pacific/Midway", - "Pacific/Nauru", - "Pacific/Niue", - "Pacific/Norfolk", - "Pacific/Noumea", - "Pacific/Pago_Pago", - "Pacific/Palau", - "Pacific/Pitcairn", - "Pacific/Pohnpei", - "Pacific/Ponape", - "Pacific/Port_Moresby", - "Pacific/Rarotonga", - "Pacific/Saipan", - "Pacific/Samoa", - "Pacific/Tahiti", - "Pacific/Tarawa", - "Pacific/Tongatapu", - "Pacific/Truk", - "Pacific/Wake", - "Pacific/Wallis", - "Pacific/Yap", - "Poland", - "Portugal", - "ROC", - "ROK", - "Singapore", - "Turkey", - "UCT", - "US/Alaska", - "US/Aleutian", - "US/Arizona", - "US/Central", - "US/East-Indiana", - "US/Eastern", - "US/Hawaii", - "US/Indiana-Starke", - "US/Michigan", - "US/Mountain", - "US/Pacific", - "US/Pacific-New", - "US/Samoa", - "UTC", - "Universal", - "W-SU", - "WET", - "Zulu", - nullptr -}; - -// Helper to return a loaded time zone by value (UTC on error). -TimeZone LoadZone(const std::string& name) { - TimeZone tz; - LoadTimeZone(name, &tz); - return tz; -} - -// This helper is a macro so that failed expectations show up with the -// correct line numbers. -#define ExpectTime(bd, y, m, d, hh, mm, ss, off, isdst, zone) \ - do { \ - EXPECT_EQ(y, bd.year); \ - EXPECT_EQ(m, bd.month); \ - EXPECT_EQ(d, bd.day); \ - EXPECT_EQ(hh, bd.hour); \ - EXPECT_EQ(mm, bd.minute); \ - EXPECT_EQ(ss, bd.second); \ - EXPECT_EQ(off, bd.offset); \ - EXPECT_EQ(isdst, bd.is_dst); \ - EXPECT_EQ(zone, bd.abbr); \ - } while (0) - -} // namespace - -TEST(TimeZones, LoadZonesConcurrently) { - std::promise ready_promise; - std::shared_future ready_future(ready_promise.get_future()); - auto load_zones = [ready_future](std::promise* started) { - started->set_value(); - ready_future.wait(); - TimeZone tz; - for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { - EXPECT_TRUE(LoadTimeZone(*np, &tz)); - } - }; - - std::vector threads; - for (size_t i = 0; i != 256; ++i) { - std::promise started; - threads.emplace_back(load_zones, &started); - started.get_future().wait(); - } - - ready_promise.set_value(); - - for (auto& thread : threads) { - thread.join(); - } -} - -TEST(TimeZone, Failures) { - TimeZone tz; - EXPECT_FALSE(LoadTimeZone(":America/Los_Angeles", &tz)); - - tz = LoadZone("America/Los_Angeles"); - EXPECT_FALSE(LoadTimeZone("Invalid/TimeZone", &tz)); - EXPECT_EQ(system_clock::from_time_t(0), - MakeTime(1970, 1, 1, 0, 0, 0, tz)); // UTC - - // Ensures that the load still fails on a subsequent attempt. - tz = LoadZone("America/Los_Angeles"); - EXPECT_FALSE(LoadTimeZone("Invalid/TimeZone", &tz)); - EXPECT_EQ(system_clock::from_time_t(0), - MakeTime(1970, 1, 1, 0, 0, 0, tz)); // UTC - - // Loading an empty string timezone should fail. - tz = LoadZone("America/Los_Angeles"); - EXPECT_FALSE(LoadTimeZone("", &tz)); - EXPECT_EQ(system_clock::from_time_t(0), - MakeTime(1970, 1, 1, 0, 0, 0, tz)); // UTC -} - -TEST(StdChronoTimePoint, TimeTAlignment) { - // Ensures that the Unix epoch and the system clock epoch are an integral - // number of seconds apart. This simplifies conversions to/from time_t. - using TP = std::chrono::system_clock::time_point; - auto diff = TP() - std::chrono::system_clock::from_time_t(0); - EXPECT_EQ(TP::duration::zero(), diff % std::chrono::seconds(1)); -} - -TEST(BreakTime, TimePointResolution) { - using std::chrono::time_point_cast; - const TimeZone utc = UTCTimeZone(); - const auto t0 = system_clock::from_time_t(0); - Breakdown bd{}; - - bd = BreakTime(time_point_cast(t0), utc); - ExpectTime(bd, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - bd = BreakTime(time_point_cast(t0), utc); - ExpectTime(bd, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - bd = BreakTime(time_point_cast(t0), utc); - ExpectTime(bd, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - bd = BreakTime(time_point_cast(t0), utc); - ExpectTime(bd, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - bd = BreakTime(time_point_cast(t0), utc); - ExpectTime(bd, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - bd = BreakTime(time_point_cast(t0), utc); - ExpectTime(bd, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - bd = BreakTime(time_point_cast(t0), utc); - ExpectTime(bd, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); -} - -TEST(BreakTime, LocalTimeInUTC) { - const Breakdown bd = BreakTime(system_clock::from_time_t(0), UTCTimeZone()); - ExpectTime(bd, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - EXPECT_EQ(4, bd.weekday); // Thursday -} - -TEST(BreakTime, LocalTimePosix) { - // See IEEE Std 1003.1-1988 B.2.3 General Terms, Epoch. - const Breakdown bd = - BreakTime(system_clock::from_time_t(536457599), UTCTimeZone()); - ExpectTime(bd, 1986, 12, 31, 23, 59, 59, 0, false, "UTC"); - EXPECT_EQ(3, bd.weekday); // Wednesday -} - -TEST(BreakTime, LocalTimeInNewYork) { - const TimeZone tz = LoadZone("America/New_York"); - const Breakdown bd = BreakTime(system_clock::from_time_t(45), tz); - ExpectTime(bd, 1969, 12, 31, 19, 0, 45, -5 * 60 * 60, false, "EST"); - EXPECT_EQ(3, bd.weekday); // Wednesday -} - -TEST(BreakTime, LocalTimeInMTV) { - const TimeZone tz = LoadZone("America/Los_Angeles"); - const Breakdown bd = BreakTime(system_clock::from_time_t(1380855729), tz); - ExpectTime(bd, 2013, 10, 3, 20, 2, 9, -7 * 60 * 60, true, "PDT"); - EXPECT_EQ(4, bd.weekday); // Thursday -} - -TEST(BreakTime, LocalTimeInSydney) { - const TimeZone tz = LoadZone("Australia/Sydney"); - const Breakdown bd = BreakTime(system_clock::from_time_t(90), tz); - ExpectTime(bd, 1970, 1, 1, 10, 1, 30, 10 * 60 * 60, false, "AEST"); - EXPECT_EQ(4, bd.weekday); // Thursday -} - -TEST(MakeTime, TimePointResolution) { - const TimeZone utc = UTCTimeZone(); - const time_point tp_ns = - MakeTime(2015, 1, 2, 3, 4, 5, utc); - EXPECT_EQ("04:05", Format("%M:%E*S", tp_ns, utc)); - const time_point tp_us = - MakeTime(2015, 1, 2, 3, 4, 5, utc); - EXPECT_EQ("04:05", Format("%M:%E*S", tp_us, utc)); - const time_point tp_ms = - MakeTime(2015, 1, 2, 3, 4, 5, utc); - EXPECT_EQ("04:05", Format("%M:%E*S", tp_ms, utc)); - const time_point tp_s = - MakeTime(2015, 1, 2, 3, 4, 5, utc); - EXPECT_EQ("04:05", Format("%M:%E*S", tp_s, utc)); - const time_point tp_s64 = - MakeTime(2015, 1, 2, 3, 4, 5, utc); - EXPECT_EQ("04:05", Format("%M:%E*S", tp_s64, utc)); - - // These next two require time_point_cast because the conversion from a - // resolution of seconds (the return value of MakeTime()) to a coarser - // resolution requires an explicit cast. - using std::chrono::time_point_cast; - const time_point tp_m = - time_point_cast(MakeTime(2015, 1, 2, 3, 4, 5, utc)); - EXPECT_EQ("04:00", Format("%M:%E*S", tp_m, utc)); - const time_point tp_h = - time_point_cast(MakeTime(2015, 1, 2, 3, 4, 5, utc)); - EXPECT_EQ("00:00", Format("%M:%E*S", tp_h, utc)); -} - -TEST(MakeTime, Normalization) { - const TimeZone tz = LoadZone("America/New_York"); - const auto tp = MakeTime(2009, 2, 13, 18, 31, 30, tz); - EXPECT_EQ(system_clock::from_time_t(1234567890), tp); - - // Now requests for the same time_point but with out-of-range fields. - EXPECT_EQ(tp, MakeTime(2008, 14, 13, 18, 31, 30, tz)); // month - EXPECT_EQ(tp, MakeTime(2009, 1, 44, 18, 31, 30, tz)); // day - EXPECT_EQ(tp, MakeTime(2009, 2, 12, 42, 31, 30, tz)); // hour - EXPECT_EQ(tp, MakeTime(2009, 2, 13, 17, 91, 30, tz)); // minute - EXPECT_EQ(tp, MakeTime(2009, 2, 13, 18, 30, 90, tz)); // second -} - -TEST(TimeZoneEdgeCase, AmericaNewYork) { - const TimeZone tz = LoadZone("America/New_York"); - - // Spring 1:59:59 -> 3:00:00 - auto tp = MakeTime(2013, 3, 10, 1, 59, 59, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 3, 10, 1, 59, 59, -5 * 3600, false, "EST"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 3, 10, 3, 0, 0, -4 * 3600, true, "EDT"); - - // Fall 1:59:59 -> 1:00:00 - tp = MakeTime(2013, 11, 3, 1, 59, 59, tz); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 11, 3, 1, 59, 59, -4 * 3600, true, "EDT"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 11, 3, 1, 0, 0, -5 * 3600, false, "EST"); -} - -TEST(TimeZoneEdgeCase, AmericaLosAngeles) { - const TimeZone tz = LoadZone("America/Los_Angeles"); - - // Spring 1:59:59 -> 3:00:00 - auto tp = MakeTime(2013, 3, 10, 1, 59, 59, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 3, 10, 1, 59, 59, -8 * 3600, false, "PST"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 3, 10, 3, 0, 0, -7 * 3600, true, "PDT"); - - // Fall 1:59:59 -> 1:00:00 - tp = MakeTime(2013, 11, 3, 1, 59, 59, tz); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 11, 3, 1, 59, 59, -7 * 3600, true, "PDT"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 11, 3, 1, 0, 0, -8 * 3600, false, "PST"); -} - -TEST(TimeZoneEdgeCase, ArizonaNoTransition) { - const TimeZone tz = LoadZone("America/Phoenix"); - - // No transition in Spring. - auto tp = MakeTime(2013, 3, 10, 1, 59, 59, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 3, 10, 1, 59, 59, -7 * 3600, false, "MST"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 3, 10, 2, 0, 0, -7 * 3600, false, "MST"); - - // No transition in Fall. - tp = MakeTime(2013, 11, 3, 1, 59, 59, tz); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 11, 3, 1, 59, 59, -7 * 3600, false, "MST"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 11, 3, 2, 0, 0, -7 * 3600, false, "MST"); -} - -TEST(TimeZoneEdgeCase, AsiaKathmandu) { - const TimeZone tz = LoadZone("Asia/Kathmandu"); - - // A non-DST offset change from +0530 to +0545 - // - // 504901799 == Tue, 31 Dec 1985 23:59:59 +0530 (IST) - // 504901800 == Wed, 1 Jan 1986 00:15:00 +0545 (NPT) - auto tp = MakeTime(1985, 12, 31, 23, 59, 59, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 1985, 12, 31, 23, 59, 59, 5.5 * 3600, false, "IST"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 1986, 1, 1, 0, 15, 0, 5.75 * 3600, false, "NPT"); -} - -TEST(TimeZoneEdgeCase, PacificChatham) { - const TimeZone tz = LoadZone("Pacific/Chatham"); - - // One-hour DST offset changes, but at atypical values - // - // 1365256799 == Sun, 7 Apr 2013 03:44:59 +1345 (CHADT) - // 1365256800 == Sun, 7 Apr 2013 02:45:00 +1245 (CHAST) - auto tp = MakeTime(2013, 4, 7, 3, 44, 59, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 4, 7, 3, 44, 59, 13.75 * 3600, true, "CHADT"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 4, 7, 2, 45, 0, 12.75 * 3600, false, "CHAST"); - - // 1380376799 == Sun, 29 Sep 2013 02:44:59 +1245 (CHAST) - // 1380376800 == Sun, 29 Sep 2013 03:45:00 +1345 (CHADT) - tp = MakeTime(2013, 9, 29, 2, 44, 59, tz); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 9, 29, 2, 44, 59, 12.75 * 3600, false, "CHAST"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 9, 29, 3, 45, 0, 13.75 * 3600, true, "CHADT"); -} - -TEST(TimeZoneEdgeCase, AustraliaLordHowe) { - const TimeZone tz = LoadZone("Australia/Lord_Howe"); - - // Half-hour DST offset changes - // - // 1365260399 == Sun, 7 Apr 2013 01:59:59 +1100 (LHDT) - // 1365260400 == Sun, 7 Apr 2013 01:30:00 +1030 (LHST) - auto tp = MakeTime(2013, 4, 7, 1, 59, 59, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 4, 7, 1, 59, 59, 11 * 3600, true, "LHDT"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 4, 7, 1, 30, 0, 10.5 * 3600, false, "LHST"); - - // 1380986999 == Sun, 6 Oct 2013 01:59:59 +1030 (LHST) - // 1380987000 == Sun, 6 Oct 2013 02:30:00 +1100 (LHDT) - tp = MakeTime(2013, 10, 6, 1, 59, 59, tz); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 10, 6, 1, 59, 59, 10.5 * 3600, false, "LHST"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2013, 10, 6, 2, 30, 0, 11 * 3600, true, "LHDT"); -} - -TEST(TimeZoneEdgeCase, PacificApia) { - const TimeZone tz = LoadZone("Pacific/Apia"); - - // At the end of December 2011, Samoa jumped forward by one day, - // skipping 30 December from the local calendar, when the nation - // moved to the west of the International Date Line. - // - // A one-day, non-DST offset change - // - // 1325239199 == Thu, 29 Dec 2011 23:59:59 -1000 (SDT) - // 1325239200 == Sat, 31 Dec 2011 00:00:00 +1400 (WSDT) - auto tp = MakeTime(2011, 12, 29, 23, 59, 59, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 2011, 12, 29, 23, 59, 59, -10 * 3600, true, "SDT"); - EXPECT_EQ(363, bd.yearday); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2011, 12, 31, 0, 0, 0, 14 * 3600, true, "WSDT"); - EXPECT_EQ(365, bd.yearday); // What else could 2011/12/31 be!? -} - -TEST(TimeZoneEdgeCase, AfricaCairo) { - const TimeZone tz = LoadZone("Africa/Cairo"); - - // An interesting case of midnight not existing. - // - // 1400191199 == Thu, 15 May 2014 23:59:59 +0200 (EET) - // 1400191200 == Fri, 16 May 2014 01:00:00 +0300 (EEST) - auto tp = MakeTime(2014, 5, 15, 23, 59, 59, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 2014, 5, 15, 23, 59, 59, 2 * 3600, false, "EET"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2014, 5, 16, 1, 0, 0, 3 * 3600, true, "EEST"); -} - -TEST(TimeZoneEdgeCase, AfricaMonrovia) { - const TimeZone tz = LoadZone("Africa/Monrovia"); - - // Strange offset change -00:44:30 -> +00:00:00 (non-DST) - // - // 73529069 == Sun, 30 Apr 1972 23:59:59 -0044 (LRT) - // 73529070 == Mon, 1 May 1972 00:44:30 +0000 (GMT) - auto tp = MakeTime(1972, 4, 30, 23, 59, 59, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 1972, 4, 30, 23, 59, 59, -44.5 * 60, false, "LRT"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 1972, 5, 1, 0, 44, 30, 0 * 60, false, "GMT"); -} - -TEST(TimeZoneEdgeCase, AmericaJamaica) { - // Jamaica discontinued DST transitions in 1983, and is now at a - // constant -0500. This makes it an interesting edge-case target. - // Note that the 32-bit times used in a (tzh_version == 0) zoneinfo - // file cannot represent the abbreviation-only transition of 1890, - // so we ignore the abbreviation by expecting what we received. - const TimeZone tz = LoadZone("America/Jamaica"); - - // Before the first transition. - auto tp = MakeTime(1889, 12, 31, 0, 0, 0, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 1889, 12, 31, 0, 0, 0, -18431, false, bd.abbr); - - // Over the first (abbreviation-change only) transition. - // -2524503170 == Tue, 31 Dec 1889 23:59:59 -0507 (LMT) - // -2524503169 == Wed, 1 Jan 1890 00:00:00 -0507 (KMT) - tp = MakeTime(1889, 12, 31, 23, 59, 59, tz); - bd = BreakTime(tp, tz); - ExpectTime(bd, 1889, 12, 31, 23, 59, 59, -18431, false, bd.abbr); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 1890, 1, 1, 0, 0, 0, -18431, false, "KMT"); - - // Over the last (DST) transition. - // 436341599 == Sun, 30 Oct 1983 01:59:59 -0400 (EDT) - // 436341600 == Sun, 30 Oct 1983 01:00:00 -0500 (EST) - tp = MakeTime(1983, 10, 30, 1, 59, 59, tz); - bd = BreakTime(tp, tz); - ExpectTime(bd, 1983, 10, 30, 1, 59, 59, -4 * 3600, true, "EDT"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 1983, 10, 30, 1, 0, 0, -5 * 3600, false, "EST"); - - // After the last transition. - tp = MakeTime(1983, 12, 31, 23, 59, 59, tz); - bd = BreakTime(tp, tz); - ExpectTime(bd, 1983, 12, 31, 23, 59, 59, -5 * 3600, false, "EST"); -} - -TEST(TimeZoneEdgeCase, WET) { - // Cover some non-existent times within forward transitions. - const TimeZone tz = LoadZone("WET"); - - // Before the first transition. - auto tp = MakeTime(1977, 1, 1, 0, 0, 0, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 1977, 1, 1, 0, 0, 0, 0, false, "WET"); - - // Over the first transition. - // 228877199 == Sun, 3 Apr 1977 00:59:59 +0000 (WET) - // 228877200 == Sun, 3 Apr 1977 02:00:00 +0100 (WEST) - tp = MakeTime(1977, 4, 3, 0, 59, 59, tz); - bd = BreakTime(tp, tz); - ExpectTime(bd, 1977, 4, 3, 0, 59, 59, 0, false, "WET"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST"); - - // A non-existent time within the first transition. - TimeInfo ti1 = MakeTimeInfo(1977, 4, 3, 1, 15, 0, tz); - EXPECT_FALSE(ti1.normalized); - EXPECT_EQ(TimeInfo::Kind::SKIPPED, ti1.kind); - bd = BreakTime(ti1.pre, tz); - ExpectTime(bd, 1977, 4, 3, 2, 15, 0, 1 * 3600, true, "WEST"); - bd = BreakTime(ti1.trans, tz); - ExpectTime(bd, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST"); - bd = BreakTime(ti1.post, tz); - ExpectTime(bd, 1977, 4, 3, 0, 15, 0, 0 * 3600, false, "WET"); - - // A non-existent time within the second forward transition. - TimeInfo ti2 = MakeTimeInfo(1978, 4, 2, 1, 15, 0, tz); - EXPECT_FALSE(ti2.normalized); - EXPECT_EQ(TimeInfo::Kind::SKIPPED, ti2.kind); - bd = BreakTime(ti2.pre, tz); - ExpectTime(bd, 1978, 4, 2, 2, 15, 0, 1 * 3600, true, "WEST"); - bd = BreakTime(ti2.trans, tz); - ExpectTime(bd, 1978, 4, 2, 2, 0, 0, 1 * 3600, true, "WEST"); - bd = BreakTime(ti2.post, tz); - ExpectTime(bd, 1978, 4, 2, 0, 15, 0, 0 * 3600, false, "WET"); -} - -TEST(TimeZoneEdgeCase, FixedOffsets) { - const TimeZone gmtm5 = LoadZone("Etc/GMT+5"); // -0500 - auto tp = MakeTime(1970, 1, 1, 0, 0, 0, gmtm5); - Breakdown bd = BreakTime(tp, gmtm5); - ExpectTime(bd, 1970, 1, 1, 0, 0, 0, -5 * 3600, false, "GMT+5"); - EXPECT_EQ(system_clock::from_time_t(5 * 3600), tp); - - const TimeZone gmtp5 = LoadZone("Etc/GMT-5"); // +0500 - tp = MakeTime(1970, 1, 1, 0, 0, 0, gmtp5); - bd = BreakTime(tp, gmtp5); - ExpectTime(bd, 1970, 1, 1, 0, 0, 0, 5 * 3600, false, "GMT-5"); - EXPECT_EQ(system_clock::from_time_t(-5 * 3600), tp); -} - -TEST(TimeZoneEdgeCase, NegativeYear) { - // Tests transition from year 0 (aka 1BCE) to year -1. - const TimeZone tz = UTCTimeZone(); - auto tp = MakeTime(0, 1, 1, 0, 0, 0, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 0, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC"); - EXPECT_EQ(6, bd.weekday); - tp -= std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, -1, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC"); - EXPECT_EQ(5, bd.weekday); -} - -TEST(TimeZoneEdgeCase, UTC32bitLimit) { - const TimeZone tz = UTCTimeZone(); - - // Limits of signed 32-bit time_t - // - // 2147483647 == Tue, 19 Jan 2038 03:14:07 +0000 (UTC) - // 2147483648 == Tue, 19 Jan 2038 03:14:08 +0000 (UTC) - auto tp = MakeTime(2038, 1, 19, 3, 14, 7, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 2038, 1, 19, 3, 14, 7, 0 * 3600, false, "UTC"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 2038, 1, 19, 3, 14, 8, 0 * 3600, false, "UTC"); -} - -TEST(TimeZoneEdgeCase, UTC5DigitYear) { - const TimeZone tz = UTCTimeZone(); - - // Rollover to 5-digit year - // - // 253402300799 == Fri, 31 Dec 9999 23:59:59 +0000 (UTC) - // 253402300800 == Sat, 1 Jan 1000 00:00:00 +0000 (UTC) - auto tp = MakeTime(9999, 12, 31, 23, 59, 59, tz); - Breakdown bd = BreakTime(tp, tz); - ExpectTime(bd, 9999, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC"); - tp += std::chrono::seconds(1); - bd = BreakTime(tp, tz); - ExpectTime(bd, 10000, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC"); -} - -// These tests are disabled because they require 64-bit civil years. -#if 0 -TEST(TimeZoneEdgeCase, East64bitLimit) { - // For zones with positive offsets we cannot really get all the way to the - // maximal time_point as anything closer than the offset will (currently) - // result in an internal integer overflow. (Check 15:30:08 with -ftrapv.) - const TimeZone tz = LoadZone("Etc/GMT-14"); - time_point tp = MakeTime(292277026596, 12, 4, 15, 30, 7, tz); - EXPECT_EQ(std::numeric_limits::max() - 14 * 3600, - tp.time_since_epoch().count()); -} - -TEST(TimeZoneEdgeCase, West64bitLimit) { - // For zones with negative offsets we cannot really get all the way to the - // minimal time_point as anything closer than the offset will (currently) - // result in an internal integer overflow. (Check 08:29:51 with -ftrapv.) - const TimeZone tz = LoadZone("Etc/GMT+12"); - time_point tp = MakeTime(-292277022657, 1, 27, 8, 29, 52, tz); - EXPECT_EQ(std::numeric_limits::min() + 12 * 3600, - tp.time_since_epoch().count()); -} -#endif - -} // namespace cctz diff --git a/src/civil_time_detail.cc b/src/civil_time_detail.cc new file mode 100644 index 000000000..b6856b8df --- /dev/null +++ b/src/civil_time_detail.cc @@ -0,0 +1,86 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cctz/civil_time_detail.h" + +#include +#include +#include + +namespace cctz { +namespace detail { + +// Output stream operators output a format matching YYYY-MM-DDThh:mm:ss, +// while omitting fields inferior to the type's alignment. For example, +// civil_day is formatted only as YYYY-MM-DD. +std::ostream& operator<<(std::ostream& os, const civil_year& y) { + std::stringstream ss; + ss << y.year(); // No padding. + return os << ss.str(); +} +std::ostream& operator<<(std::ostream& os, const civil_month& m) { + std::stringstream ss; + ss << civil_year(m) << '-'; + ss << std::setfill('0') << std::setw(2) << m.month(); + return os << ss.str(); +} +std::ostream& operator<<(std::ostream& os, const civil_day& d) { + std::stringstream ss; + ss << civil_month(d) << '-'; + ss << std::setfill('0') << std::setw(2) << d.day(); + return os << ss.str(); +} +std::ostream& operator<<(std::ostream& os, const civil_hour& h) { + std::stringstream ss; + ss << civil_day(h) << 'T'; + ss << std::setfill('0') << std::setw(2) << h.hour(); + return os << ss.str(); +} +std::ostream& operator<<(std::ostream& os, const civil_minute& m) { + std::stringstream ss; + ss << civil_hour(m) << ':'; + ss << std::setfill('0') << std::setw(2) << m.minute(); + return os << ss.str(); +} +std::ostream& operator<<(std::ostream& os, const civil_second& s) { + std::stringstream ss; + ss << civil_minute(s) << ':'; + ss << std::setfill('0') << std::setw(2) << s.second(); + return os << ss.str(); +} + +//////////////////////////////////////////////////////////////////////// + +std::ostream& operator<<(std::ostream& os, weekday wd) { + switch (wd) { + case weekday::monday: + return os << "Monday"; + case weekday::tuesday: + return os << "Tuesday"; + case weekday::wednesday: + return os << "Wednesday"; + case weekday::thursday: + return os << "Thursday"; + case weekday::friday: + return os << "Friday"; + case weekday::saturday: + return os << "Saturday"; + case weekday::sunday: + return os << "Sunday"; + } + return os; // Should never get here, but -Wreturn-type may warn without this. +} + +} // namespace detail +} // namespace cctz diff --git a/src/civil_time_test.cc b/src/civil_time_test.cc index d3e8a636c..5ec0ca8d3 100644 --- a/src/civil_time_test.cc +++ b/src/civil_time_test.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "civil_time.h" +#include "cctz/civil_time.h" #include #include -#include #include +#include #include #include "gtest/gtest.h" @@ -35,7 +35,7 @@ std::string Format(const T& t) { } // namespace -#if __clang__ && __cpp_constexpr >= 201304 +#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) // Construction constexpr tests TEST(CivilTime, Normal) { @@ -223,11 +223,79 @@ TEST(CivilTime, Subtraction) { static_assert(cs2.second() == 22, "Subtraction.second"); } -TEST(CivilTime, Diff) { +TEST(CivilTime, Difference) { constexpr civil_day cd1(2016, 1, 28); constexpr civil_day cd2(2015, 1, 28); constexpr int diff = cd1 - cd2; - static_assert(diff == 365, "Diff"); + static_assert(diff == 365, "Difference"); +} + +// NOTE: Run this with --copt=-ftrapv to detect overflow problems. +TEST(CivilTime, ConstructionWithHugeYear) { + constexpr civil_hour h(-9223372036854775807, 1, 1, -1); + static_assert(h.year() == -9223372036854775807 - 1, + "ConstructionWithHugeYear"); + static_assert(h.month() == 12, "ConstructionWithHugeYear"); + static_assert(h.day() == 31, "ConstructionWithHugeYear"); + static_assert(h.hour() == 23, "ConstructionWithHugeYear"); +} + +// NOTE: Run this with --copt=-ftrapv to detect overflow problems. +TEST(CivilTime, DifferenceWithHugeYear) { + { + constexpr civil_day d1(9223372036854775807, 1, 1); + constexpr civil_day d2(9223372036854775807, 12, 31); + static_assert(d2 - d1 == 364, "DifferenceWithHugeYear"); + } + { + constexpr civil_day d1(-9223372036854775807 - 1, 1, 1); + constexpr civil_day d2(-9223372036854775807 - 1, 12, 31); + static_assert(d2 - d1 == 365, "DifferenceWithHugeYear"); + } + { + // Check the limits of the return value at the end of the year range. + constexpr civil_day d1(9223372036854775807, 1, 1); + constexpr civil_day d2(9198119301927009252, 6, 6); + static_assert(d1 - d2 == 9223372036854775807, "DifferenceWithHugeYear"); + static_assert((d2 - 1) - d1 == -9223372036854775807 - 1, + "DifferenceWithHugeYear"); + } + { + // Check the limits of the return value at the start of the year range. + constexpr civil_day d1(-9223372036854775807 - 1, 1, 1); + constexpr civil_day d2(-9198119301927009254, 7, 28); + static_assert(d2 - d1 == 9223372036854775807, "DifferenceWithHugeYear"); + static_assert(d1 - (d2 + 1) == -9223372036854775807 - 1, + "DifferenceWithHugeYear"); + } + { + // Check the limits of the return value from either side of year 0. + constexpr civil_day d1(-12626367463883278, 9, 3); + constexpr civil_day d2(12626367463883277, 3, 28); + static_assert(d2 - d1 == 9223372036854775807, "DifferenceWithHugeYear"); + static_assert(d1 - (d2 + 1) == -9223372036854775807 - 1, + "DifferenceWithHugeYear"); + } +} + +// NOTE: Run this with --copt=-ftrapv to detect overflow problems. +TEST(CivilTime, DifferenceNoIntermediateOverflow) { + { + // The difference up to the minute field would be below the minimum + // diff_t, but the 52 extra seconds brings us back to the minimum. + constexpr civil_second s1(-292277022657, 1, 27, 8, 29 - 1, 52); + constexpr civil_second s2(1970, 1, 1, 0, 0 - 1, 0); + static_assert(s1 - s2 == -9223372036854775807 - 1, + "DifferenceNoIntermediateOverflow"); + } + { + // The difference up to the minute field would be above the maximum + // diff_t, but the -53 extra seconds brings us back to the maximum. + constexpr civil_second s1(292277026596, 12, 4, 15, 30, 7 - 7); + constexpr civil_second s2(1970, 1, 1, 0, 0, 0 - 7); + static_assert(s1 - s2 == 9223372036854775807, + "DifferenceNoIntermediateOverflow"); + } } // Helper constexpr tests @@ -259,7 +327,7 @@ TEST(CivilTime, YearDay) { constexpr int yd = get_yearday(cd); static_assert(yd == 28, "YearDay"); } -#endif // __clang__ && __cpp_constexpr >= 201304 +#endif // __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) // The remaining tests do not use constexpr. @@ -363,25 +431,6 @@ TEST(CivilTime, FieldsConstructionLimits) { Format(civil_second(1970, kIntMin, kIntMin, kIntMin, kIntMin, kIntMin))); } -TEST(CivilTime, RangeLimits) { - const int kIntMax = std::numeric_limits::max(); - const int kIntMin = std::numeric_limits::min(); - - EXPECT_EQ(civil_year(kIntMax), civil_year::max()); - EXPECT_EQ(civil_month(kIntMax, 12), civil_month::max()); - EXPECT_EQ(civil_day(kIntMax, 12, 31), civil_day::max()); - EXPECT_EQ(civil_hour(kIntMax, 12, 31, 23), civil_hour::max()); - EXPECT_EQ(civil_minute(kIntMax, 12, 31, 23, 59), civil_minute::max()); - EXPECT_EQ(civil_second(kIntMax, 12, 31, 23, 59, 59), civil_second::max()); - - EXPECT_EQ(civil_year(kIntMin), civil_year::min()); - EXPECT_EQ(civil_month(kIntMin, 1), civil_month::min()); - EXPECT_EQ(civil_day(kIntMin, 1, 1), civil_day::min()); - EXPECT_EQ(civil_hour(kIntMin, 1, 1, 0), civil_hour::min()); - EXPECT_EQ(civil_minute(kIntMin, 1, 1, 0, 0), civil_minute::min()); - EXPECT_EQ(civil_second(kIntMin, 1, 1, 0, 0, 0), civil_second::min()); -} - TEST(CivilTime, ImplicitCrossAlignment) { civil_year year(2015); civil_month month = year; @@ -490,6 +539,47 @@ TEST(CivilTime, ExplicitCrossAlignment) { EXPECT_EQ("2015-01-01T00:00:00", Format(second)); } +// Metafunction to test whether difference is allowed between two types. +template +struct HasDifference { + template + static std::false_type test(...); + template + static std::true_type test(decltype(std::declval() - std::declval())); + static constexpr bool value = decltype(test(0))::value; +}; + +TEST(CivilTime, DisallowCrossAlignedDifference) { + // Difference is allowed between types with the same alignment. + static_assert(HasDifference::value, ""); + static_assert(HasDifference::value, ""); + static_assert(HasDifference::value, ""); + static_assert(HasDifference::value, ""); + static_assert(HasDifference::value, ""); + static_assert(HasDifference::value, ""); + + // Difference is disallowed between types with different alignments. + static_assert(!HasDifference::value, ""); + static_assert(!HasDifference::value, ""); + static_assert(!HasDifference::value, ""); + static_assert(!HasDifference::value, ""); + static_assert(!HasDifference::value, ""); + + static_assert(!HasDifference::value, ""); + static_assert(!HasDifference::value, ""); + static_assert(!HasDifference::value, ""); + static_assert(!HasDifference::value, ""); + + static_assert(!HasDifference::value, ""); + static_assert(!HasDifference::value, ""); + static_assert(!HasDifference::value, ""); + + static_assert(!HasDifference::value, ""); + static_assert(!HasDifference::value, ""); + + static_assert(!HasDifference::value, ""); +} + TEST(CivilTime, ValueSemantics) { const civil_hour a(2015, 1, 2, 3); const civil_hour b = a; @@ -538,7 +628,7 @@ TEST(CivilTime, Relational) { TEST_RELATIONAL(civil_second(2014, 1, 1, 1, 1, 0), civil_second(2014, 1, 1, 1, 1, 1)); - // Tests the relational operators of two different CivilTime types. + // Tests the relational operators of two different civil-time types. TEST_RELATIONAL(civil_day(2014, 1, 1), civil_minute(2014, 1, 1, 1, 1)); TEST_RELATIONAL(civil_day(2014, 1, 1), civil_month(2014, 2)); @@ -678,7 +768,7 @@ TEST(CivilTime, ArithmeticLimits) { EXPECT_EQ("0", Format(year)); } -TEST(CivilTime, Difference) { +TEST(CivilTime, ArithmeticDifference) { civil_second second(2015, 1, 2, 3, 4, 5); EXPECT_EQ(0, second - second); EXPECT_EQ(10, (second + 10) - second); @@ -739,6 +829,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(4, ss.hour()); EXPECT_EQ(5, ss.minute()); EXPECT_EQ(6, ss.second()); + EXPECT_EQ(weekday::tuesday, get_weekday(ss)); + EXPECT_EQ(34, get_yearday(ss)); civil_minute mm(2015, 2, 3, 4, 5, 6); EXPECT_EQ(2015, mm.year()); @@ -747,6 +839,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(4, mm.hour()); EXPECT_EQ(5, mm.minute()); EXPECT_EQ(0, mm.second()); + EXPECT_EQ(weekday::tuesday, get_weekday(mm)); + EXPECT_EQ(34, get_yearday(mm)); civil_hour hh(2015, 2, 3, 4, 5, 6); EXPECT_EQ(2015, hh.year()); @@ -755,6 +849,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(4, hh.hour()); EXPECT_EQ(0, hh.minute()); EXPECT_EQ(0, hh.second()); + EXPECT_EQ(weekday::tuesday, get_weekday(hh)); + EXPECT_EQ(34, get_yearday(hh)); civil_day d(2015, 2, 3, 4, 5, 6); EXPECT_EQ(2015, d.year()); @@ -773,6 +869,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(0, m.hour()); EXPECT_EQ(0, m.minute()); EXPECT_EQ(0, m.second()); + EXPECT_EQ(weekday::sunday, get_weekday(m)); + EXPECT_EQ(32, get_yearday(m)); civil_year y(2015, 2, 3, 4, 5, 6); EXPECT_EQ(2015, y.year()); @@ -781,6 +879,8 @@ TEST(CivilTime, Properties) { EXPECT_EQ(0, y.hour()); EXPECT_EQ(0, y.minute()); EXPECT_EQ(0, y.second()); + EXPECT_EQ(weekday::thursday, get_weekday(y)); + EXPECT_EQ(1, get_yearday(y)); } TEST(CivilTime, OutputStream) { @@ -900,48 +1000,16 @@ TEST(CivilTime, NextPrevWeekday) { EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::wednesday)); } -// NOTE: Run this with --copt=-ftrapv to detect overflow problems. -TEST(CivilTime, DifferenceWithHugeYear) { - civil_day d1(5881579, 1, 1); - civil_day d2(5881579, 12, 31); - EXPECT_EQ(364, d2 - d1); - - d1 = civil_day(-5877640, 1, 1); - d2 = civil_day(-5877640, 12, 31); - EXPECT_EQ(365, d2 - d1); - - // Check the limits of the return value with large positive year. - d1 = civil_day(5881580, 7, 11); - d2 = civil_day(1970, 1, 1); - EXPECT_EQ(2147483647, d1 - d2); - d2 = d2 - 1; - EXPECT_EQ(-2147483647 - 1, d2 - d1); - - // Check the limits of the return value with large negative year. - d1 = civil_day(-5877641, 6, 23); - d2 = civil_day(1969, 12, 31); - EXPECT_EQ(2147483647, d2 - d1); - d2 = d2 + 1; - EXPECT_EQ(-2147483647 - 1, d1 - d2); - - // Check the limits of the return value from either side of year 0. - d1 = civil_day(-2939806, 9, 26); - d2 = civil_day(2939805, 4, 6); - EXPECT_EQ(2147483647, d2 - d1); - d2 = d2 + 1; - EXPECT_EQ(-2147483647 - 1, d1 - d2); -} - TEST(CivilTime, NormalizeWithHugeYear) { - civil_month c(2147483647, 1); - EXPECT_EQ("2147483647-01", Format(c)); + civil_month c(9223372036854775807, 1); + EXPECT_EQ("9223372036854775807-01", Format(c)); c = c - 1; // Causes normalization - EXPECT_EQ("2147483646-12", Format(c)); + EXPECT_EQ("9223372036854775806-12", Format(c)); - c = civil_month(-2147483647 - 1, 1); - EXPECT_EQ("-2147483648-01", Format(c)); + c = civil_month(-9223372036854775807 - 1, 1); + EXPECT_EQ("-9223372036854775808-01", Format(c)); c = c + 12; // Causes normalization - EXPECT_EQ("-2147483647-01", Format(c)); + EXPECT_EQ("-9223372036854775807-01", Format(c)); } TEST(CivilTime, LeapYears) { @@ -969,29 +1037,23 @@ TEST(CivilTime, LeapYears) { {2100, 365, {3, 1}}, }; - for (size_t i = 0; i < (sizeof kLeapYearTable) / (sizeof kLeapYearTable[0]); - ++i) { - const int y = kLeapYearTable[i].year; - const int m = kLeapYearTable[i].leap_day.month; - const int d = kLeapYearTable[i].leap_day.day; - const int n = kLeapYearTable[i].days; - + for (const auto& e : kLeapYearTable) { // Tests incrementing through the leap day. - const civil_day feb28(y, 2, 28); + const civil_day feb28(e.year, 2, 28); const civil_day next_day = feb28 + 1; - EXPECT_EQ(m, next_day.month()); - EXPECT_EQ(d, next_day.day()); + EXPECT_EQ(e.leap_day.month, next_day.month()); + EXPECT_EQ(e.leap_day.day, next_day.day()); // Tests difference in days of leap years. const civil_year year(feb28); const civil_year next_year = year + 1; - EXPECT_EQ(n, civil_day(next_year) - civil_day(year)); + EXPECT_EQ(e.days, civil_day(next_year) - civil_day(year)); } } TEST(CivilTime, FirstThursdayInMonth) { const civil_day nov1(2014, 11, 1); - const civil_day thursday = prev_weekday(nov1, weekday::thursday) + 7; + const civil_day thursday = next_weekday(nov1 - 1, weekday::thursday); EXPECT_EQ("2014-11-06", Format(thursday)); // Bonus: Date of Thanksgiving in the United States diff --git a/src/test_time_zone_names.cc b/src/test_time_zone_names.cc new file mode 100644 index 000000000..a89469474 --- /dev/null +++ b/src/test_time_zone_names.cc @@ -0,0 +1,509 @@ +// Copyright 2025 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test_time_zone_names.h" + +namespace cctz { + +// A list of known time-zone names. +const char* const kTimeZoneNames[] = { + "Africa/Abidjan", + "Africa/Accra", + "Africa/Addis_Ababa", + "Africa/Algiers", + "Africa/Asmara", + "Africa/Bamako", + "Africa/Bangui", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Blantyre", + "Africa/Brazzaville", + "Africa/Bujumbura", + "Africa/Cairo", + "Africa/Casablanca", + "Africa/Ceuta", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Douala", + "Africa/El_Aaiun", + "Africa/Freetown", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Kigali", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Lome", + "Africa/Luanda", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Malabo", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Africa/Mogadishu", + "Africa/Monrovia", + "Africa/Nairobi", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Porto-Novo", + "Africa/Sao_Tome", + "Africa/Timbuktu", + "Africa/Tripoli", + "Africa/Tunis", + "Africa/Windhoek", + "America/Adak", + "America/Anchorage", + "America/Anguilla", + "America/Antigua", + "America/Araguaina", + "America/Argentina/Buenos_Aires", + "America/Argentina/Catamarca", + "America/Argentina/Cordoba", + "America/Argentina/Jujuy", + "America/Argentina/La_Rioja", + "America/Argentina/Mendoza", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Aruba", + "America/Asuncion", + "America/Atikokan", + "America/Atka", + "America/Bahia", + "America/Bahia_Banderas", + "America/Barbados", + "America/Belem", + "America/Belize", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Bogota", + "America/Boise", + "America/Cambridge_Bay", + "America/Campo_Grande", + "America/Cancun", + "America/Caracas", + "America/Cayenne", + "America/Cayman", + "America/Chicago", + "America/Chihuahua", + "America/Ciudad_Juarez", + "America/Coral_Harbour", + "America/Costa_Rica", + "America/Coyhaique", + "America/Creston", + "America/Cuiaba", + "America/Curacao", + "America/Danmarkshavn", + "America/Dawson", + "America/Dawson_Creek", + "America/Denver", + "America/Detroit", + "America/Dominica", + "America/Edmonton", + "America/Eirunepe", + "America/El_Salvador", + "America/Ensenada", + "America/Fort_Nelson", + "America/Fortaleza", + "America/Glace_Bay", + "America/Goose_Bay", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guatemala", + "America/Guayaquil", + "America/Guyana", + "America/Halifax", + "America/Havana", + "America/Hermosillo", + "America/Indiana/Indianapolis", + "America/Indiana/Knox", + "America/Indiana/Marengo", + "America/Indiana/Petersburg", + "America/Indiana/Tell_City", + "America/Indiana/Vevay", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Inuvik", + "America/Iqaluit", + "America/Jamaica", + "America/Juneau", + "America/Kentucky/Louisville", + "America/Kentucky/Monticello", + "America/Kralendijk", + "America/La_Paz", + "America/Lima", + "America/Los_Angeles", + "America/Lower_Princes", + "America/Maceio", + "America/Managua", + "America/Manaus", + "America/Marigot", + "America/Martinique", + "America/Matamoros", + "America/Mazatlan", + "America/Menominee", + "America/Merida", + "America/Metlakatla", + "America/Mexico_City", + "America/Miquelon", + "America/Moncton", + "America/Monterrey", + "America/Montevideo", + "America/Montreal", + "America/Montserrat", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Nome", + "America/Noronha", + "America/North_Dakota/Beulah", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Nuuk", + "America/Ojinaga", + "America/Panama", + "America/Pangnirtung", + "America/Paramaribo", + "America/Phoenix", + "America/Port-au-Prince", + "America/Port_of_Spain", + "America/Porto_Acre", + "America/Porto_Velho", + "America/Puerto_Rico", + "America/Punta_Arenas", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Recife", + "America/Regina", + "America/Resolute", + "America/Rio_Branco", + "America/Santa_Isabel", + "America/Santarem", + "America/Santiago", + "America/Santo_Domingo", + "America/Sao_Paulo", + "America/Scoresbysund", + "America/Shiprock", + "America/Sitka", + "America/St_Barthelemy", + "America/St_Johns", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Swift_Current", + "America/Tegucigalpa", + "America/Thule", + "America/Thunder_Bay", + "America/Tijuana", + "America/Toronto", + "America/Tortola", + "America/Vancouver", + "America/Virgin", + "America/Whitehorse", + "America/Winnipeg", + "America/Yakutat", + "America/Yellowknife", + "Antarctica/Casey", + "Antarctica/Davis", + "Antarctica/DumontDUrville", + "Antarctica/Macquarie", + "Antarctica/Mawson", + "Antarctica/McMurdo", + "Antarctica/Palmer", + "Antarctica/Rothera", + "Antarctica/Syowa", + "Antarctica/Troll", + "Antarctica/Vostok", + "Arctic/Longyearbyen", + "Asia/Aden", + "Asia/Almaty", + "Asia/Amman", + "Asia/Anadyr", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Atyrau", + "Asia/Baghdad", + "Asia/Bahrain", + "Asia/Baku", + "Asia/Bangkok", + "Asia/Barnaul", + "Asia/Beirut", + "Asia/Bishkek", + "Asia/Brunei", + "Asia/Chita", + "Asia/Choibalsan", + "Asia/Chongqing", + "Asia/Colombo", + "Asia/Damascus", + "Asia/Dhaka", + "Asia/Dili", + "Asia/Dubai", + "Asia/Dushanbe", + "Asia/Famagusta", + "Asia/Gaza", + "Asia/Harbin", + "Asia/Hebron", + "Asia/Ho_Chi_Minh", + "Asia/Hong_Kong", + "Asia/Hovd", + "Asia/Irkutsk", + "Asia/Istanbul", + "Asia/Jakarta", + "Asia/Jayapura", + "Asia/Jerusalem", + "Asia/Kabul", + "Asia/Kamchatka", + "Asia/Karachi", + "Asia/Kashgar", + "Asia/Kathmandu", + "Asia/Khandyga", + "Asia/Kolkata", + "Asia/Krasnoyarsk", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Kuwait", + "Asia/Macau", + "Asia/Magadan", + "Asia/Makassar", + "Asia/Manila", + "Asia/Muscat", + "Asia/Nicosia", + "Asia/Novokuznetsk", + "Asia/Novosibirsk", + "Asia/Omsk", + "Asia/Oral", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Pyongyang", + "Asia/Qatar", + "Asia/Qostanay", + "Asia/Qyzylorda", + "Asia/Riyadh", + "Asia/Sakhalin", + "Asia/Samarkand", + "Asia/Seoul", + "Asia/Shanghai", + "Asia/Singapore", + "Asia/Srednekolymsk", + "Asia/Taipei", + "Asia/Tashkent", + "Asia/Tbilisi", + "Asia/Tehran", + "Asia/Tel_Aviv", + "Asia/Thimphu", + "Asia/Tokyo", + "Asia/Tomsk", + "Asia/Ulaanbaatar", + "Asia/Urumqi", + "Asia/Ust-Nera", + "Asia/Vientiane", + "Asia/Vladivostok", + "Asia/Yakutsk", + "Asia/Yangon", + "Asia/Yekaterinburg", + "Asia/Yerevan", + "Atlantic/Azores", + "Atlantic/Bermuda", + "Atlantic/Canary", + "Atlantic/Cape_Verde", + "Atlantic/Faroe", + "Atlantic/Jan_Mayen", + "Atlantic/Madeira", + "Atlantic/Reykjavik", + "Atlantic/South_Georgia", + "Atlantic/St_Helena", + "Atlantic/Stanley", + "Australia/Adelaide", + "Australia/Brisbane", + "Australia/Broken_Hill", + "Australia/Canberra", + "Australia/Currie", + "Australia/Darwin", + "Australia/Eucla", + "Australia/Hobart", + "Australia/Lindeman", + "Australia/Lord_Howe", + "Australia/Melbourne", + "Australia/Perth", + "Australia/Sydney", + "Australia/Yancowinna", + "Etc/GMT", + "Etc/GMT+0", + "Etc/GMT+1", + "Etc/GMT+10", + "Etc/GMT+11", + "Etc/GMT+12", + "Etc/GMT+2", + "Etc/GMT+3", + "Etc/GMT+4", + "Etc/GMT+5", + "Etc/GMT+6", + "Etc/GMT+7", + "Etc/GMT+8", + "Etc/GMT+9", + "Etc/GMT-0", + "Etc/GMT-1", + "Etc/GMT-10", + "Etc/GMT-11", + "Etc/GMT-12", + "Etc/GMT-13", + "Etc/GMT-14", + "Etc/GMT-2", + "Etc/GMT-3", + "Etc/GMT-4", + "Etc/GMT-5", + "Etc/GMT-6", + "Etc/GMT-7", + "Etc/GMT-8", + "Etc/GMT-9", + "Etc/GMT0", + "Etc/Greenwich", + "Etc/UCT", + "Etc/UTC", + "Etc/Universal", + "Etc/Zulu", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Astrakhan", + "Europe/Athens", + "Europe/Belfast", + "Europe/Belgrade", + "Europe/Berlin", + "Europe/Bratislava", + "Europe/Brussels", + "Europe/Bucharest", + "Europe/Budapest", + "Europe/Busingen", + "Europe/Chisinau", + "Europe/Copenhagen", + "Europe/Dublin", + "Europe/Gibraltar", + "Europe/Guernsey", + "Europe/Helsinki", + "Europe/Isle_of_Man", + "Europe/Istanbul", + "Europe/Jersey", + "Europe/Kaliningrad", + "Europe/Kirov", + "Europe/Kyiv", + "Europe/Lisbon", + "Europe/Ljubljana", + "Europe/London", + "Europe/Luxembourg", + "Europe/Madrid", + "Europe/Malta", + "Europe/Mariehamn", + "Europe/Minsk", + "Europe/Monaco", + "Europe/Moscow", + "Europe/Nicosia", + "Europe/Oslo", + "Europe/Paris", + "Europe/Podgorica", + "Europe/Prague", + "Europe/Riga", + "Europe/Rome", + "Europe/Samara", + "Europe/San_Marino", + "Europe/Sarajevo", + "Europe/Saratov", + "Europe/Simferopol", + "Europe/Skopje", + "Europe/Sofia", + "Europe/Stockholm", + "Europe/Tallinn", + "Europe/Tirane", + "Europe/Tiraspol", + "Europe/Ulyanovsk", + "Europe/Vaduz", + "Europe/Vatican", + "Europe/Vienna", + "Europe/Vilnius", + "Europe/Volgograd", + "Europe/Warsaw", + "Europe/Zagreb", + "Europe/Zurich", + "Factory", + "Indian/Antananarivo", + "Indian/Chagos", + "Indian/Christmas", + "Indian/Cocos", + "Indian/Comoro", + "Indian/Kerguelen", + "Indian/Mahe", + "Indian/Maldives", + "Indian/Mauritius", + "Indian/Mayotte", + "Indian/Reunion", + "Pacific/Apia", + "Pacific/Auckland", + "Pacific/Bougainville", + "Pacific/Chatham", + "Pacific/Chuuk", + "Pacific/Easter", + "Pacific/Efate", + "Pacific/Fakaofo", + "Pacific/Fiji", + "Pacific/Funafuti", + "Pacific/Galapagos", + "Pacific/Gambier", + "Pacific/Guadalcanal", + "Pacific/Guam", + "Pacific/Honolulu", + "Pacific/Johnston", + "Pacific/Kanton", + "Pacific/Kiritimati", + "Pacific/Kosrae", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Marquesas", + "Pacific/Midway", + "Pacific/Nauru", + "Pacific/Niue", + "Pacific/Norfolk", + "Pacific/Noumea", + "Pacific/Pago_Pago", + "Pacific/Palau", + "Pacific/Pitcairn", + "Pacific/Pohnpei", + "Pacific/Port_Moresby", + "Pacific/Rarotonga", + "Pacific/Saipan", + "Pacific/Samoa", + "Pacific/Tahiti", + "Pacific/Tarawa", + "Pacific/Tongatapu", + "Pacific/Wake", + "Pacific/Wallis", + "Pacific/Yap", + "UTC", + nullptr +}; + +} // namespace cctz diff --git a/src/test_time_zone_names.h b/src/test_time_zone_names.h new file mode 100644 index 000000000..194d5350c --- /dev/null +++ b/src/test_time_zone_names.h @@ -0,0 +1,25 @@ +// Copyright 2025 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CCTZ_TEST_TIME_ZONE_NAMES_H_ +#define CCTZ_TEST_TIME_ZONE_NAMES_H_ + +namespace cctz { + +// A list of known time-zone names. +extern const char* const kTimeZoneNames[]; + +} // namespace cctz + +#endif // CCTZ_TEST_TIME_ZONE_NAMES_H_ diff --git a/src/time_tool.cc b/src/time_tool.cc index 05fbe0efa..31ce2bab4 100644 --- a/src/time_tool.cc +++ b/src/time_tool.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -14,31 +14,33 @@ // A command-line tool for exercising the CCTZ library. -#include #include #include #include #include #include #include +#include #include +#include #include #include +#include -#include "civil_time.h" -#include "time_zone.h" +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" // Pulls in the aliases from cctz for brevity. template using time_point = cctz::time_point; -using sys_seconds = cctz::sys_seconds; +using seconds = cctz::seconds; // parse() specifiers for command-line time arguments. const char* const kFormats[] = { "%Y %m %d %H %M %E*S", - "%Y - %m - %d T %H : %M : %E*S", + "%Y - %m - %d %ET %H : %M : %E*S", "%Y - %m - %d %H : %M : %E*S", - "%Y - %m - %d T %H : %M", + "%Y - %m - %d %ET %H : %M", "%Y - %m - %d %H : %M", "%Y - %m - %d", "%a %b %d %H : %M : %E*S %Z %Y", @@ -57,12 +59,12 @@ const char* const kFormats[] = { nullptr }; -bool ParseTimeSpec(const std::string& args, cctz::time_zone zone, - time_point* when) { - for (const char* const* fmt = kFormats; *fmt != NULL; ++fmt) { - const std::string format = std::string(*fmt) + " %Ez"; - time_point tp; - if (cctz::parse(format, args, zone, &tp)) { +bool ParseTimeSpec(const std::string& args, time_point* when) { + const cctz::time_zone ignored{}; + for (const char* const* fmt = kFormats; *fmt != nullptr; ++fmt) { + const std::string format = std::string(*fmt) + " %E*z"; + time_point tp; + if (cctz::parse(format, args, ignored, &tp)) { *when = tp; return true; } @@ -70,10 +72,10 @@ bool ParseTimeSpec(const std::string& args, cctz::time_zone zone, return false; } -bool ParseBreakdownSpec(const std::string& args, cctz::civil_second* when) { +bool ParseCivilSpec(const std::string& args, cctz::civil_second* when) { const cctz::time_zone utc = cctz::utc_time_zone(); - for (const char* const* fmt = kFormats; *fmt != NULL; ++fmt) { - time_point tp; + for (const char* const* fmt = kFormats; *fmt != nullptr; ++fmt) { + time_point tp; if (cctz::parse(*fmt, args, utc, &tp)) { *when = cctz::convert(tp, utc); return true; @@ -82,9 +84,6 @@ bool ParseBreakdownSpec(const std::string& args, cctz::civil_second* when) { return false; } -// The FormatTime() specifier for output. -const char* const kFormat = "%Y-%m-%d %H:%M:%S %Ez (%Z)"; - const char* WeekDayName(cctz::weekday wd) { switch (wd) { case cctz::weekday::monday: return "Mon"; @@ -98,78 +97,143 @@ const char* WeekDayName(cctz::weekday wd) { return "XXX"; } -std::string FormatTimeInZone(time_point when, +std::string FormatTimeInZone(const std::string& fmt, time_point when, cctz::time_zone zone) { std::ostringstream oss; - oss << std::setw(33) << std::left << cctz::format(kFormat, when, zone); + oss << std::setw(36) << std::left << cctz::format(fmt, when, zone); cctz::time_zone::absolute_lookup al = zone.lookup(when); - cctz::civil_day cd(al.cs); - oss << " [wd=" << WeekDayName(cctz::get_weekday(cd)) + oss << " [wd=" << WeekDayName(cctz::get_weekday(al.cs)) << " yd=" << std::setw(3) << std::setfill('0') - << std::right << cctz::get_yearday(cd) + << std::right << cctz::get_yearday(al.cs) << " dst=" << (al.is_dst ? 'T' : 'F') << " off=" << std::showpos << al.offset << std::noshowpos << "]"; return oss.str(); } -void InstantInfo(const std::string& label, time_point when, - cctz::time_zone zone) { +void ZoneInfo(const std::string& label, cctz::time_zone tz) { + std::string version = tz.version(); + if (version.empty()) version = ""; + std::cout << label << tz.name() << " [ver=" << version << " " + << tz.description() << "]\n"; +} + +void InstantInfo(const std::string& label, const std::string& fmt, + time_point when, cctz::time_zone zone) { + const cctz::time_zone loc = cctz::local_time_zone(); // might == zone const cctz::time_zone utc = cctz::utc_time_zone(); // might == zone const std::string time_label = "time_t"; const std::string utc_label = "UTC"; - const std::string zone_label = "in-tz"; - std::size_t width = - 2 + std::max(std::max(time_label.size(), utc_label.size()), - zone_label.size()); + const std::string loc_label = "local"; + const std::string zone_label = "in-tz"; // perhaps zone.name()? + int width = 2 + static_cast( + std::max(std::max(time_label.size(), utc_label.size()), + std::max(loc_label.size(), zone_label.size()))); std::cout << label << " {\n"; std::cout << std::setw(width) << std::right << time_label << ": "; - std::cout << std::setw(10) << format("%s", when, utc); + std::cout << std::setw(10) << cctz::format("%s", when, utc); std::cout << "\n"; std::cout << std::setw(width) << std::right << utc_label << ": "; - std::cout << FormatTimeInZone(when, utc) << "\n"; + std::cout << FormatTimeInZone(fmt, when, utc) << "\n"; + std::cout << std::setw(width) << std::right << loc_label << ": "; + std::cout << FormatTimeInZone(fmt, when, loc) << "\n"; std::cout << std::setw(width) << std::right << zone_label << ": "; - std::cout << FormatTimeInZone(when, zone) << "\n"; + std::cout << FormatTimeInZone(fmt, when, zone) << "\n"; std::cout << "}\n"; } // Report everything we know about a cctz::civil_second (YMDHMS). -int BreakdownInfo(const cctz::civil_second& cs, cctz::time_zone zone) { +void CivilInfo(const std::string& fmt, const cctz::civil_second cs, + cctz::time_zone zone) { + ZoneInfo("tz: ", zone); cctz::time_zone::civil_lookup cl = zone.lookup(cs); switch (cl.kind) { case cctz::time_zone::civil_lookup::UNIQUE: { std::cout << "kind: UNIQUE\n"; - InstantInfo("when", cl.pre, zone); + InstantInfo("when", fmt, cl.pre, zone); break; } case cctz::time_zone::civil_lookup::SKIPPED: { std::cout << "kind: SKIPPED\n"; - InstantInfo("post", cl.post, zone); // might == trans-1 - InstantInfo("trans-1", cl.trans - std::chrono::seconds(1), zone); - InstantInfo("trans", cl.trans, zone); - InstantInfo("pre", cl.pre, zone); // might == trans + InstantInfo("post", fmt, cl.post, zone); // might == trans-1 + InstantInfo("trans-1", fmt, cl.trans - seconds(1), zone); + InstantInfo("trans", fmt, cl.trans, zone); + InstantInfo("pre", fmt, cl.pre, zone); // might == trans break; } case cctz::time_zone::civil_lookup::REPEATED: { std::cout << "kind: REPEATED\n"; - InstantInfo("pre", cl.pre, zone); // might == trans-1 - InstantInfo("trans-1", cl.trans - std::chrono::seconds(1), zone); - InstantInfo("trans", cl.trans, zone); - InstantInfo("post", cl.post, zone); // might == trans + InstantInfo("pre", fmt, cl.pre, zone); // might == trans-1 + InstantInfo("trans-1", fmt, cl.trans - seconds(1), zone); + InstantInfo("trans", fmt, cl.trans, zone); + InstantInfo("post", fmt, cl.post, zone); // might == trans break; } } - return 0; } -// Report everything we know about a time_point. -int TimeInfo(time_point when, cctz::time_zone zone) { +// Report everything we know about a time_point. +void TimeInfo(const std::string& fmt, time_point when, + cctz::time_zone zone) { + ZoneInfo("tz: ", zone); std::cout << "kind: UNIQUE\n"; - InstantInfo("when", when, zone); - return 0; + InstantInfo("when", fmt, when, zone); +} + +// Report everything we know about a time_zone. +void ZoneDump(bool zdump, const std::string& fmt, cctz::time_zone zone, + cctz::year_t lo_year, cctz::year_t hi_year) { + const cctz::time_zone utc = cctz::utc_time_zone(); + if (zdump) { + std::cout << zone.name() << " " + << std::numeric_limits::min() + << " = NULL\n"; + std::cout << zone.name() << " " + << std::numeric_limits::min() + 86400 + << " = NULL\n"; + } else { + ZoneInfo("", zone); + } + + auto tp = cctz::convert(cctz::civil_second(lo_year, 1, 1, 0, 0, -1), zone); + cctz::time_zone::civil_transition trans; + while (zone.next_transition(tp, &trans)) { + if (trans.from.year() >= hi_year && trans.to.year() >= hi_year) break; + tp = zone.lookup(trans.to).trans; + if (!zdump) std::cout << "\n"; + for (int count_down = 1; count_down >= 0; --count_down) { + auto ttp = tp - seconds(count_down); + if (zdump) { + std::cout << zone.name() << " " << cctz::format("%c UT", ttp, utc) + << " = " << cctz::format("%c %Z", ttp, zone); + } else { + std::cout << std::setw(10) << std::chrono::system_clock::to_time_t(ttp); + std::cout << " = " << cctz::format(fmt, ttp, utc); + std::cout << " = " << cctz::format(fmt, ttp, zone); + } + auto al = zone.lookup(ttp); + if (zdump) { + std::cout << " isdst=" << (al.is_dst ? '1' : '0') + << " gmtoff=" << al.offset << "\n"; + } else { + const char* wd = WeekDayName(get_weekday(al.cs)); + std::cout << " [wd=" << wd << " dst=" << (al.is_dst ? 'T' : 'F') + << " off=" << al.offset << "]\n"; + } + } + } + + if (zdump) { + std::cout << zone.name() << " " + << std::numeric_limits::max() - 86400 + << " = NULL\n"; + std::cout << zone.name() << " " + << std::numeric_limits::max() + << " = NULL\n"; + } } const char* Basename(const char* p) { - if (const char* b = strrchr(p, '/')) return ++b; + if (const char* b = std::strrchr(p, '/')) return ++b; return p; } @@ -184,46 +248,161 @@ bool LooksLikeNegOffset(const char* s) { return false; } -int main(int argc, char** argv) { - std::string prog = argv[0] ? Basename(argv[0]) : "time_tool"; +std::vector StrSplit(char sep, const std::string& s) { + std::vector v; + // An empty string value corresponds to an empty vector, not a vector + // with a single, empty string. + if (!s.empty()) { + std::string::size_type pos = 0; + for (;;) { + std::string::size_type spos = s.find(sep, pos); + if (spos == std::string::npos) break; + v.push_back(s.substr(pos, spos - pos)); + pos = spos + 1; + } + v.push_back(s.substr(pos)); + } + return v; +} + +// Parses [,]. +bool ParseYearRange(bool zdump, const std::string& args, + cctz::year_t* lo_year, cctz::year_t* hi_year) { + std::size_t pos = 0; + std::size_t digit_pos = pos + (args[pos] == '-' ? 1 : 0); + if (digit_pos >= args.size() || !std::isdigit(args[digit_pos])) { + return false; + } + const cctz::year_t first = std::stoll(args, &pos); + if (pos == args.size()) { + *lo_year = (zdump ? -292277022656 : first); + *hi_year = (zdump ? first : first + 1); + return true; + } + if (args[pos] != ' ' || ++pos == args.size()) { + // Any comma was already converted to a space. + return false; + } + digit_pos = pos + (args[pos] == '-' ? 1 : 0); + if (digit_pos >= args.size() || !std::isdigit(args[digit_pos])) { + return false; + } + const std::string rem = args.substr(pos); + const cctz::year_t second = std::stoll(rem, &pos); + if (pos == rem.size()) { + *lo_year = first; + *hi_year = (zdump ? second : second + 1); + return true; + } + return false; +} + +int main(int argc, const char** argv) { + const char* argv0 = (argc > 0) ? (argc--, *argv++) : (argc = 0, "time_tool"); + const std::string prog = Basename(argv0); // Escape arguments that look like negative offsets so that they // don't look like flags. - for (int i = 1; i < argc; ++i) { - if (strcmp(argv[i], "--") == 0) break; + std::vector eargs; + for (int i = 0; i < argc; ++i) { + if (std::strcmp(argv[i], "--") == 0) break; if (LooksLikeNegOffset(argv[i])) { - char* buf = new char[strlen(argv[i] + 2)]; - buf[0] = ' '; // will later be ignorned - strcpy(buf + 1, argv[i]); - argv[i] = buf; + eargs.push_back(" "); // space will later be ignorned + eargs.back().append(argv[i]); + argv[i] = eargs.back().c_str(); } } - // Determine the time zone. - cctz::time_zone zone = cctz::local_time_zone(); - for (;;) { - static option opts[] = { - {"tz", required_argument, nullptr, 'z'}, - {nullptr, 0, nullptr, 0}, - }; - int c = getopt_long(argc, argv, "z:", opts, nullptr); - if (c == -1) break; - switch (c) { - case 'z': - if (!cctz::load_time_zone(optarg, &zone)) { - std::cerr << optarg << ": Unrecognized time zone\n"; - return 1; + // Determine the time zone and other options. + std::string zones = "localtime"; + std::string fmt = "%Y-%m-%d %H:%M:%S %E*z (%Z)"; + bool zone_dump = (prog == "zone_dump"); + bool zdump = false; // Use zdump(8) format. + int optind = 0; + int opterr = 0; + for (; optind < argc && opterr == 0; ++optind) { + const char* opt = argv[optind]; + if (*opt++ != '-') break; + if (*opt != '-') { // short options + while (char c = *opt++) { + if (c == 'z') { + if (*opt != '\0') { + zones = opt; + break; + } + if (optind + 1 == argc) { + std::cerr << argv0 << ": option requires an argument -- 'z'\n"; + ++opterr; + break; + } + zones = argv[++optind]; + } else if (c == 'f') { + if (*opt != '\0') { + fmt = opt; + break; + } + if (optind + 1 == argc) { + std::cerr << argv0 << ": option requires an argument -- 'f'\n"; + ++opterr; + break; + } + fmt = argv[++optind]; + } else if (c == 'D') { + zdump = true; + } else if (c == 'd') { + zone_dump = true; + } else { + std::cerr << argv0 << ": invalid option -- '" << c << "'\n"; + ++opterr; + break; } + } + } else { // long options + if (*++opt == '\0') { // "--" + ++optind; break; - default: - std::cerr << "Usage: " << prog << " [--tz=] []\n"; - return 1; + } + if (std::strcmp(opt, "tz") == 0) { + if (optind + 1 == argc) { + std::cerr << argv0 << ": option '--tz' requires an argument\n"; + ++opterr; + } else { + zones = argv[++optind]; + } + } else if (std::strncmp(opt, "tz=", 3) == 0) { + zones = opt + 3; + } else if (std::strcmp(opt, "fmt") == 0) { + if (optind + 1 == argc) { + std::cerr << argv0 << ": option '--fmt' requires an argument\n"; + ++opterr; + } else { + fmt = argv[++optind]; + } + } else if (std::strncmp(opt, "fmt=", 4) == 0) { + fmt = opt + 4; + } else if (std::strcmp(opt, "zdump") == 0) { + zdump = true; + } else if (std::strcmp(opt, "zone_dump") == 0) { + zone_dump = true; + } else { + std::cerr << argv0 << ": unrecognized option '--" << opt << "'\n"; + ++opterr; + } } } + if (opterr != 0) { + std::cerr << "Usage: " << prog << " [--tz=[,...]] [--fmt=]"; + if (prog == "zone_dump") { + std::cerr << " [[,]|]\n"; + std::cerr << " Default years are last year and next year," + << " respectively.\n"; + } else { + std::cerr << " []\n"; + } + std::cerr << " Default is 'now'.\n"; + return 1; + } - // Determine the time point. - time_point tp = std::chrono::time_point_cast( - std::chrono::system_clock::now()); std::string args; for (int i = optind; i < argc; ++i) { if (i != optind) args += " "; @@ -231,7 +410,11 @@ int main(int argc, char** argv) { } std::replace(args.begin(), args.end(), ',', ' '); std::replace(args.begin(), args.end(), '/', '-'); - bool have_time = ParseTimeSpec(args, zone, &tp); + + // Determine the time point. + time_point tp = + std::chrono::time_point_cast(std::chrono::system_clock::now()); + bool have_time = ParseTimeSpec(args, &tp); if (!have_time && !args.empty()) { std::string spec = args.substr((args[0] == '@') ? 1 : 0); if ((spec.size() > 0 && std::isdigit(spec[0])) || @@ -239,20 +422,49 @@ int main(int argc, char** argv) { std::size_t end; const time_t t = std::stoll(spec, &end); if (end == spec.size()) { - tp = std::chrono::time_point_cast( - std::chrono::system_clock::from_time_t(0)) + - sys_seconds(t); + tp = std::chrono::time_point_cast( + std::chrono::system_clock::from_time_t(t)); have_time = true; } } } - cctz::civil_second when = cctz::convert(tp, zone); - bool have_break_down = !have_time && ParseBreakdownSpec(args, &when); - // Show results. - if (have_break_down) return BreakdownInfo(when, zone); - if (have_time || args.empty()) return TimeInfo(tp, zone); + std::string leader = ""; + for (const std::string& tz : StrSplit(',', zones)) { + std::cout << leader; + cctz::time_zone zone; + if (tz == "localtime") { + zone = cctz::local_time_zone(); + } else if (!cctz::load_time_zone(tz, &zone)) { + std::cerr << tz << ": Unrecognized time zone\n"; + return 1; + } + + cctz::civil_second when = cctz::convert(tp, zone); + bool have_civil = !have_time && ParseCivilSpec(args, &when); - std::cerr << args << ": Malformed time spec\n"; - return 1; + if (zone_dump || zdump) { + cctz::year_t lo_year = (zdump ? -292277026596 : when.year()); + cctz::year_t hi_year = (zdump ? 292277026596 : when.year() + 1); + if (!args.empty() && !ParseYearRange(zdump, args, &lo_year, &hi_year)) { + if (!have_time && !have_civil) { + std::cerr << args << ": Malformed year range\n"; + return 1; + } + } + ZoneDump(zdump, fmt, zone, lo_year, hi_year); + leader = "---\n"; + } else { + if (!have_civil && !have_time && !args.empty()) { + std::cerr << args << ": Malformed time spec\n"; + return 1; + } + if (have_civil) { + CivilInfo(fmt, when, zone); + } else { + TimeInfo(fmt, tp, zone); + } + leader = "\n"; + } + } } diff --git a/src/time_zone_fixed.cc b/src/time_zone_fixed.cc new file mode 100644 index 000000000..f88209b68 --- /dev/null +++ b/src/time_zone_fixed.cc @@ -0,0 +1,134 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "time_zone_fixed.h" + +#include +#include +#include +#include +#include + +namespace cctz { + +namespace { + +// The prefix used for the internal names of fixed-offset zones. +const char kFixedZonePrefix[] = "Fixed/UTC"; + +const char kDigits[] = "0123456789"; + +char* Format02d(char* p, int v) { + *p++ = kDigits[(v / 10) % 10]; + *p++ = kDigits[v % 10]; + return p; +} + +int Parse02d(const char* p) { + if (const char* ap = std::strchr(kDigits, *p)) { + int v = static_cast(ap - kDigits); + if (const char* bp = std::strchr(kDigits, *++p)) { + return (v * 10) + static_cast(bp - kDigits); + } + } + return -1; +} + +} // namespace + +bool FixedOffsetFromName(const std::string& name, seconds* offset) { + if (name == "UTC" || name == "UTC0") { + *offset = seconds::zero(); + return true; + } + + const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; + const char* const ep = kFixedZonePrefix + prefix_len; + if (name.size() != prefix_len + 9) // +99:99:99 + return false; + if (!std::equal(kFixedZonePrefix, ep, name.begin())) + return false; + const char* np = name.data() + prefix_len; + if (np[0] != '+' && np[0] != '-') + return false; + if (np[3] != ':' || np[6] != ':') // see note below about large offsets + return false; + + int hours = Parse02d(np + 1); + if (hours == -1) return false; + int mins = Parse02d(np + 4); + if (mins == -1) return false; + int secs = Parse02d(np + 7); + if (secs == -1) return false; + + secs += ((hours * 60) + mins) * 60; + if (secs > 24 * 60 * 60) return false; // outside supported offset range + *offset = seconds(secs * (np[0] == '-' ? -1 : 1)); // "-" means west + return true; +} + +std::string FixedOffsetToName(const seconds& offset) { + if (offset == seconds::zero()) return "UTC"; + if (offset < std::chrono::hours(-24) || offset > std::chrono::hours(24)) { + // We don't support fixed-offset zones more than 24 hours + // away from UTC to avoid complications in rendering such + // offsets and to (somewhat) limit the total number of zones. + return "UTC"; + } + int offset_seconds = static_cast(offset.count()); + const char sign = (offset_seconds < 0 ? '-' : '+'); + int offset_minutes = offset_seconds / 60; + offset_seconds %= 60; + if (sign == '-') { + if (offset_seconds > 0) { + offset_seconds -= 60; + offset_minutes += 1; + } + offset_seconds = -offset_seconds; + offset_minutes = -offset_minutes; + } + int offset_hours = offset_minutes / 60; + offset_minutes %= 60; + const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; + char buf[prefix_len + sizeof("-24:00:00")]; + char* ep = std::copy_n(kFixedZonePrefix, prefix_len, buf); + *ep++ = sign; + ep = Format02d(ep, offset_hours); + *ep++ = ':'; + ep = Format02d(ep, offset_minutes); + *ep++ = ':'; + ep = Format02d(ep, offset_seconds); + *ep++ = '\0'; + assert(ep == buf + sizeof(buf)); + return buf; +} + +std::string FixedOffsetToAbbr(const seconds& offset) { + std::string abbr = FixedOffsetToName(offset); + const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; + if (abbr.size() == prefix_len + 9) { // +99:99:99 + abbr.erase(0, prefix_len); // +99:99:99 + abbr.erase(6, 1); // +99:9999 + abbr.erase(3, 1); // +999999 + if (abbr[5] == '0' && abbr[6] == '0') { // +999900 + abbr.erase(5, 2); // +9999 + if (abbr[3] == '0' && abbr[4] == '0') { // +9900 + abbr.erase(3, 2); // +99 + } + } + } + return abbr; +} + +} // namespace cctz diff --git a/src/time_zone_fixed.h b/src/time_zone_fixed.h new file mode 100644 index 000000000..f37226ff4 --- /dev/null +++ b/src/time_zone_fixed.h @@ -0,0 +1,45 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CCTZ_TIME_ZONE_FIXED_H_ +#define CCTZ_TIME_ZONE_FIXED_H_ + +#include + +#include "cctz/time_zone.h" + +namespace cctz { + +// Helper functions for dealing with the names and abbreviations +// of time zones that are a fixed offset (seconds east) from UTC. +// FixedOffsetFromName() extracts the offset from a valid fixed-offset +// name, while FixedOffsetToName() and FixedOffsetToAbbr() generate +// the canonical zone name and abbreviation respectively for the given +// offset. +// +// A fixed-offset name looks like "Fixed/UTC<+->::". +// Its abbreviation is of the form "UTC(<+->H?H(MM(SS)?)?)?" where the +// optional pieces are omitted when their values are zero. (Note that +// the sign is the opposite of that used in a POSIX TZ specification.) +// +// Note: FixedOffsetFromName() fails on syntax errors or when the parsed +// offset exceeds 24 hours. FixedOffsetToName() and FixedOffsetToAbbr() +// both produce "UTC" when the argument offset exceeds 24 hours. +bool FixedOffsetFromName(const std::string& name, seconds* offset); +std::string FixedOffsetToName(const seconds& offset); +std::string FixedOffsetToAbbr(const seconds& offset); + +} // namespace cctz + +#endif // CCTZ_TIME_ZONE_FIXED_H_ diff --git a/src/time_zone_format.cc b/src/time_zone_format.cc index 5ef9126cb..7ecfec414 100644 --- a/src/time_zone_format.cc +++ b/src/time_zone_format.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -13,26 +13,41 @@ // limitations under the License. #if !defined(HAS_STRPTIME) -# if !defined(_WIN32) && !defined(_WIN64) -# define HAS_STRPTIME 1 // assume everyone has strptime() except windows +# if defined(_MSC_VER) || defined(__MINGW32__) || defined(__VXWORKS__) +# define HAS_STRPTIME 0 +# else +# define HAS_STRPTIME 1 // Assume everyone else has strptime(). # endif #endif -#include "time_zone.h" -#include "time_zone_if.h" +#if HAS_STRPTIME +# if !defined(_XOPEN_SOURCE) && !defined(__FreeBSD__) && !defined(__OpenBSD__) +# define _XOPEN_SOURCE 500 // Exposes definitions for SUSv2 (UNIX 98). +# endif +#endif + +#include "cctz/time_zone.h" + +// Include time.h directly since, by C++ standards, ctime doesn't have to +// declare strptime. +#include #include #include +#include #include #include #include #include -#include +#include #if !HAS_STRPTIME #include #include #endif +#include "cctz/civil_time.h" +#include "time_zone_if.h" + namespace cctz { namespace detail { @@ -44,10 +59,53 @@ char* strptime(const char* s, const char* fmt, std::tm* tm) { std::istringstream input(s); input >> std::get_time(tm, fmt); if (input.fail()) return nullptr; - return const_cast(s) + input.tellg(); + return const_cast(s) + + (input.eof() ? strlen(s) : static_cast(input.tellg())); } #endif +// Convert a cctz::weekday to a tm_wday value (0-6, Sunday = 0). +int ToTmWday(weekday wd) { + switch (wd) { + case weekday::sunday: + return 0; + case weekday::monday: + return 1; + case weekday::tuesday: + return 2; + case weekday::wednesday: + return 3; + case weekday::thursday: + return 4; + case weekday::friday: + return 5; + case weekday::saturday: + return 6; + } + return 0; /*NOTREACHED*/ +} + +// Convert a tm_wday value (0-6, Sunday = 0) to a cctz::weekday. +weekday FromTmWday(int tm_wday) { + switch (tm_wday) { + case 0: + return weekday::sunday; + case 1: + return weekday::monday; + case 2: + return weekday::tuesday; + case 3: + return weekday::wednesday; + case 4: + return weekday::thursday; + case 5: + return weekday::friday; + case 6: + return weekday::saturday; + } + return weekday::sunday; /*NOTREACHED*/ +} + std::tm ToTM(const time_zone::absolute_lookup& al) { std::tm tm{}; tm.tm_sec = al.cs.second(); @@ -56,7 +114,7 @@ std::tm ToTM(const time_zone::absolute_lookup& al) { tm.tm_mday = al.cs.day(); tm.tm_mon = al.cs.month() - 1; - // Saturate tm.tm_year is cases of over/underflow. + // Saturate tm.tm_year in cases of over/underflow. if (al.cs.year() < std::numeric_limits::min() + 1900) { tm.tm_year = std::numeric_limits::min(); } else if (al.cs.year() - 1900 > std::numeric_limits::max()) { @@ -65,47 +123,32 @@ std::tm ToTM(const time_zone::absolute_lookup& al) { tm.tm_year = static_cast(al.cs.year() - 1900); } - switch (get_weekday(civil_day(al.cs))) { - case weekday::sunday: - tm.tm_wday = 0; - break; - case weekday::monday: - tm.tm_wday = 1; - break; - case weekday::tuesday: - tm.tm_wday = 2; - break; - case weekday::wednesday: - tm.tm_wday = 3; - break; - case weekday::thursday: - tm.tm_wday = 4; - break; - case weekday::friday: - tm.tm_wday = 5; - break; - case weekday::saturday: - tm.tm_wday = 6; - break; - } - tm.tm_yday = get_yearday(civil_day(al.cs)) - 1; + tm.tm_wday = ToTmWday(get_weekday(al.cs)); + tm.tm_yday = get_yearday(al.cs) - 1; tm.tm_isdst = al.is_dst ? 1 : 0; return tm; } +// Returns the week of the year [0:53] given a civil day and the day on +// which weeks are defined to start. +int ToWeek(const civil_day& cd, weekday week_start) { + const civil_day d(cd.year() % 400, cd.month(), cd.day()); + return static_cast((d - prev_weekday(civil_year(d), week_start)) / 7); +} + const char kDigits[] = "0123456789"; // Formats a 64-bit integer in the given field width. Note that it is up // to the caller of Format64() [and Format02d()/FormatOffset()] to ensure // that there is sufficient space before ep to hold the conversion. -char* Format64(char* ep, int width, int64_t v) { +char* Format64(char* ep, int width, std::int_fast64_t v) { bool neg = false; if (v < 0) { --width; neg = true; - if (v == INT64_MIN) { - // Avoid negating INT64_MIN. - int last_digit = -(v % 10); + if (v == std::numeric_limits::min()) { + // Avoid negating minimum value. + std::int_fast64_t last_digit = -(v % 10); v /= 10; if (last_digit < 0) { ++v; @@ -133,37 +176,52 @@ char* Format02d(char* ep, int v) { } // Formats a UTC offset, like +00:00. -char* FormatOffset(char* ep, int minutes, char sep) { +char* FormatOffset(char* ep, int offset, const char* mode) { + // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and + // generate a "negative zero" when we're formatting a zero offset + // as the result of a failed load_time_zone(). char sign = '+'; - if (minutes < 0) { - minutes = -minutes; + if (offset < 0) { + offset = -offset; // bounded by 24h so no overflow sign = '-'; } - ep = Format02d(ep, minutes % 60); - if (sep != '\0') *--ep = sep; - ep = Format02d(ep, minutes / 60); + const int seconds = offset % 60; + const int minutes = (offset /= 60) % 60; + const int hours = offset /= 60; + const char sep = mode[0]; + const bool ext = (sep != '\0' && mode[1] == '*'); + const bool ccc = (ext && mode[2] == ':'); + if (ext && (!ccc || seconds != 0)) { + ep = Format02d(ep, seconds); + *--ep = sep; + } else { + // If we're not rendering seconds, sub-minute negative offsets + // should get a positive sign (e.g., offset=-10s => "+00:00"). + if (hours == 0 && minutes == 0) sign = '+'; + } + if (!ccc || minutes != 0 || seconds != 0) { + ep = Format02d(ep, minutes); + if (sep != '\0') *--ep = sep; + } + ep = Format02d(ep, hours); *--ep = sign; return ep; } // Formats a std::tm using strftime(3). void FormatTM(std::string* out, const std::string& fmt, const std::tm& tm) { - // strftime(3) returns the number of characters placed in the output - // array (which may be 0 characters). It also returns 0 to indicate - // an error, like the array wasn't large enough. To accomodate this, - // the following code grows the buffer size from 2x the format string - // length up to 32x. - for (int i = 2; i != 32; i *= 2) { - size_t buf_size = fmt.size() * i; - std::vector buf(buf_size); - if (size_t len = strftime(&buf[0], buf_size, fmt.c_str(), &tm)) { - out->append(&buf[0], len); - return; - } - } + // We assume that 16 times the length of the format string will + // be sufficient to store the result. The extreme case appears + // to be "%c" (2 chars), which, in the POSIX locale, produces + // "Thu Jan 1 00:00:00 1970" (24 chars). + auto out_size = out->size(); + auto buf_size = (16 * fmt.size()) + 1; + out->resize(out_size + buf_size); + auto len = strftime(&(*out)[out_size], buf_size, fmt.c_str(), &tm); + out->resize(out_size + len); } -// Used for %E#S specifiers and for data values in Parse(). +// Used for %E#S/%E#f specifiers and for data values in parse(). template const char* ParseInt(const char* dp, int width, T min, T max, T* vp) { if (dp != nullptr) { @@ -215,11 +273,12 @@ const char* ParseInt(const char* dp, int width, T min, T max, T* vp) { return dp; } -// The number of base-10 digits that can be represented by an int64_t. -const int kDigits10_64 = std::numeric_limits::digits10; +// The number of base-10 digits that can be represented by a signed 64-bit +// integer. That is, 10^kDigits10_64 <= 2^63 - 1 < 10^(kDigits10_64 + 1). +const int kDigits10_64 = 18; -// 10^n for everything that can be represented by an int64_t. -const int64_t kExp10[kDigits10_64 + 1] = { +// 10^n for everything that can be represented by a signed 64-bit integer. +const std::int_fast64_t kExp10[kDigits10_64 + 1] = { 1, 10, 100, @@ -246,10 +305,12 @@ const int64_t kExp10[kDigits10_64 + 1] = { // Uses strftime(3) to format the given Time. The following extended format // specifiers are also supported: // -// - %Ez - RFC3339-compatible numeric timezone (+hh:mm or -hh:mm) +// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) +// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) // - %E#S - Seconds with # digits of fractional precision // - %E*S - Seconds with full fractional precision (a literal '*') // - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) +// - %ET - The RFC3339 "date-time" separator "T" // // The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are // handled internally for performance reasons. strftime(3) is slow due to @@ -260,14 +321,17 @@ const int64_t kExp10[kDigits10_64 + 1] = { // // We also handle the %z and %Z specifiers to accommodate platforms that do // not support the tm_gmtoff and tm_zone extensions to std::tm. -std::string format(const std::string& format, const time_point& tp, - const std::chrono::nanoseconds& ns, const time_zone& tz) { +// +// Requires that zero() <= fs < seconds(1). +std::string format(const std::string& format, const time_point& tp, + const detail::femtoseconds& fs, const time_zone& tz) { std::string result; + result.reserve(2 * format.size()); // A guess for the result size. const time_zone::absolute_lookup al = tz.lookup(tp); const std::tm tm = ToTM(al); // Scratch buffer for internal conversions. - char buf[3 + kDigits10_64]; // enough for longest conversion + char buf[6 + (kDigits10_64 + 2)]; // enough for longest conversion (%F) char* const ep = buf + sizeof(buf); char* bp; // works back from ep @@ -276,29 +340,35 @@ std::string format(const std::string& format, const time_point& tp, // [pending ... cur) : formatting pending, but no special cases // [cur ... format.end()) : unexamined // Initially, everything is in the unexamined part. - const char* pending = format.c_str(); // NUL terminated + const char* pending = format.data(); const char* cur = pending; - const char* end = pending + format.length(); + const char* const end = pending + format.size(); while (cur != end) { // while something is unexamined // Moves cur to the next percent sign. const char* start = cur; - while (cur != end && *cur != '%') ++cur; + while (cur != end && *cur != '%') { + if (*cur == '\0' && pending != start) { + FormatTM(&result, std::string(pending, cur), tm); + pending = start = cur; + } + ++cur; + } // If the new pending text is all ordinary, copy it out. if (cur != start && pending == start) { - result.append(pending, cur - pending); + result.append(pending, cur); pending = start = cur; } // Span the sequential percent signs. - const char* percent = cur; + const char* const percent = cur; while (cur != end && *cur == '%') ++cur; // If the new pending text is all percents, copy out one // percent for every matched pair, then skip those pairs. if (cur != start && pending == start) { - size_t escaped = (cur - pending) / 2; + std::size_t escaped = static_cast(cur - pending) / 2; result.append(pending, escaped); pending += escaped * 2; // Also copy out a single trailing percent. @@ -311,138 +381,229 @@ std::string format(const std::string& format, const time_point& tp, if (cur == end || (cur - percent) % 2 == 0) continue; // Simple specifiers that we handle ourselves. - if (strchr("YmdeHMSzZs", *cur)) { - if (cur - 1 != pending) { - FormatTM(&result, std::string(pending, cur - 1), tm); - } + if (*cur == '\0' || strchr("YmdeFUuWwHMSTzZs%", *cur)) { + FormatTM(&result, std::string(pending, cur - 1), tm); switch (*cur) { + case '\0': + // Because we allow NULs in the format string, we must give + // some meaning to the "%\0" specifier. We choose the common + // (but undefined) strftime() behavior of echoing unknown + // specifiers. + result.push_back('%'); + result.push_back('\0'); + break; case 'Y': - // This avoids the tm_year overflow problem for %Y, however + // This avoids the tm.tm_year overflow problem for %Y, however // tm.tm_year will still be used by other specifiers like %D. bp = Format64(ep, 0, al.cs.year()); - result.append(bp, ep - bp); + result.append(bp, ep); break; case 'm': bp = Format02d(ep, al.cs.month()); - result.append(bp, ep - bp); + result.append(bp, ep); break; case 'd': case 'e': bp = Format02d(ep, al.cs.day()); if (*cur == 'e' && *bp == '0') *bp = ' '; // for Windows - result.append(bp, ep - bp); + result.append(bp, ep); + break; + case 'F': + bp = Format02d(ep, al.cs.day()); + *--bp = '-'; + bp = Format02d(bp, al.cs.month()); + *--bp = '-'; + bp = Format64(bp, 0, al.cs.year()); + result.append(bp, ep); + break; + case 'U': + bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::sunday)); + result.append(bp, ep); + break; + case 'u': + bp = Format64(ep, 0, tm.tm_wday ? tm.tm_wday : 7); + result.append(bp, ep); + break; + case 'W': + bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::monday)); + result.append(bp, ep); + break; + case 'w': + bp = Format64(ep, 0, tm.tm_wday); + result.append(bp, ep); break; case 'H': bp = Format02d(ep, al.cs.hour()); - result.append(bp, ep - bp); + result.append(bp, ep); break; case 'M': bp = Format02d(ep, al.cs.minute()); - result.append(bp, ep - bp); + result.append(bp, ep); break; case 'S': bp = Format02d(ep, al.cs.second()); - result.append(bp, ep - bp); + result.append(bp, ep); + break; + case 'T': + bp = Format02d(ep, al.cs.second()); + *--bp = ':'; + bp = Format02d(bp, al.cs.minute()); + *--bp = ':'; + bp = Format02d(bp, al.cs.hour()); + result.append(bp, ep); break; case 'z': - bp = FormatOffset(ep, al.offset / 60, '\0'); - result.append(bp, ep - bp); + bp = FormatOffset(ep, al.offset, ""); + result.append(bp, ep); break; case 'Z': result.append(al.abbr); break; case 's': bp = Format64(ep, 0, ToUnixSeconds(tp)); - result.append(bp, ep - bp); + result.append(bp, ep); + break; + case '%': + result.push_back('%'); break; } pending = ++cur; continue; } + // More complex specifiers that we handle ourselves. + if (*cur == ':' && cur + 1 != end) { + if (*(cur + 1) == 'z') { + // Formats %:z. + FormatTM(&result, std::string(pending, cur - 1), tm); + bp = FormatOffset(ep, al.offset, ":"); + result.append(bp, ep); + pending = cur += 2; + continue; + } + if (*(cur + 1) == ':' && cur + 2 != end) { + if (*(cur + 2) == 'z') { + // Formats %::z. + FormatTM(&result, std::string(pending, cur - 1), tm); + bp = FormatOffset(ep, al.offset, ":*"); + result.append(bp, ep); + pending = cur += 3; + continue; + } + if (*(cur + 2) == ':' && cur + 3 != end) { + if (*(cur + 3) == 'z') { + // Formats %:::z. + FormatTM(&result, std::string(pending, cur - 1), tm); + bp = FormatOffset(ep, al.offset, ":*:"); + result.append(bp, ep); + pending = cur += 4; + continue; + } + } + } + } + // Loop if there is no E modifier. if (*cur != 'E' || ++cur == end) continue; // Format our extensions. - if (*cur == 'z') { + if (*cur == 'T') { + // Formats %ET. + FormatTM(&result, std::string(pending, cur - 2), tm); + result.append("T"); + pending = ++cur; + } else if (*cur == 'z') { // Formats %Ez. - if (cur - 2 != pending) { - FormatTM(&result, std::string(pending, cur - 2), tm); - } - bp = FormatOffset(ep, al.offset / 60, ':'); - result.append(bp, ep - bp); + FormatTM(&result, std::string(pending, cur - 2), tm); + bp = FormatOffset(ep, al.offset, ":"); + result.append(bp, ep); pending = ++cur; - } else if (*cur == '*' && cur + 1 != end && *(cur + 1) == 'S') { - // Formats %E*S. - if (cur - 2 != pending) { - FormatTM(&result, std::string(pending, cur - 2), tm); - } + } else if (*cur == '*' && cur + 1 != end && *(cur + 1) == 'z') { + // Formats %E*z. + FormatTM(&result, std::string(pending, cur - 2), tm); + bp = FormatOffset(ep, al.offset, ":*"); + result.append(bp, ep); + pending = cur += 2; + } else if (*cur == '*' && cur + 1 != end && + (*(cur + 1) == 'S' || *(cur + 1) == 'f')) { + // Formats %E*S or %E*F. + FormatTM(&result, std::string(pending, cur - 2), tm); char* cp = ep; - bp = Format64(cp, 9, ns.count()); + bp = Format64(cp, 15, fs.count()); while (cp != bp && cp[-1] == '0') --cp; - if (cp != bp) *--bp = '.'; - bp = Format02d(bp, al.cs.second()); - result.append(bp, cp - bp); + switch (*(cur + 1)) { + case 'S': + if (cp != bp) *--bp = '.'; + bp = Format02d(bp, al.cs.second()); + break; + case 'f': + if (cp == bp) *--bp = '0'; + break; + } + result.append(bp, cp); pending = cur += 2; } else if (*cur == '4' && cur + 1 != end && *(cur + 1) == 'Y') { // Formats %E4Y. - if (cur - 2 != pending) { - FormatTM(&result, std::string(pending, cur - 2), tm); - } + FormatTM(&result, std::string(pending, cur - 2), tm); bp = Format64(ep, 4, al.cs.year()); - result.append(bp, ep - bp); + result.append(bp, ep); pending = cur += 2; } else if (std::isdigit(*cur)) { - // Possibly found %E#S. + // Possibly found %E#S or %E#f. int n = 0; if (const char* np = ParseInt(cur, 0, 0, 1024, &n)) { - if (*np++ == 'S') { - // Formats %E#S. - if (cur - 2 != pending) { - FormatTM(&result, std::string(pending, cur - 2), tm); - } + if (*np == 'S' || *np == 'f') { + // Formats %E#S or %E#f. + FormatTM(&result, std::string(pending, cur - 2), tm); bp = ep; if (n > 0) { if (n > kDigits10_64) n = kDigits10_64; - bp = Format64(bp, n, (n > 9) ? ns.count() * kExp10[n - 9] - : ns.count() / kExp10[9 - n]); - *--bp = '.'; + bp = Format64(bp, n, (n > 15) ? fs.count() * kExp10[n - 15] + : fs.count() / kExp10[15 - n]); + if (*np == 'S') *--bp = '.'; } - bp = Format02d(bp, al.cs.second()); - result.append(bp, ep - bp); - pending = cur = np; + if (*np == 'S') bp = Format02d(bp, al.cs.second()); + result.append(bp, ep); + pending = cur = ++np; } } } } // Formats any remaining data. - if (end != pending) { - FormatTM(&result, std::string(pending, end), tm); - } + FormatTM(&result, std::string(pending, end), tm); return result; } namespace { -const char* ParseOffset(const char* dp, char sep, int* offset) { +const char* ParseOffset(const char* dp, const char* mode, int* offset) { if (dp != nullptr) { - const char sign = *dp++; - if (sign == '+' || sign == '-') { + const char first = *dp++; + if (first == '+' || first == '-') { + char sep = mode[0]; int hours = 0; + int minutes = 0; + int seconds = 0; const char* ap = ParseInt(dp, 2, 0, 23, &hours); if (ap != nullptr && ap - dp == 2) { dp = ap; if (sep != '\0' && *ap == sep) ++ap; - int minutes = 0; const char* bp = ParseInt(ap, 2, 0, 59, &minutes); - if (bp != nullptr && bp - ap == 2) dp = bp; - *offset = (hours * 60 + minutes) * 60; - if (sign == '-') *offset = -*offset; + if (bp != nullptr && bp - ap == 2) { + dp = bp; + if (sep != '\0' && *bp == sep) ++bp; + const char* cp = ParseInt(bp, 2, 0, 59, &seconds); + if (cp != nullptr && cp - bp == 2) dp = cp; + } + *offset = ((hours * 60 + minutes) * 60) + seconds; + if (first == '-') *offset = -*offset; } else { dp = nullptr; } + } else if (first == 'Z' || first == 'z') { // Zulu + *offset = 0; } else { dp = nullptr; } @@ -459,29 +620,26 @@ const char* ParseZone(const char* dp, std::string* zone) { return dp; } -const char* ParseSubSeconds(const char* dp, - std::chrono::nanoseconds* subseconds) { +const char* ParseSubSeconds(const char* dp, detail::femtoseconds* subseconds) { if (dp != nullptr) { - if (*dp == '.') { - int64_t v = 0; - int64_t exp = 0; - const char* const bp = ++dp; - while (const char* cp = strchr(kDigits, *dp)) { - int d = static_cast(cp - kDigits); - if (d >= 10) break; - if (exp < 9) { - exp += 1; - v *= 10; - v += d; - } - ++dp; - } - if (dp != bp) { - v *= kExp10[9 - exp]; - *subseconds = std::chrono::nanoseconds(v); - } else { - dp = nullptr; + std::int_fast64_t v = 0; + std::int_fast64_t exp = 0; + const char* const bp = dp; + while (const char* cp = strchr(kDigits, *dp)) { + int d = static_cast(cp - kDigits); + if (d >= 10) break; + if (exp < 15) { + exp += 1; + v *= 10; + v += d; } + ++dp; + } + if (dp != bp) { + v *= kExp10[15 - exp]; + *subseconds = detail::femtoseconds(v); + } else { + dp = nullptr; } } return dp; @@ -495,11 +653,32 @@ const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) { return dp; } +// Sets year, tm_mon and tm_mday given the year, week_num, and tm_wday, +// and the day on which weeks are defined to start. Returns false if year +// would need to move outside its bounds. +bool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) { + const civil_year y(*year % 400); + civil_day cd = prev_weekday(y, week_start); // week 0 + cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7); + if (const year_t shift = cd.year() - y.year()) { + if (shift > 0) { + if (*year > std::numeric_limits::max() - shift) return false; + } else { + if (*year < std::numeric_limits::min() - shift) return false; + } + *year += shift; + } + tm->tm_mon = cd.month() - 1; + tm->tm_mday = cd.day(); + return true; +} + } // namespace // Uses strptime(3) to parse the given input. Supports the same extended // format specifiers as format(), although %E#S and %E*S are treated -// identically. +// identically (and similarly for %E#f and %E*f). %Ez and %E*z also accept +// the same inputs. %ET accepts either 'T' or 't'. // // The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are // handled internally so that we can normally avoid strptime() altogether @@ -511,18 +690,24 @@ const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) { // We also handle the %z specifier to accommodate platforms that do not // support the tm_gmtoff extension to std::tm. %Z is parsed but ignored. bool parse(const std::string& format, const std::string& input, - const time_zone& tz, time_point* tpp, - std::chrono::nanoseconds* ns) { - // The unparsed input. + const time_zone& tz, time_point* sec, + detail::femtoseconds* fs, std::string* err) { + // The unparsed input. Even though we allow NULs in input, and + // match them against corresponding NULs in format, we depend on + // *edata being a NUL so that we can call strptime(). This also + // makes our handling of input easier. const char* data = input.c_str(); // NUL terminated + const char* const edata = data + input.size(); // Skips leading whitespace. while (std::isspace(*data)) ++data; - const int kintmax = std::numeric_limits::max(); - const int kintmin = std::numeric_limits::min(); + const year_t kyearmax = std::numeric_limits::max(); + const year_t kyearmin = std::numeric_limits::min(); // Sets default values for unspecified fields. + bool saw_year = false; + year_t year = 1970; std::tm tm{}; tm.tm_year = 1970 - 1900; tm.tm_mon = 1 - 1; // Jan @@ -533,19 +718,26 @@ bool parse(const std::string& format, const std::string& input, tm.tm_wday = 4; // Thu tm.tm_yday = 0; tm.tm_isdst = 0; - auto subseconds = std::chrono::nanoseconds(0); - int offset = kintmin; + auto subseconds = detail::femtoseconds::zero(); + bool saw_offset = false; + int offset = 0; // No offset from passed tz. std::string zone = "UTC"; + // Even though we allow NULs in format, and match them against + // corresponding NULs in input, we simplify its handling by also + // ensuring that *efmt is a NUL. const char* fmt = format.c_str(); // NUL terminated + const char* const efmt = fmt + format.size(); bool twelve_hour = false; bool afternoon = false; + int week_num = -1; + weekday week_start = weekday::sunday; bool saw_percent_s = false; - int64_t percent_s_time = 0; + std::int_fast64_t percent_s = 0; // Steps through format, one specifier at a time. - while (data != nullptr && *fmt != '\0') { + while (data != nullptr && fmt != efmt) { if (std::isspace(*fmt)) { while (std::isspace(*data)) ++data; while (std::isspace(*++fmt)) continue; @@ -553,7 +745,7 @@ bool parse(const std::string& format, const std::string& input, } if (*fmt != '%') { - if (*data == *fmt) { + if (data != edata && *data == *fmt) { ++data; ++fmt; } else { @@ -562,25 +754,64 @@ bool parse(const std::string& format, const std::string& input, continue; } - const char* percent = fmt; - if (*++fmt == '\0') { + const char* const percent = fmt; + if (++fmt == efmt) { data = nullptr; continue; } switch (*fmt++) { + case '\0': + // Because we allow NULs in the format string, we must give + // some meaning to the "%\0" specifier. We choose the common + // (but undefined) strptime() behavior of failing on unknown + // specifiers. + data = nullptr; + continue; case 'Y': - // We're more liberal than the 4-digit year typically handled by - // strptime(), but we still need to store the result in an int, - // and the intermediate value has a 1900 excess. - data = ParseInt(data, 0, kintmin + 1900, kintmax, &tm.tm_year); - if (data != nullptr) tm.tm_year -= 1900; + // Symmetrically with format(), directly handing %Y avoids the + // tm.tm_year overflow problem. However, tm.tm_year will still be + // used by other specifiers like %D. + data = ParseInt(data, 0, kyearmin, kyearmax, &year); + if (data != nullptr) saw_year = true; continue; case 'm': data = ParseInt(data, 2, 1, 12, &tm.tm_mon); if (data != nullptr) tm.tm_mon -= 1; + week_num = -1; continue; case 'd': + case 'e': data = ParseInt(data, 2, 1, 31, &tm.tm_mday); + week_num = -1; + continue; + case 'F': + data = ParseInt(data, 0, kyearmin, kyearmax, &year); + if (data != nullptr) { + saw_year = true; + data = (*data == '-' ? data + 1 : nullptr); + } + data = ParseInt(data, 2, 1, 12, &tm.tm_mon); + if (data != nullptr) { + tm.tm_mon -= 1; + data = (*data == '-' ? data + 1 : nullptr); + } + data = ParseInt(data, 2, 1, 31, &tm.tm_mday); + week_num = -1; + continue; + case 'U': + data = ParseInt(data, 0, 0, 53, &week_num); + week_start = weekday::sunday; + continue; + case 'W': + data = ParseInt(data, 0, 0, 53, &week_num); + week_start = weekday::monday; + continue; + case 'u': + data = ParseInt(data, 0, 1, 7, &tm.tm_wday); + if (data != nullptr) tm.tm_wday %= 7; + continue; + case 'w': + data = ParseInt(data, 0, 0, 6, &tm.tm_wday); continue; case 'H': data = ParseInt(data, 2, 0, 23, &tm.tm_hour); @@ -592,50 +823,88 @@ bool parse(const std::string& format, const std::string& input, case 'S': data = ParseInt(data, 2, 0, 60, &tm.tm_sec); continue; + case 'T': + data = ParseInt(data, 2, 0, 23, &tm.tm_hour); + twelve_hour = false; + data = (data != nullptr && *data == ':' ? data + 1 : nullptr); + data = ParseInt(data, 2, 0, 59, &tm.tm_min); + data = (data != nullptr && *data == ':' ? data + 1 : nullptr); + data = ParseInt(data, 2, 0, 60, &tm.tm_sec); + continue; case 'I': case 'l': case 'r': // probably uses %I twelve_hour = true; break; case 'R': // uses %H - case 'T': // uses %H case 'c': // probably uses %H case 'X': // probably uses %H twelve_hour = false; break; case 'z': - data = ParseOffset(data, '\0', &offset); + data = ParseOffset(data, "", &offset); + if (data != nullptr) saw_offset = true; continue; case 'Z': // ignored; zone abbreviations are ambiguous data = ParseZone(data, &zone); continue; case 's': - data = ParseInt(data, 0, INT64_MIN, INT64_MAX, &percent_s_time); + data = ParseInt(data, 0, + std::numeric_limits::min(), + std::numeric_limits::max(), + &percent_s); if (data != nullptr) saw_percent_s = true; continue; + case ':': + if (fmt[0] == 'z' || + (fmt[0] == ':' && + (fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) { + data = ParseOffset(data, ":", &offset); + if (data != nullptr) saw_offset = true; + fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3; + continue; + } + break; + case '%': + data = (*data == '%' ? data + 1 : nullptr); + continue; case 'E': - if (*fmt == 'z') { - if (data != nullptr && *data == 'Z') { // Zulu - offset = 0; - data += 1; + if (fmt[0] == 'T') { + if (*data == 'T' || *data == 't') { + ++data; + ++fmt; } else { - data = ParseOffset(data, ':', &offset); + data = nullptr; } - fmt += 1; continue; } - if (*fmt == '*' && *(fmt + 1) == 'S') { + if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) { + data = ParseOffset(data, ":", &offset); + if (data != nullptr) saw_offset = true; + fmt += (fmt[0] == 'z') ? 1 : 2; + continue; + } + if (fmt[0] == '*' && fmt[1] == 'S') { data = ParseInt(data, 2, 0, 60, &tm.tm_sec); - data = ParseSubSeconds(data, &subseconds); + if (data != nullptr && *data == '.') { + data = ParseSubSeconds(data + 1, &subseconds); + } fmt += 2; continue; } - if (*fmt == '4' && *(fmt + 1) == 'Y') { + if (fmt[0] == '*' && fmt[1] == 'f') { + if (data != nullptr && std::isdigit(*data)) { + data = ParseSubSeconds(data, &subseconds); + } + fmt += 2; + continue; + } + if (fmt[0] == '4' && fmt[1] == 'Y') { const char* bp = data; - data = ParseInt(data, 4, -999, 9999, &tm.tm_year); + data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year); if (data != nullptr) { if (data - bp == 4) { - tm.tm_year -= 1900; + saw_year = true; } else { data = nullptr; // stopped too soon } @@ -644,14 +913,21 @@ bool parse(const std::string& format, const std::string& input, continue; } if (std::isdigit(*fmt)) { - int n = 0; + int n = 0; // value ignored if (const char* np = ParseInt(fmt, 0, 0, 1024, &n)) { - if (*np++ == 'S') { + if (*np == 'S') { data = ParseInt(data, 2, 0, 60, &tm.tm_sec); - if (n > 0) { // n is otherwise ignored + if (data != nullptr && *data == '.') { + data = ParseSubSeconds(data + 1, &subseconds); + } + fmt = ++np; + continue; + } + if (*np == 'f') { + if (data != nullptr && std::isdigit(*data)) { data = ParseSubSeconds(data, &subseconds); } - fmt = np; + fmt = ++np; continue; } } @@ -668,19 +944,19 @@ bool parse(const std::string& format, const std::string& input, } // Parses the current specifier. - const char* orig_data = data; - std::string spec(percent, fmt - percent); + const char* const orig_data = data; + std::string spec(percent, fmt); data = ParseTM(data, spec.c_str(), &tm); // If we successfully parsed %p we need to remember whether the result - // was AM or PM so that we can adjust tm_hour before ConvertDateTime(). + // was AM or PM so that we can adjust tm_hour before time_zone::lookup(). // So reparse the input with a known AM hour, and check if it is shifted // to a PM hour. if (spec == "%p" && data != nullptr) { - std::string test_input = "1" + std::string(orig_data, data - orig_data); - const char* test_data = test_input.c_str(); + std::string test_input = "1"; + test_input.append(orig_data, data); std::tm tmp{}; - ParseTM(test_data, "%I%p", &tmp); + ParseTM(test_input.c_str(), "%I%p", &tmp); afternoon = (tmp.tm_hour == 13); } } @@ -690,59 +966,95 @@ bool parse(const std::string& format, const std::string& input, tm.tm_hour += 12; } - if (data == nullptr) return false; + if (data == nullptr) { + if (err != nullptr) *err = "Failed to parse input"; + return false; + } // Skip any remaining whitespace. while (std::isspace(*data)) ++data; - // Parse() must consume the entire input string. - if (*data != '\0') return false; + // parse() must consume the entire input string. + if (data != edata) { + if (err != nullptr) *err = "Illegal trailing data in input string"; + return false; + } // If we saw %s then we ignore anything else and return that time. if (saw_percent_s) { - *tpp = FromUnixSeconds(percent_s_time); - *ns = std::chrono::nanoseconds::zero(); + *sec = FromUnixSeconds(percent_s); + *fs = detail::femtoseconds::zero(); return true; } - // If we saw %z or %Ez then we want to interpret the parsed fields in - // UTC and then shift by that offset. Otherwise we want to interpret + // If we saw %z, %Ez, or %E*z then we want to interpret the parsed fields + // in UTC and then shift by that offset. Otherwise we want to interpret // the fields directly in the passed time_zone. - time_zone ptz = tz; - if (offset != kintmin) { - ptz = utc_time_zone(); // Override tz. Offset applied later. - } else { - offset = 0; // No offset from passed tz. - } + time_zone ptz = saw_offset ? utc_time_zone() : tz; // Allows a leap second of 60 to normalize forward to the following ":00". if (tm.tm_sec == 60) { tm.tm_sec -= 1; offset -= 1; - subseconds = std::chrono::nanoseconds::zero(); + subseconds = detail::femtoseconds::zero(); } - int64_t year = tm.tm_year; - if (year > INT64_MAX - 1900) { - year = INT64_MAX; - } else { + if (!saw_year) { + year = year_t{tm.tm_year}; + if (year > kyearmax - 1900) { + // Platform-dependent, maybe unreachable. + if (err != nullptr) *err = "Out-of-range year"; + return false; + } year += 1900; } - // TODO: Eliminate extra normalization. - const civil_second cs(year, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); + // Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number. + if (week_num != -1) { + if (!FromWeek(week_num, week_start, &year, &tm)) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + } + + const int month = tm.tm_mon + 1; + civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); - // Parse() fails if any normalization was done. That is, - // parsing "Sep 31" will not produce the equivalent of "Oct 1". - if (cs.year() != year || cs.month() != tm.tm_mon + 1 || - cs.day() != tm.tm_mday || cs.hour() != tm.tm_hour || - cs.minute() != tm.tm_min || cs.second() != tm.tm_sec) { + // parse() should not allow normalization. Due to the restricted field + // ranges above (see ParseInt()), the only possibility is for days to roll + // into months. That is, parsing "Sep 31" should not produce "Oct 1". + if (cs.month() != month || cs.day() != tm.tm_mday) { + if (err != nullptr) *err = "Out-of-range field"; return false; } - *tpp = ptz.lookup(cs).pre - sys_seconds(offset); - *ns = subseconds; + // Accounts for the offset adjustment before converting to absolute time. + if ((offset < 0 && cs > civil_second::max() + offset) || + (offset > 0 && cs < civil_second::min() + offset)) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + cs -= offset; + + const auto tp = ptz.lookup(cs).pre; + // Checks for overflow/underflow and returns an error as necessary. + if (tp == time_point::max()) { + const auto al = ptz.lookup(time_point::max()); + if (cs > al.cs) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + } + if (tp == time_point::min()) { + const auto al = ptz.lookup(time_point::min()); + if (cs < al.cs) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + } + + *sec = tp; + *fs = subseconds; return true; } diff --git a/src/time_zone_format_test.cc b/src/time_zone_format_test.cc index 7f7338cb9..cfbe161cf 100644 --- a/src/time_zone_format_test.cc +++ b/src/time_zone_format_test.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,25 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "time_zone.h" +#include "cctz/time_zone.h" #include #include #include #include #include +#if defined(__linux__) +#include +#endif +#include "cctz/civil_time.h" #include "gmock/gmock.h" #include "gtest/gtest.h" -using std::chrono::system_clock; -using std::chrono::nanoseconds; -using std::chrono::microseconds; -using std::chrono::milliseconds; -using std::chrono::seconds; -using std::chrono::minutes; -using std::chrono::hours; -using testing::HasSubstr; +namespace chrono = std::chrono; namespace cctz { @@ -49,11 +46,11 @@ namespace { EXPECT_EQ(ss, al.cs.second()); \ EXPECT_EQ(off, al.offset); \ EXPECT_TRUE(isdst == al.is_dst); \ - EXPECT_EQ(zone, al.abbr); \ + EXPECT_STREQ(zone, al.abbr); \ } while (0) -const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez"; -const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez"; +const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez"; +const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez"; const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z"; const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z"; @@ -63,10 +60,10 @@ const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z"; template void TestFormatSpecifier(time_point tp, time_zone tz, const std::string& fmt, const std::string& ans) { - EXPECT_EQ(ans, format(fmt, tp, tz)) << fmt; - EXPECT_EQ("xxx " + ans, format("xxx " + fmt, tp, tz)); - EXPECT_EQ(ans + " yyy", format(fmt + " yyy", tp, tz)); - EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz)); + EXPECT_EQ(ans, cctz::format(fmt, tp, tz)) << fmt; + EXPECT_EQ("xxx " + ans, cctz::format("xxx " + fmt, tp, tz)); + EXPECT_EQ(ans + " yyy", cctz::format(fmt + " yyy", tp, tz)); + EXPECT_EQ("xxx " + ans + " yyy", cctz::format("xxx " + fmt + " yyy", tp, tz)); } } // namespace @@ -76,69 +73,107 @@ void TestFormatSpecifier(time_point tp, time_zone tz, const std::string& fmt, // TEST(Format, TimePointResolution) { - using std::chrono::time_point_cast; const char kFmt[] = "%H:%M:%E*S"; const time_zone utc = utc_time_zone(); - const time_point t0 = - system_clock::from_time_t(1420167845) + std::chrono::milliseconds(123) + - std::chrono::microseconds(456) + std::chrono::nanoseconds(789); + const time_point t0 = + chrono::system_clock::from_time_t(1420167845) + + chrono::milliseconds(123) + chrono::microseconds(456) + + chrono::nanoseconds(789); EXPECT_EQ("03:04:05.123456789", - format(kFmt, time_point_cast(t0), utc)); + cctz::format(kFmt, chrono::time_point_cast(t0), + utc)); EXPECT_EQ("03:04:05.123456", - format(kFmt, time_point_cast(t0), utc)); + cctz::format( + kFmt, chrono::time_point_cast(t0), utc)); EXPECT_EQ("03:04:05.123", - format(kFmt, time_point_cast(t0), utc)); - EXPECT_EQ("03:04:05", - format(kFmt, time_point_cast(t0), utc)); - EXPECT_EQ("03:04:05", - format(kFmt, time_point_cast(t0), utc)); - EXPECT_EQ("03:04:00", - format(kFmt, time_point_cast(t0), utc)); - EXPECT_EQ("03:00:00", - format(kFmt, time_point_cast(t0), utc)); + cctz::format( + kFmt, chrono::time_point_cast(t0), utc)); + EXPECT_EQ( + "03:04:05", + cctz::format(kFmt, chrono::time_point_cast(t0), utc)); + EXPECT_EQ( + "03:04:05", + cctz::format(kFmt, chrono::time_point_cast(t0), utc)); + EXPECT_EQ( + "03:04:00", + cctz::format(kFmt, chrono::time_point_cast(t0), utc)); + EXPECT_EQ( + "03:00:00", + cctz::format(kFmt, chrono::time_point_cast(t0), utc)); +} + +TEST(Format, TimePointExtendedResolution) { + const char kFmt[] = "%H:%M:%E*S"; + const time_zone utc = utc_time_zone(); + const time_point tp = + chrono::time_point_cast( + chrono::system_clock::from_time_t(0)) + + chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56); + + EXPECT_EQ( + "12:34:56.123456789012345", + detail::format(kFmt, tp, detail::femtoseconds(123456789012345), utc)); + EXPECT_EQ( + "12:34:56.012345678901234", + detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc)); + EXPECT_EQ( + "12:34:56.001234567890123", + detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc)); + EXPECT_EQ( + "12:34:56.000123456789012", + detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc)); + + EXPECT_EQ("12:34:56.000000000000123", + detail::format(kFmt, tp, detail::femtoseconds(123), utc)); + EXPECT_EQ("12:34:56.000000000000012", + detail::format(kFmt, tp, detail::femtoseconds(12), utc)); + EXPECT_EQ("12:34:56.000000000000001", + detail::format(kFmt, tp, detail::femtoseconds(1), utc)); } TEST(Format, Basics) { time_zone tz = utc_time_zone(); - time_point tp = system_clock::from_time_t(0); + time_point tp = chrono::system_clock::from_time_t(0); - // Starts with a couple basic edge cases. - EXPECT_EQ("", format("", tp, tz)); - EXPECT_EQ(" ", format(" ", tp, tz)); - EXPECT_EQ(" ", format(" ", tp, tz)); - EXPECT_EQ("xxx", format("xxx", tp, tz)); + // Start with basic edge cases. + EXPECT_EQ("", cctz::format("", tp, tz)); + EXPECT_EQ(" ", cctz::format(" ", tp, tz)); + EXPECT_EQ(" ", cctz::format(" ", tp, tz)); + EXPECT_EQ("xxx", cctz::format("xxx", tp, tz)); std::string big(128, 'x'); - EXPECT_EQ(big, format(big, tp, tz)); + EXPECT_EQ(big, cctz::format(big, tp, tz)); // Cause the 1024-byte buffer to grow. std::string bigger(100000, 'x'); - EXPECT_EQ(bigger, format(bigger, tp, tz)); - - tp += hours(13) + minutes(4) + seconds(5); - tp += milliseconds(6) + microseconds(7) + nanoseconds(8); - EXPECT_EQ("1970-01-01", format("%Y-%m-%d", tp, tz)); - EXPECT_EQ("13:04:05", format("%H:%M:%S", tp, tz)); - EXPECT_EQ("13:04:05.006", format("%H:%M:%E3S", tp, tz)); - EXPECT_EQ("13:04:05.006007", format("%H:%M:%E6S", tp, tz)); - EXPECT_EQ("13:04:05.006007008", format("%H:%M:%E9S", tp, tz)); + EXPECT_EQ(bigger, cctz::format(bigger, tp, tz)); + + tp += chrono::hours(13) + chrono::minutes(4) + chrono::seconds(5); + tp += chrono::milliseconds(6) + chrono::microseconds(7) + + chrono::nanoseconds(8); + EXPECT_EQ("1970-01-01", cctz::format("%Y-%m-%d", tp, tz)); + EXPECT_EQ("13:04:05", cctz::format("%H:%M:%S", tp, tz)); + EXPECT_EQ("13:04:05.006", cctz::format("%H:%M:%E3S", tp, tz)); + EXPECT_EQ("13:04:05.006007", cctz::format("%H:%M:%E6S", tp, tz)); + EXPECT_EQ("13:04:05.006007008", cctz::format("%H:%M:%E9S", tp, tz)); } TEST(Format, PosixConversions) { const time_zone tz = utc_time_zone(); - auto tp = system_clock::from_time_t(0); + auto tp = + chrono::system_clock::from_time_t(308189482); // 1979-10-08T00:11:22Z - TestFormatSpecifier(tp, tz, "%d", "01"); - TestFormatSpecifier(tp, tz, "%e", " 1"); // extension but internal support + TestFormatSpecifier(tp, tz, "%d", "08"); + TestFormatSpecifier(tp, tz, "%e", " 8"); // extension but internal support TestFormatSpecifier(tp, tz, "%H", "00"); TestFormatSpecifier(tp, tz, "%I", "12"); - TestFormatSpecifier(tp, tz, "%j", "001"); - TestFormatSpecifier(tp, tz, "%m", "01"); - TestFormatSpecifier(tp, tz, "%M", "00"); - TestFormatSpecifier(tp, tz, "%S", "00"); - TestFormatSpecifier(tp, tz, "%U", "00"); - TestFormatSpecifier(tp, tz, "%w", "4"); // 4=Thursday - TestFormatSpecifier(tp, tz, "%W", "00"); - TestFormatSpecifier(tp, tz, "%y", "70"); - TestFormatSpecifier(tp, tz, "%Y", "1970"); + TestFormatSpecifier(tp, tz, "%j", "281"); + TestFormatSpecifier(tp, tz, "%m", "10"); + TestFormatSpecifier(tp, tz, "%M", "11"); + TestFormatSpecifier(tp, tz, "%S", "22"); + TestFormatSpecifier(tp, tz, "%U", "40"); + TestFormatSpecifier(tp, tz, "%w", "1"); // 1=Monday + TestFormatSpecifier(tp, tz, "%W", "41"); + TestFormatSpecifier(tp, tz, "%y", "79"); + TestFormatSpecifier(tp, tz, "%Y", "1979"); TestFormatSpecifier(tp, tz, "%z", "+0000"); TestFormatSpecifier(tp, tz, "%Z", "UTC"); TestFormatSpecifier(tp, tz, "%%", "%"); @@ -146,25 +181,27 @@ TEST(Format, PosixConversions) { #if defined(__linux__) // SU/C99/TZ extensions TestFormatSpecifier(tp, tz, "%C", "19"); - TestFormatSpecifier(tp, tz, "%D", "01/01/70"); - TestFormatSpecifier(tp, tz, "%F", "1970-01-01"); - TestFormatSpecifier(tp, tz, "%g", "70"); - TestFormatSpecifier(tp, tz, "%G", "1970"); + TestFormatSpecifier(tp, tz, "%D", "10/08/79"); + TestFormatSpecifier(tp, tz, "%F", "1979-10-08"); + TestFormatSpecifier(tp, tz, "%g", "79"); + TestFormatSpecifier(tp, tz, "%G", "1979"); +#if defined(__GLIBC__) TestFormatSpecifier(tp, tz, "%k", " 0"); TestFormatSpecifier(tp, tz, "%l", "12"); +#endif TestFormatSpecifier(tp, tz, "%n", "\n"); - TestFormatSpecifier(tp, tz, "%R", "00:00"); + TestFormatSpecifier(tp, tz, "%R", "00:11"); TestFormatSpecifier(tp, tz, "%t", "\t"); - TestFormatSpecifier(tp, tz, "%T", "00:00:00"); - TestFormatSpecifier(tp, tz, "%u", "4"); // 4=Thursday - TestFormatSpecifier(tp, tz, "%V", "01"); - TestFormatSpecifier(tp, tz, "%s", "0"); + TestFormatSpecifier(tp, tz, "%T", "00:11:22"); + TestFormatSpecifier(tp, tz, "%u", "1"); // 1=Monday + TestFormatSpecifier(tp, tz, "%V", "41"); + TestFormatSpecifier(tp, tz, "%s", "308189482"); #endif } TEST(Format, LocaleSpecific) { const time_zone tz = utc_time_zone(); - auto tp = system_clock::from_time_t(0); + auto tp = chrono::system_clock::from_time_t(0); TestFormatSpecifier(tp, tz, "%a", "Thu"); TestFormatSpecifier(tp, tz, "%A", "Thursday"); @@ -172,9 +209,9 @@ TEST(Format, LocaleSpecific) { TestFormatSpecifier(tp, tz, "%B", "January"); // %c should at least produce the numeric year and time-of-day. - const std::string s = format("%c", tp, utc_time_zone()); - EXPECT_THAT(s, HasSubstr("1970")); - EXPECT_THAT(s, HasSubstr("00:00:00")); + const std::string s = cctz::format("%c", tp, utc_time_zone()); + EXPECT_THAT(s, testing::HasSubstr("1970")); + EXPECT_THAT(s, testing::HasSubstr("00:00:00")); TestFormatSpecifier(tp, tz, "%p", "AM"); TestFormatSpecifier(tp, tz, "%x", "01/01/70"); @@ -183,7 +220,9 @@ TEST(Format, LocaleSpecific) { #if defined(__linux__) // SU/C99/TZ extensions TestFormatSpecifier(tp, tz, "%h", "Jan"); // Same as %b +#if defined(__GLIBC__) TestFormatSpecifier(tp, tz, "%P", "am"); +#endif TestFormatSpecifier(tp, tz, "%r", "12:00:00 AM"); // Modified conversion specifiers %E_ @@ -213,7 +252,7 @@ TEST(Format, LocaleSpecific) { TEST(Format, Escaping) { const time_zone tz = utc_time_zone(); - auto tp = system_clock::from_time_t(0); + auto tp = chrono::system_clock::from_time_t(0); TestFormatSpecifier(tp, tz, "%%", "%"); TestFormatSpecifier(tp, tz, "%%a", "%a"); @@ -232,66 +271,330 @@ TEST(Format, Escaping) { TEST(Format, ExtendedSeconds) { const time_zone tz = utc_time_zone(); - time_point tp = system_clock::from_time_t(0); - tp += hours(3) + minutes(4) + seconds(5); - tp += milliseconds(6) + microseconds(7) + nanoseconds(8); - - EXPECT_EQ("11045", format("%s", tp, tz)); - - EXPECT_EQ("03:04:05", format("%H:%M:%E0S", tp, tz)); - EXPECT_EQ("03:04:05.0", format("%H:%M:%E1S", tp, tz)); - EXPECT_EQ("03:04:05.00", format("%H:%M:%E2S", tp, tz)); - EXPECT_EQ("03:04:05.006", format("%H:%M:%E3S", tp, tz)); - EXPECT_EQ("03:04:05.0060", format("%H:%M:%E4S", tp, tz)); - EXPECT_EQ("03:04:05.00600", format("%H:%M:%E5S", tp, tz)); - EXPECT_EQ("03:04:05.006007", format("%H:%M:%E6S", tp, tz)); - EXPECT_EQ("03:04:05.0060070", format("%H:%M:%E7S", tp, tz)); - EXPECT_EQ("03:04:05.00600700", format("%H:%M:%E8S", tp, tz)); - EXPECT_EQ("03:04:05.006007008", format("%H:%M:%E9S", tp, tz)); - EXPECT_EQ("03:04:05.0060070080", format("%H:%M:%E10S", tp, tz)); - EXPECT_EQ("03:04:05.00600700800", format("%H:%M:%E11S", tp, tz)); - EXPECT_EQ("03:04:05.006007008000", format("%H:%M:%E12S", tp, tz)); - EXPECT_EQ("03:04:05.0060070080000", format("%H:%M:%E13S", tp, tz)); - EXPECT_EQ("03:04:05.00600700800000", format("%H:%M:%E14S", tp, tz)); - EXPECT_EQ("03:04:05.006007008000000", format("%H:%M:%E15S", tp, tz)); - - EXPECT_EQ("03:04:05.006007008", format("%H:%M:%E*S", tp, tz)); + + // No subseconds. + time_point tp = chrono::system_clock::from_time_t(0); + tp += chrono::seconds(5); + EXPECT_EQ("05", cctz::format("%E*S", tp, tz)); + EXPECT_EQ("05", cctz::format("%E0S", tp, tz)); + EXPECT_EQ("05.0", cctz::format("%E1S", tp, tz)); + EXPECT_EQ("05.00", cctz::format("%E2S", tp, tz)); + EXPECT_EQ("05.000", cctz::format("%E3S", tp, tz)); + EXPECT_EQ("05.0000", cctz::format("%E4S", tp, tz)); + EXPECT_EQ("05.00000", cctz::format("%E5S", tp, tz)); + EXPECT_EQ("05.000000", cctz::format("%E6S", tp, tz)); + EXPECT_EQ("05.0000000", cctz::format("%E7S", tp, tz)); + EXPECT_EQ("05.00000000", cctz::format("%E8S", tp, tz)); + EXPECT_EQ("05.000000000", cctz::format("%E9S", tp, tz)); + EXPECT_EQ("05.0000000000", cctz::format("%E10S", tp, tz)); + EXPECT_EQ("05.00000000000", cctz::format("%E11S", tp, tz)); + EXPECT_EQ("05.000000000000", cctz::format("%E12S", tp, tz)); + EXPECT_EQ("05.0000000000000", cctz::format("%E13S", tp, tz)); + EXPECT_EQ("05.00000000000000", cctz::format("%E14S", tp, tz)); + EXPECT_EQ("05.000000000000000", cctz::format("%E15S", tp, tz)); + + // With subseconds. + tp += chrono::milliseconds(6) + chrono::microseconds(7) + + chrono::nanoseconds(8); + EXPECT_EQ("05.006007008", cctz::format("%E*S", tp, tz)); + EXPECT_EQ("05", cctz::format("%E0S", tp, tz)); + EXPECT_EQ("05.0", cctz::format("%E1S", tp, tz)); + EXPECT_EQ("05.00", cctz::format("%E2S", tp, tz)); + EXPECT_EQ("05.006", cctz::format("%E3S", tp, tz)); + EXPECT_EQ("05.0060", cctz::format("%E4S", tp, tz)); + EXPECT_EQ("05.00600", cctz::format("%E5S", tp, tz)); + EXPECT_EQ("05.006007", cctz::format("%E6S", tp, tz)); + EXPECT_EQ("05.0060070", cctz::format("%E7S", tp, tz)); + EXPECT_EQ("05.00600700", cctz::format("%E8S", tp, tz)); + EXPECT_EQ("05.006007008", cctz::format("%E9S", tp, tz)); + EXPECT_EQ("05.0060070080", cctz::format("%E10S", tp, tz)); + EXPECT_EQ("05.00600700800", cctz::format("%E11S", tp, tz)); + EXPECT_EQ("05.006007008000", cctz::format("%E12S", tp, tz)); + EXPECT_EQ("05.0060070080000", cctz::format("%E13S", tp, tz)); + EXPECT_EQ("05.00600700800000", cctz::format("%E14S", tp, tz)); + EXPECT_EQ("05.006007008000000", cctz::format("%E15S", tp, tz)); + + // Times before the Unix epoch. + tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1); + EXPECT_EQ("1969-12-31 23:59:59.999999", + cctz::format("%Y-%m-%d %H:%M:%E*S", tp, tz)); + + // Here is a "%E*S" case we got wrong for a while. While the first + // instant below is correctly rendered as "...:07.333304", the second + // one used to appear as "...:07.33330499999999999". + tp = chrono::system_clock::from_time_t(0) + + chrono::microseconds(1395024427333304); + EXPECT_EQ("2014-03-17 02:47:07.333304", + cctz::format("%Y-%m-%d %H:%M:%E*S", tp, tz)); + tp += chrono::microseconds(1); + EXPECT_EQ("2014-03-17 02:47:07.333305", + cctz::format("%Y-%m-%d %H:%M:%E*S", tp, tz)); +} + +TEST(Format, ExtendedSubeconds) { + const time_zone tz = utc_time_zone(); + + // No subseconds. + time_point tp = chrono::system_clock::from_time_t(0); + tp += chrono::seconds(5); + EXPECT_EQ("0", cctz::format("%E*f", tp, tz)); + EXPECT_EQ("", cctz::format("%E0f", tp, tz)); + EXPECT_EQ("0", cctz::format("%E1f", tp, tz)); + EXPECT_EQ("00", cctz::format("%E2f", tp, tz)); + EXPECT_EQ("000", cctz::format("%E3f", tp, tz)); + EXPECT_EQ("0000", cctz::format("%E4f", tp, tz)); + EXPECT_EQ("00000", cctz::format("%E5f", tp, tz)); + EXPECT_EQ("000000", cctz::format("%E6f", tp, tz)); + EXPECT_EQ("0000000", cctz::format("%E7f", tp, tz)); + EXPECT_EQ("00000000", cctz::format("%E8f", tp, tz)); + EXPECT_EQ("000000000", cctz::format("%E9f", tp, tz)); + EXPECT_EQ("0000000000", cctz::format("%E10f", tp, tz)); + EXPECT_EQ("00000000000", cctz::format("%E11f", tp, tz)); + EXPECT_EQ("000000000000", cctz::format("%E12f", tp, tz)); + EXPECT_EQ("0000000000000", cctz::format("%E13f", tp, tz)); + EXPECT_EQ("00000000000000", cctz::format("%E14f", tp, tz)); + EXPECT_EQ("000000000000000", cctz::format("%E15f", tp, tz)); + + // With subseconds. + tp += chrono::milliseconds(6) + chrono::microseconds(7) + + chrono::nanoseconds(8); + EXPECT_EQ("006007008", cctz::format("%E*f", tp, tz)); + EXPECT_EQ("", cctz::format("%E0f", tp, tz)); + EXPECT_EQ("0", cctz::format("%E1f", tp, tz)); + EXPECT_EQ("00", cctz::format("%E2f", tp, tz)); + EXPECT_EQ("006", cctz::format("%E3f", tp, tz)); + EXPECT_EQ("0060", cctz::format("%E4f", tp, tz)); + EXPECT_EQ("00600", cctz::format("%E5f", tp, tz)); + EXPECT_EQ("006007", cctz::format("%E6f", tp, tz)); + EXPECT_EQ("0060070", cctz::format("%E7f", tp, tz)); + EXPECT_EQ("00600700", cctz::format("%E8f", tp, tz)); + EXPECT_EQ("006007008", cctz::format("%E9f", tp, tz)); + EXPECT_EQ("0060070080", cctz::format("%E10f", tp, tz)); + EXPECT_EQ("00600700800", cctz::format("%E11f", tp, tz)); + EXPECT_EQ("006007008000", cctz::format("%E12f", tp, tz)); + EXPECT_EQ("0060070080000", cctz::format("%E13f", tp, tz)); + EXPECT_EQ("00600700800000", cctz::format("%E14f", tp, tz)); + EXPECT_EQ("006007008000000", cctz::format("%E15f", tp, tz)); // Times before the Unix epoch. - tp = system_clock::from_time_t(0) + microseconds(-1); + tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1); EXPECT_EQ("1969-12-31 23:59:59.999999", - format("%Y-%m-%d %H:%M:%E*S", tp, tz)); + cctz::format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz)); // Here is a "%E*S" case we got wrong for a while. While the first // instant below is correctly rendered as "...:07.333304", the second // one used to appear as "...:07.33330499999999999". - tp = system_clock::from_time_t(0) + microseconds(1395024427333304); + tp = chrono::system_clock::from_time_t(0) + + chrono::microseconds(1395024427333304); EXPECT_EQ("2014-03-17 02:47:07.333304", - format("%Y-%m-%d %H:%M:%E*S", tp, tz)); - tp += microseconds(1); + cctz::format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz)); + tp += chrono::microseconds(1); EXPECT_EQ("2014-03-17 02:47:07.333305", - format("%Y-%m-%d %H:%M:%E*S", tp, tz)); + cctz::format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz)); +} + +TEST(Format, CompareExtendSecondsVsSubseconds) { + const time_zone tz = utc_time_zone(); + + // This test case illustrates the differences/similarities between: + // fmt_A: %ES + // fmt_B: %S.%Ef + auto fmt_A = [](const std::string& prec) { return "%E" + prec + "S"; }; + auto fmt_B = [](const std::string& prec) { return "%S.%E" + prec + "f"; }; + + // No subseconds: + time_point tp = chrono::system_clock::from_time_t(0); + tp += chrono::seconds(5); + // ... %E*S and %S.%E*f are different. + EXPECT_EQ("05", cctz::format(fmt_A("*"), tp, tz)); + EXPECT_EQ("05.0", cctz::format(fmt_B("*"), tp, tz)); + // ... %E0S and %S.%E0f are different. + EXPECT_EQ("05", cctz::format(fmt_A("0"), tp, tz)); + EXPECT_EQ("05.", cctz::format(fmt_B("0"), tp, tz)); + // ... %ES and %S.%Ef are the same for prec in [1:15]. + for (int prec = 1; prec <= 15; ++prec) { + const std::string a = cctz::format(fmt_A(std::to_string(prec)), tp, tz); + const std::string b = cctz::format(fmt_B(std::to_string(prec)), tp, tz); + EXPECT_EQ(a, b) << "prec=" << prec; + } + + // With subseconds: + // ... %E*S and %S.%E*f are the same. + tp += chrono::milliseconds(6) + chrono::microseconds(7) + + chrono::nanoseconds(8); + EXPECT_EQ("05.006007008", cctz::format(fmt_A("*"), tp, tz)); + EXPECT_EQ("05.006007008", cctz::format(fmt_B("*"), tp, tz)); + // ... %E0S and %S.%E0f are different. + EXPECT_EQ("05", cctz::format(fmt_A("0"), tp, tz)); + EXPECT_EQ("05.", cctz::format(fmt_B("0"), tp, tz)); + // ... %ES and %S.%Ef are the same for prec in [1:15]. + for (int prec = 1; prec <= 15; ++prec) { + const std::string a = cctz::format(fmt_A(std::to_string(prec)), tp, tz); + const std::string b = cctz::format(fmt_B(std::to_string(prec)), tp, tz); + EXPECT_EQ(a, b) << "prec=" << prec; + } } TEST(Format, ExtendedOffset) { - auto tp = system_clock::from_time_t(0); + const auto tp = chrono::system_clock::from_time_t(0); - time_zone tz = utc_time_zone(); + auto tz = fixed_time_zone(cctz::seconds::zero()); + TestFormatSpecifier(tp, tz, "%z", "+0000"); + TestFormatSpecifier(tp, tz, "%:z", "+00:00"); TestFormatSpecifier(tp, tz, "%Ez", "+00:00"); - EXPECT_TRUE(load_time_zone("America/New_York", &tz)); - TestFormatSpecifier(tp, tz, "%Ez", "-05:00"); + tz = fixed_time_zone(chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "+0000"); + TestFormatSpecifier(tp, tz, "%:z", "+00:00"); + TestFormatSpecifier(tp, tz, "%Ez", "+00:00"); - EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); - TestFormatSpecifier(tp, tz, "%Ez", "-08:00"); + tz = fixed_time_zone(-chrono::seconds(56)); // NOTE: +00:00 + TestFormatSpecifier(tp, tz, "%z", "+0000"); + TestFormatSpecifier(tp, tz, "%:z", "+00:00"); + TestFormatSpecifier(tp, tz, "%Ez", "+00:00"); - EXPECT_TRUE(load_time_zone("Australia/Sydney", &tz)); - TestFormatSpecifier(tp, tz, "%Ez", "+10:00"); + tz = fixed_time_zone(chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%z", "+0034"); + TestFormatSpecifier(tp, tz, "%:z", "+00:34"); + TestFormatSpecifier(tp, tz, "%Ez", "+00:34"); + + tz = fixed_time_zone(-chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%z", "-0034"); + TestFormatSpecifier(tp, tz, "%:z", "-00:34"); + TestFormatSpecifier(tp, tz, "%Ez", "-00:34"); + + tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "+0034"); + TestFormatSpecifier(tp, tz, "%:z", "+00:34"); + TestFormatSpecifier(tp, tz, "%Ez", "+00:34"); + + tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "-0034"); + TestFormatSpecifier(tp, tz, "%:z", "-00:34"); + TestFormatSpecifier(tp, tz, "%Ez", "-00:34"); + + tz = fixed_time_zone(chrono::hours(12)); + TestFormatSpecifier(tp, tz, "%z", "+1200"); + TestFormatSpecifier(tp, tz, "%:z", "+12:00"); + TestFormatSpecifier(tp, tz, "%Ez", "+12:00"); + + tz = fixed_time_zone(-chrono::hours(12)); + TestFormatSpecifier(tp, tz, "%z", "-1200"); + TestFormatSpecifier(tp, tz, "%:z", "-12:00"); + TestFormatSpecifier(tp, tz, "%Ez", "-12:00"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "+1200"); + TestFormatSpecifier(tp, tz, "%:z", "+12:00"); + TestFormatSpecifier(tp, tz, "%Ez", "+12:00"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "-1200"); + TestFormatSpecifier(tp, tz, "%:z", "-12:00"); + TestFormatSpecifier(tp, tz, "%Ez", "-12:00"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%z", "+1234"); + TestFormatSpecifier(tp, tz, "%:z", "+12:34"); + TestFormatSpecifier(tp, tz, "%Ez", "+12:34"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%z", "-1234"); + TestFormatSpecifier(tp, tz, "%:z", "-12:34"); + TestFormatSpecifier(tp, tz, "%Ez", "-12:34"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) + + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "+1234"); + TestFormatSpecifier(tp, tz, "%:z", "+12:34"); + TestFormatSpecifier(tp, tz, "%Ez", "+12:34"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) - + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "-1234"); + TestFormatSpecifier(tp, tz, "%:z", "-12:34"); + TestFormatSpecifier(tp, tz, "%Ez", "-12:34"); +} - EXPECT_TRUE(load_time_zone("Africa/Monrovia", &tz)); - // The true offset is -00:44:30 but %z only gives (truncated) minutes. - TestFormatSpecifier(tp, tz, "%z", "-0044"); - TestFormatSpecifier(tp, tz, "%Ez", "-00:44"); +TEST(Format, ExtendedSecondOffset) { + const auto tp = chrono::system_clock::from_time_t(0); + + auto tz = fixed_time_zone(cctz::seconds::zero()); + TestFormatSpecifier(tp, tz, "%E*z", "+00:00:00"); + TestFormatSpecifier(tp, tz, "%::z", "+00:00:00"); + TestFormatSpecifier(tp, tz, "%:::z", "+00"); + + tz = fixed_time_zone(chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "+00:00:56"); + TestFormatSpecifier(tp, tz, "%::z", "+00:00:56"); + TestFormatSpecifier(tp, tz, "%:::z", "+00:00:56"); + + tz = fixed_time_zone(-chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "-00:00:56"); + TestFormatSpecifier(tp, tz, "%::z", "-00:00:56"); + TestFormatSpecifier(tp, tz, "%:::z", "-00:00:56"); + + tz = fixed_time_zone(chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%E*z", "+00:34:00"); + TestFormatSpecifier(tp, tz, "%::z", "+00:34:00"); + TestFormatSpecifier(tp, tz, "%:::z", "+00:34"); + + tz = fixed_time_zone(-chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%E*z", "-00:34:00"); + TestFormatSpecifier(tp, tz, "%::z", "-00:34:00"); + TestFormatSpecifier(tp, tz, "%:::z", "-00:34"); + + tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "+00:34:56"); + TestFormatSpecifier(tp, tz, "%::z", "+00:34:56"); + TestFormatSpecifier(tp, tz, "%:::z", "+00:34:56"); + + tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "-00:34:56"); + TestFormatSpecifier(tp, tz, "%::z", "-00:34:56"); + TestFormatSpecifier(tp, tz, "%:::z", "-00:34:56"); + + tz = fixed_time_zone(chrono::hours(12)); + TestFormatSpecifier(tp, tz, "%E*z", "+12:00:00"); + TestFormatSpecifier(tp, tz, "%::z", "+12:00:00"); + TestFormatSpecifier(tp, tz, "%:::z", "+12"); + + tz = fixed_time_zone(-chrono::hours(12)); + TestFormatSpecifier(tp, tz, "%E*z", "-12:00:00"); + TestFormatSpecifier(tp, tz, "%::z", "-12:00:00"); + TestFormatSpecifier(tp, tz, "%:::z", "-12"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "+12:00:56"); + TestFormatSpecifier(tp, tz, "%::z", "+12:00:56"); + TestFormatSpecifier(tp, tz, "%:::z", "+12:00:56"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "-12:00:56"); + TestFormatSpecifier(tp, tz, "%::z", "-12:00:56"); + TestFormatSpecifier(tp, tz, "%:::z", "-12:00:56"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%E*z", "+12:34:00"); + TestFormatSpecifier(tp, tz, "%::z", "+12:34:00"); + TestFormatSpecifier(tp, tz, "%:::z", "+12:34"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%E*z", "-12:34:00"); + TestFormatSpecifier(tp, tz, "%::z", "-12:34:00"); + TestFormatSpecifier(tp, tz, "%:::z", "-12:34"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) + + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "+12:34:56"); + TestFormatSpecifier(tp, tz, "%::z", "+12:34:56"); + TestFormatSpecifier(tp, tz, "%:::z", "+12:34:56"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) - + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "-12:34:56"); + TestFormatSpecifier(tp, tz, "%::z", "-12:34:56"); + TestFormatSpecifier(tp, tz, "%:::z", "-12:34:56"); } TEST(Format, ExtendedYears) { @@ -300,87 +603,149 @@ TEST(Format, ExtendedYears) { // %E4Y zero-pads the year to produce at least 4 chars, including the sign. auto tp = convert(civil_second(-999, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("-9991127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("-9991127", cctz::format(e4y_fmt, tp, utc)); tp = convert(civil_second(-99, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("-0991127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("-0991127", cctz::format(e4y_fmt, tp, utc)); tp = convert(civil_second(-9, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("-0091127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("-0091127", cctz::format(e4y_fmt, tp, utc)); tp = convert(civil_second(-1, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("-0011127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("-0011127", cctz::format(e4y_fmt, tp, utc)); tp = convert(civil_second(0, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("00001127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("00001127", cctz::format(e4y_fmt, tp, utc)); tp = convert(civil_second(1, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("00011127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("00011127", cctz::format(e4y_fmt, tp, utc)); tp = convert(civil_second(9, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("00091127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("00091127", cctz::format(e4y_fmt, tp, utc)); tp = convert(civil_second(99, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("00991127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("00991127", cctz::format(e4y_fmt, tp, utc)); tp = convert(civil_second(999, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("09991127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("09991127", cctz::format(e4y_fmt, tp, utc)); tp = convert(civil_second(9999, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("99991127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("99991127", cctz::format(e4y_fmt, tp, utc)); // When the year is outside [-999:9999], more than 4 chars are produced. tp = convert(civil_second(-1000, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("-10001127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("-10001127", cctz::format(e4y_fmt, tp, utc)); tp = convert(civil_second(10000, 11, 27, 0, 0, 0), utc); - EXPECT_EQ("100001127", format(e4y_fmt, tp, utc)); + EXPECT_EQ("100001127", cctz::format(e4y_fmt, tp, utc)); } TEST(Format, RFC3339Format) { time_zone tz; EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); - time_point tp = + time_point tp = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz)); + + tp += chrono::milliseconds(100); + EXPECT_EQ("1977-06-28T09:08:07.1-07:00", cctz::format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz)); + + tp += chrono::milliseconds(20); + EXPECT_EQ("1977-06-28T09:08:07.12-07:00", cctz::format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz)); + + tp += chrono::milliseconds(3); + EXPECT_EQ("1977-06-28T09:08:07.123-07:00", + cctz::format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz)); + + tp += chrono::microseconds(400); + EXPECT_EQ("1977-06-28T09:08:07.1234-07:00", + cctz::format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz)); + + tp += chrono::microseconds(50); + EXPECT_EQ("1977-06-28T09:08:07.12345-07:00", + cctz::format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz)); + + tp += chrono::microseconds(6); + EXPECT_EQ("1977-06-28T09:08:07.123456-07:00", + cctz::format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz)); + + tp += chrono::nanoseconds(700); + EXPECT_EQ("1977-06-28T09:08:07.1234567-07:00", + cctz::format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz)); + + tp += chrono::nanoseconds(80); + EXPECT_EQ("1977-06-28T09:08:07.12345678-07:00", + cctz::format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz)); + + tp += chrono::nanoseconds(9); + EXPECT_EQ("1977-06-28T09:08:07.123456789-07:00", + cctz::format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", cctz::format(RFC3339_sec, tp, tz)); +} - tp += milliseconds(100); - EXPECT_EQ("1977-06-28T09:08:07.1-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); +TEST(Format, RFC1123Format) { // locale specific + time_zone tz; + EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); - tp += milliseconds(20); - EXPECT_EQ("1977-06-28T09:08:07.12-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + auto tp = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); + EXPECT_EQ("Tue, 28 Jun 1977 09:08:07 -0700", + cctz::format(RFC1123_full, tp, tz)); + EXPECT_EQ("28 Jun 1977 09:08:07 -0700", + cctz::format(RFC1123_no_wday, tp, tz)); +} - tp += milliseconds(3); - EXPECT_EQ("1977-06-28T09:08:07.123-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); +TEST(Format, Week) { + const time_zone utc = utc_time_zone(); - tp += microseconds(400); - EXPECT_EQ("1977-06-28T09:08:07.1234-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + auto tp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc); + EXPECT_EQ("2017-01-7", cctz::format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2017-00-0", cctz::format("%Y-%W-%w", tp, utc)); - tp += microseconds(50); - EXPECT_EQ("1977-06-28T09:08:07.12345-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + tp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc); + EXPECT_EQ("2017-53-7", cctz::format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2017-52-0", cctz::format("%Y-%W-%w", tp, utc)); - tp += microseconds(6); - EXPECT_EQ("1977-06-28T09:08:07.123456-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + tp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc); + EXPECT_EQ("2018-00-1", cctz::format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2018-01-1", cctz::format("%Y-%W-%w", tp, utc)); - tp += nanoseconds(700); - EXPECT_EQ("1977-06-28T09:08:07.1234567-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + tp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc); + EXPECT_EQ("2018-52-1", cctz::format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2018-53-1", cctz::format("%Y-%W-%w", tp, utc)); - tp += nanoseconds(80); - EXPECT_EQ("1977-06-28T09:08:07.12345678-07:00", format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + tp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc); + EXPECT_EQ("2019-00-2", cctz::format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2019-00-2", cctz::format("%Y-%W-%w", tp, utc)); - tp += nanoseconds(9); - EXPECT_EQ("1977-06-28T09:08:07.123456789-07:00", - format(RFC3339_full, tp, tz)); - EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + tp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); + EXPECT_EQ("2019-52-2", cctz::format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2019-52-2", cctz::format("%Y-%W-%w", tp, utc)); } -TEST(Format, RFC1123Format) { // locale specific - time_zone tz; - EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); - - auto tp = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); - EXPECT_EQ("Tue, 28 Jun 1977 09:08:07 -0700", format(RFC1123_full, tp, tz)); - EXPECT_EQ("28 Jun 1977 09:08:07 -0700", format(RFC1123_no_wday, tp, tz)); +TEST(Format, NULsInFormatString) { + time_zone tz = utc_time_zone(); + time_point tp = chrono::system_clock::from_time_t(0); + + // All NULs. + std::string nuls(32, '\0'); + EXPECT_EQ(nuls, cctz::format(nuls, tp, tz)); + + // NULs amongst ordinary text plus the internal "%\0" specifier. + std::string percent_nul("\0X\0\0X%\0\0X\0\0X\0", 13); + EXPECT_EQ(percent_nul, cctz::format(percent_nul, tp, tz)); + + // NULs amongst ordinary text plus a non-internal specifier (%I). + EXPECT_EQ(std::string("X\0\0\0X12\0X\0\0\0X", 13), + cctz::format(std::string("X\0\0\0X%I\0X\0\0\0X", 13), tp, tz)); + +#if defined(__linux__) && defined(__GLIBC__) + // Depending upon strftime() behavior on "%E" + // and "%O", "%E\0" and "%0\0" produce themselves. + std::string percent_E_nul("abc%E\0xyz", 9); + EXPECT_EQ(percent_E_nul, cctz::format(percent_E_nul, tp, tz)); + std::string percent_O_nul("abc%O\0xyz", 9); + EXPECT_EQ(percent_O_nul, cctz::format(percent_O_nul, tp, tz)); +#endif } // @@ -388,55 +753,74 @@ TEST(Format, RFC1123Format) { // locale specific // TEST(Parse, TimePointResolution) { - using std::chrono::time_point_cast; const char kFmt[] = "%H:%M:%E*S"; const time_zone utc = utc_time_zone(); - time_point tp_ns; + time_point tp_ns; EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_ns)); - EXPECT_EQ("03:04:05.123456789", format(kFmt, tp_ns, utc)); + EXPECT_EQ("03:04:05.123456789", cctz::format(kFmt, tp_ns, utc)); EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ns)); - EXPECT_EQ("03:04:05.123456", format(kFmt, tp_ns, utc)); + EXPECT_EQ("03:04:05.123456", cctz::format(kFmt, tp_ns, utc)); - time_point tp_us; + time_point tp_us; EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_us)); - EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc)); + EXPECT_EQ("03:04:05.123456", cctz::format(kFmt, tp_us, utc)); EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_us)); - EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc)); + EXPECT_EQ("03:04:05.123456", cctz::format(kFmt, tp_us, utc)); EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_us)); - EXPECT_EQ("03:04:05.123", format(kFmt, tp_us, utc)); + EXPECT_EQ("03:04:05.123", cctz::format(kFmt, tp_us, utc)); - time_point tp_ms; + time_point tp_ms; EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ms)); - EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc)); + EXPECT_EQ("03:04:05.123", cctz::format(kFmt, tp_ms, utc)); EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_ms)); - EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc)); + EXPECT_EQ("03:04:05.123", cctz::format(kFmt, tp_ms, utc)); EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_ms)); - EXPECT_EQ("03:04:05", format(kFmt, tp_ms, utc)); + EXPECT_EQ("03:04:05", cctz::format(kFmt, tp_ms, utc)); - time_point tp_s; + time_point tp_s; EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_s)); - EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc)); + EXPECT_EQ("03:04:05", cctz::format(kFmt, tp_s, utc)); EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_s)); - EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc)); + EXPECT_EQ("03:04:05", cctz::format(kFmt, tp_s, utc)); - time_point tp_m; + time_point tp_m; EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_m)); - EXPECT_EQ("03:04:00", format(kFmt, tp_m, utc)); + EXPECT_EQ("03:04:00", cctz::format(kFmt, tp_m, utc)); - time_point tp_h; + time_point tp_h; EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_h)); - EXPECT_EQ("03:00:00", format(kFmt, tp_h, utc)); + EXPECT_EQ("03:00:00", cctz::format(kFmt, tp_h, utc)); +} + +TEST(Parse, TimePointExtendedResolution) { + const char kFmt[] = "%H:%M:%E*S"; + const time_zone utc = utc_time_zone(); + + time_point tp; + detail::femtoseconds fs; + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.123456789012345", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.123456789012345", detail::format(kFmt, tp, fs, utc)); + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.012345678901234", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.012345678901234", detail::format(kFmt, tp, fs, utc)); + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.001234567890123", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.001234567890123", detail::format(kFmt, tp, fs, utc)); + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000123", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.000000000000123", detail::format(kFmt, tp, fs, utc)); + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000012", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.000000000000012", detail::format(kFmt, tp, fs, utc)); + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000001", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.000000000000001", detail::format(kFmt, tp, fs, utc)); } TEST(Parse, Basics) { time_zone tz = utc_time_zone(); - time_point tp = - system_clock::from_time_t(1234567890); + time_point tp = + chrono::system_clock::from_time_t(1234567890); // Simple edge cases. EXPECT_TRUE(parse("", "", tz, &tp)); - EXPECT_EQ(system_clock::from_time_t(0), tp); // everything defaulted + EXPECT_EQ(chrono::system_clock::from_time_t(0), tp); // everything defaulted EXPECT_TRUE(parse(" ", " ", tz, &tp)); EXPECT_TRUE(parse(" ", " ", tz, &tp)); EXPECT_TRUE(parse("x", "x", tz, &tp)); @@ -450,7 +834,7 @@ TEST(Parse, Basics) { TEST(Parse, WithTimeZone) { time_zone tz; EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); - time_point tp; + time_point tp; // We can parse a string without a UTC offset if we supply a timezone. EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &tp)); @@ -461,13 +845,13 @@ TEST(Parse, WithTimeZone) { utc_time_zone(), &tp)); ExpectTime(tp, tz, 2013, 6, 28, 19 - 8 - 7, 8, 9, -7 * 60 * 60, true, "PDT"); - // Check a skipped time (a Spring DST transition). parse() returns - // the preferred-offset result, as defined for ConvertDateTime(). + // Check a skipped time (a Spring DST transition). parse() uses the + // pre-transition offset. EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-03-13 02:15:00", tz, &tp)); ExpectTime(tp, tz, 2011, 3, 13, 3, 15, 0, -7 * 60 * 60, true, "PDT"); - // Check a repeated time (a Fall DST transition). parse() returns - // the preferred-offset result, as defined for ConvertDateTime(). + // Check a repeated time (a Fall DST transition). parse() uses the + // pre-transition offset. EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-11-06 01:15:00", tz, &tp)); ExpectTime(tp, tz, 2011, 11, 6, 1, 15, 0, -7 * 60 * 60, true, "PDT"); } @@ -475,7 +859,7 @@ TEST(Parse, WithTimeZone) { TEST(Parse, LeapSecond) { time_zone tz; EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); - time_point tp; + time_point tp; // ":59" -> ":59" EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59-08:00", tz, &tp)); @@ -499,7 +883,10 @@ TEST(Parse, LeapSecond) { TEST(Parse, ErrorCases) { const time_zone tz = utc_time_zone(); - auto tp = system_clock::from_time_t(0); + auto tp = chrono::system_clock::from_time_t(0); + + // No data. + EXPECT_FALSE(parse("X", "", tz, &tp)); // Illegal trailing data. EXPECT_FALSE(parse("%S", "123", tz, &tp)); @@ -542,7 +929,7 @@ TEST(Parse, ErrorCases) { TEST(Parse, PosixConversions) { time_zone tz = utc_time_zone(); - auto tp = system_clock::from_time_t(0); + auto tp = chrono::system_clock::from_time_t(0); const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); tp = reset; @@ -599,9 +986,14 @@ TEST(Parse, PosixConversions) { #if defined(__linux__) // SU/C99/TZ extensions + // Because we handle each (non-internal) specifier in a separate call + // to strptime(), there is no way to group %C and %y together. So we + // just skip the %C/%y case. +#if 0 tp = reset; - EXPECT_TRUE(parse("%C", "20", tz, &tp)); - EXPECT_EQ(2000, convert(tp, tz).year()); + EXPECT_TRUE(parse("%C %y", "20 04", tz, &tp)); + EXPECT_EQ(2004, convert(tp, tz).year()); +#endif tp = reset; EXPECT_TRUE(parse("%D", "02/03/04", tz, &tp)); @@ -626,14 +1018,14 @@ TEST(Parse, PosixConversions) { tp = reset; EXPECT_TRUE(parse("%s", "1234567890", tz, &tp)); - EXPECT_EQ(system_clock::from_time_t(1234567890), tp); + EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp); // %s conversion, like %z/%Ez, pays no heed to the optional zone. time_zone lax; EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax)); tp = reset; EXPECT_TRUE(parse("%s", "1234567890", lax, &tp)); - EXPECT_EQ(system_clock::from_time_t(1234567890), tp); + EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp); // This is most important when the time has the same YMDhms // breakdown in the zone as some other time. For example, ... @@ -641,16 +1033,16 @@ TEST(Parse, PosixConversions) { // 1414920600 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PST) tp = reset; EXPECT_TRUE(parse("%s", "1414917000", lax, &tp)); - EXPECT_EQ(system_clock::from_time_t(1414917000), tp); + EXPECT_EQ(chrono::system_clock::from_time_t(1414917000), tp); tp = reset; EXPECT_TRUE(parse("%s", "1414920600", lax, &tp)); - EXPECT_EQ(system_clock::from_time_t(1414920600), tp); + EXPECT_EQ(chrono::system_clock::from_time_t(1414920600), tp); #endif } TEST(Parse, LocaleSpecific) { time_zone tz = utc_time_zone(); - auto tp = system_clock::from_time_t(0); + auto tp = chrono::system_clock::from_time_t(0); const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); // %a is parsed but ignored. @@ -675,8 +1067,12 @@ TEST(Parse, LocaleSpecific) { tp = reset; EXPECT_TRUE(parse("%x", "02/03/04", tz, &tp)); - EXPECT_EQ(2, convert(tp, tz).month()); - EXPECT_EQ(3, convert(tp, tz).day()); + if (convert(tp, tz).month() == 2) { + EXPECT_EQ(3, convert(tp, tz).day()); + } else { + EXPECT_EQ(2, convert(tp, tz).day()); + EXPECT_EQ(3, convert(tp, tz).month()); + } EXPECT_EQ(2004, convert(tp, tz).year()); tp = reset; @@ -692,9 +1088,11 @@ TEST(Parse, LocaleSpecific) { EXPECT_TRUE(parse("%h", "Feb", tz, &tp)); EXPECT_EQ(2, convert(tp, tz).month()); // Equivalent to %b +#if defined(__GLIBC__) tp = reset; EXPECT_TRUE(parse("%l %p", "5 PM", tz, &tp)); EXPECT_EQ(17, convert(tp, tz).hour()); +#endif tp = reset; EXPECT_TRUE(parse("%r", "03:44:55 PM", tz, &tp)); @@ -702,16 +1100,13 @@ TEST(Parse, LocaleSpecific) { EXPECT_EQ(44, convert(tp, tz).minute()); EXPECT_EQ(55, convert(tp, tz).second()); +#if defined(__GLIBC__) tp = reset; EXPECT_TRUE(parse("%Ec", "Tue Nov 19 05:06:07 2013", tz, &tp)); EXPECT_EQ(convert(civil_second(2013, 11, 19, 5, 6, 7), tz), tp); // Modified conversion specifiers %E_ - tp = reset; - EXPECT_TRUE(parse("%EC", "20", tz, &tp)); - EXPECT_EQ(2000, convert(tp, tz).year()); - tp = reset; EXPECT_TRUE(parse("%Ex", "02/03/04", tz, &tp)); EXPECT_EQ(2, convert(tp, tz).month()); @@ -724,16 +1119,11 @@ TEST(Parse, LocaleSpecific) { EXPECT_EQ(44, convert(tp, tz).minute()); EXPECT_EQ(55, convert(tp, tz).second()); -// %Ey, the year offset from %EC, doesn't really make sense alone as there -// is no way to represent it in tm_year (%EC is not simply the century). -// Yet, because we handle each (non-internal) specifier in a separate call -// to strptime(), there is no way to group %EC and %Ey either. So we just -// skip the %Ey case. -#if 0 - tp = reset; - EXPECT_TRUE(parse("%Ey", "04", tz, &tp)); - EXPECT_EQ(2004, convert(tp, tz).year()); -#endif + // %Ey, the year offset from %EC, doesn't really make sense alone as there + // is no way to represent it in tm_year (%EC is not simply the century). + // Yet, because we handle each (non-internal) specifier in a separate call + // to strptime(), there is no way to group %EC and %Ey either. So we just + // skip the %EC and %Ey cases. tp = reset; EXPECT_TRUE(parse("%EY", "2004", tz, &tp)); @@ -782,39 +1172,80 @@ TEST(Parse, LocaleSpecific) { EXPECT_TRUE(parse("%Oy", "04", tz, &tp)); EXPECT_EQ(2004, convert(tp, tz).year()); #endif +#endif } TEST(Parse, ExtendedSeconds) { const time_zone tz = utc_time_zone(); + const time_point unix_epoch = + chrono::system_clock::from_time_t(0); + + // All %ES cases are treated the same as %E*S on input. + auto precisions = {"*", "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "10", "11", "12", "13", "14", "15"}; + for (const std::string prec : precisions) { + const std::string fmt = "%E" + prec + "S"; + SCOPED_TRACE(fmt); + time_point tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "5", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.0", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.00", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.6", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.60", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.600", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.67", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.670", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.678", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(678), tp); + } // Here is a "%E*S" case we got wrong for a while. The fractional // part of the first instant is less than 2^31 and was correctly // parsed, while the second (and any subsecond field >=2^31) failed. - time_point tp = system_clock::from_time_t(0); + time_point tp = unix_epoch; EXPECT_TRUE(parse("%E*S", "0.2147483647", tz, &tp)); - EXPECT_EQ(system_clock::from_time_t(0) + nanoseconds(214748364), tp); - tp = system_clock::from_time_t(0); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); + tp = unix_epoch; EXPECT_TRUE(parse("%E*S", "0.2147483648", tz, &tp)); - EXPECT_EQ(system_clock::from_time_t(0) + nanoseconds(214748364), tp); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); // We should also be able to specify long strings of digits far // beyond the current resolution and have them convert the same way. - tp = system_clock::from_time_t(0); + tp = unix_epoch; EXPECT_TRUE(parse( "%E*S", "0.214748364801234567890123456789012345678901234567890123456789", tz, &tp)); - EXPECT_EQ(system_clock::from_time_t(0) + nanoseconds(214748364), tp); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); } TEST(Parse, ExtendedSecondsScan) { const time_zone tz = utc_time_zone(); - time_point tp; - for (int64_t ms = 0; ms < 1000; ms += 111) { - for (int64_t us = 0; us < 1000; us += 27) { - const int64_t micros = ms * 1000 + us; - for (int64_t ns = 0; ns < 1000; ns += 9) { - const auto expected = - system_clock::from_time_t(0) + nanoseconds(micros * 1000 + ns); + time_point tp; + for (int ms = 0; ms < 1000; ms += 111) { + for (int us = 0; us < 1000; us += 27) { + const int micros = ms * 1000 + us; + for (int ns = 0; ns < 1000; ns += 9) { + const auto expected = chrono::system_clock::from_time_t(0) + + chrono::nanoseconds(micros * 1000 + ns); std::ostringstream oss; oss << "0." << std::setfill('0') << std::setw(3); oss << ms << std::setw(3) << us << std::setw(3) << ns; @@ -826,29 +1257,92 @@ TEST(Parse, ExtendedSecondsScan) { } } -TEST(Parse, ExtendedOffset) { - const time_zone utc = utc_time_zone(); - time_point tp; +TEST(Parse, ExtendedSubeconds) { + const time_zone tz = utc_time_zone(); + const time_point unix_epoch = + chrono::system_clock::from_time_t(0); + + // All %Ef cases are treated the same as %E*f on input. + auto precisions = {"*", "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "10", "11", "12", "13", "14", "15"}; + for (const std::string prec : precisions) { + const std::string fmt = "%E" + prec + "f"; + SCOPED_TRACE(fmt); + time_point tp = unix_epoch - chrono::seconds(1); + EXPECT_TRUE(parse(fmt, "", tz, &tp)); + EXPECT_EQ(unix_epoch, tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "6", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "60", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "600", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "67", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "670", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "678", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(678), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "6789", tz, &tp)); + EXPECT_EQ( + unix_epoch + chrono::milliseconds(678) + chrono::microseconds(900), tp); + } - // %z against +-HHMM. - EXPECT_TRUE(parse("%z", "+0000", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse("%z", "-1234", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); - EXPECT_TRUE(parse("%z", "+1234", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); - EXPECT_FALSE(parse("%z", "-123", utc, &tp)); + // Here is a "%E*f" case we got wrong for a while. The fractional + // part of the first instant is less than 2^31 and was correctly + // parsed, while the second (and any subsecond field >=2^31) failed. + time_point tp = unix_epoch; + EXPECT_TRUE(parse("%E*f", "2147483647", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); + tp = unix_epoch; + EXPECT_TRUE(parse("%E*f", "2147483648", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); - // %z against +-HH. - EXPECT_TRUE(parse("%z", "+00", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse("%z", "-12", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp); - EXPECT_TRUE(parse("%z", "+12", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp); - EXPECT_FALSE(parse("%z", "-1", utc, &tp)); + // We should also be able to specify long strings of digits far + // beyond the current resolution and have them convert the same way. + tp = unix_epoch; + EXPECT_TRUE(parse( + "%E*f", "214748364801234567890123456789012345678901234567890123456789", + tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); +} + +TEST(Parse, ExtendedSubecondsScan) { + time_point tp; + const time_zone tz = utc_time_zone(); + for (int ms = 0; ms < 1000; ms += 111) { + for (int us = 0; us < 1000; us += 27) { + const int micros = ms * 1000 + us; + for (int ns = 0; ns < 1000; ns += 9) { + std::ostringstream oss; + oss << std::setfill('0') << std::setw(3) << ms; + oss << std::setw(3) << us << std::setw(3) << ns; + const std::string nanos = oss.str(); + const auto expected = chrono::system_clock::from_time_t(0) + + chrono::nanoseconds(micros * 1000 + ns); + for (int ps = 0; ps < 1000; ps += 250) { + std::ostringstream ps_oss; + oss << std::setfill('0') << std::setw(3) << ps; + const std::string input = nanos + ps_oss.str() + "999"; + EXPECT_TRUE(parse("%E*f", input, tz, &tp)); + EXPECT_EQ(expected + chrono::nanoseconds(ps) / 1000, tp) << input; + } + } + } + } +} + +TEST(Parse, ExtendedOffset) { + const time_zone utc = utc_time_zone(); + time_point tp; - // %Ez against +-HH:MM. EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp)); EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp)); @@ -857,29 +1351,76 @@ TEST(Parse, ExtendedOffset) { EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp)); - // %Ez against +-HHMM. - EXPECT_TRUE(parse("%Ez", "+0000", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse("%Ez", "-1234", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); - EXPECT_TRUE(parse("%Ez", "+1234", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); - EXPECT_FALSE(parse("%Ez", "-123", utc, &tp)); + for (auto fmt : {"%Ez", "%z"}) { + EXPECT_TRUE(parse(fmt, "+0000", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-1234", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "+1234", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); + EXPECT_FALSE(parse(fmt, "-123", utc, &tp)); + + EXPECT_TRUE(parse(fmt, "+00", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-12", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "+12", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp); + EXPECT_FALSE(parse(fmt, "-1", utc, &tp)); + } +} - // %Ez against +-HH. - EXPECT_TRUE(parse("%Ez", "+00", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); - EXPECT_TRUE(parse("%Ez", "-12", utc, &tp)); - EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp); - EXPECT_TRUE(parse("%Ez", "+12", utc, &tp)); - EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp); - EXPECT_FALSE(parse("%Ez", "-1", utc, &tp)); +TEST(Parse, ExtendedSecondOffset) { + const time_zone utc = utc_time_zone(); + time_point tp; + + for (auto fmt : {"%Ez", "%E*z", "%:z", "%::z", "%:::z"}) { + EXPECT_TRUE(parse(fmt, "+00:00:00", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-12:34:56", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp); + EXPECT_TRUE(parse(fmt, "+12:34:56", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp); + EXPECT_FALSE(parse(fmt, "-12:34:5", utc, &tp)); + + EXPECT_TRUE(parse(fmt, "+000000", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-123456", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp); + EXPECT_TRUE(parse(fmt, "+123456", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp); + EXPECT_FALSE(parse(fmt, "-12345", utc, &tp)); + + EXPECT_TRUE(parse(fmt, "+00:00", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-12:34", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "+12:34", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); + EXPECT_FALSE(parse(fmt, "-12:3", utc, &tp)); + + EXPECT_TRUE(parse(fmt, "+0000", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-1234", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "+1234", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); + EXPECT_FALSE(parse(fmt, "-123", utc, &tp)); + + EXPECT_TRUE(parse(fmt, "+00", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-12", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "+12", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp); + EXPECT_FALSE(parse(fmt, "-1", utc, &tp)); + } } TEST(Parse, ExtendedYears) { const time_zone utc = utc_time_zone(); const char e4y_fmt[] = "%E4Y%m%d"; // no separators - time_point tp; + time_point tp; // %E4Y consumes exactly four chars, including any sign. EXPECT_TRUE(parse(e4y_fmt, "-9991127", utc, &tp)); @@ -910,14 +1451,239 @@ TEST(Parse, ExtendedYears) { TEST(Parse, RFC3339Format) { const time_zone tz = utc_time_zone(); - time_point tp; + time_point tp; EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00+00:00", tz, &tp)); ExpectTime(tp, tz, 2014, 2, 12, 20, 21, 0, 0, false, "UTC"); - // Check that %Ez also accepts "Z" as a synonym for "+00:00". - time_point tp2; - EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp2)); + // Check that %ET also accepts "t". + time_point tp2; + EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12t20:21:00+00:00", tz, &tp2)); EXPECT_EQ(tp, tp2); + + // Check that %Ez also accepts "Z" as a synonym for "+00:00". + time_point tp3; + EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp3)); + EXPECT_EQ(tp, tp3); + + // Check that %Ez also accepts "z" as a synonym for "+00:00". + time_point tp4; + EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00z", tz, &tp4)); + EXPECT_EQ(tp, tp4); +} + +TEST(Parse, Week) { + const time_zone utc = utc_time_zone(); + time_point tp; + + auto exp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2017-01-7", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2017-00-0", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2017-53-7", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2017-52-0", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2018-00-1", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2018-01-1", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2018-52-1", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2018-53-1", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2019-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2019-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2019-52-2", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2019-52-2", utc, &tp)); + EXPECT_EQ(exp, tp); +} + +TEST(Parse, WeekYearShift) { + // %U/%W conversions with week values in {0, 52, 53} can slip + // into the previous/following calendar years. + const time_zone utc = utc_time_zone(); + time_point tp; + + auto exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2020-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2020-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2021, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2020-52-5", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp)); + EXPECT_EQ(exp, tp); + + // Slipping into the previous/following calendar years should fail when + // we're already at the extremes. + EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp)); + EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp)); +} + +TEST(Parse, NULsInFormatAndInputStrings) { + const time_zone utc = utc_time_zone(); + time_point tp; + + // Check that NULs are parsed just like any other chars. + EXPECT_FALSE( + parse(std::string("abc\0def", 7), std::string("abc\0xyz", 7), utc, &tp)); + EXPECT_FALSE( + parse(std::string("%Y\0def", 6), std::string("2026\0xyz", 8), utc, &tp)); + EXPECT_TRUE( + parse(std::string("%Y\0xyz", 6), std::string("2026\0xyz", 8), utc, &tp)); + ExpectTime(tp, utc, 2026, 1, 1, 0, 0, 0, 0, false, "UTC"); + + // All NULs. + std::string nuls(32, '\0'); + EXPECT_TRUE(parse(nuls, nuls, utc, &tp)); + ExpectTime(tp, utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + + // The "%\0" specifier never matches, even on the empty string and itself. + std::string percent_nul("%\0", 2); + EXPECT_FALSE(parse(percent_nul, "", utc, &tp)); + EXPECT_FALSE(parse(percent_nul, percent_nul, utc, &tp)); + +#if defined(__linux__) && defined(__GLIBC__) + // Depending upon strptime() behavior on "%E" + // and "%O", "%E\0" and "%0\0" also never match. + std::string percent_E_nul("%E\0", 3); + EXPECT_FALSE(parse(percent_E_nul, "", utc, &tp)); + EXPECT_FALSE(parse(percent_E_nul, percent_E_nul, utc, &tp)); + std::string percent_O_nul("%O\0", 3); + EXPECT_FALSE(parse(percent_O_nul, "", utc, &tp)); + EXPECT_FALSE(parse(percent_O_nul, percent_O_nul, utc, &tp)); +#endif +} + +TEST(Parse, MaxRange) { + const time_zone utc = utc_time_zone(); + time_point tp; + + // tests the upper limit using +00:00 offset + EXPECT_TRUE( + parse(RFC3339_sec, "292277026596-12-04T15:30:07+00:00", utc, &tp)); + EXPECT_EQ(tp, time_point::max()); + EXPECT_FALSE( + parse(RFC3339_sec, "292277026596-12-04T15:30:08+00:00", utc, &tp)); + + // tests the upper limit using -01:00 offset + EXPECT_TRUE( + parse(RFC3339_sec, "292277026596-12-04T14:30:07-01:00", utc, &tp)); + EXPECT_EQ(tp, time_point::max()); + EXPECT_FALSE( + parse(RFC3339_sec, "292277026596-12-04T14:30:08-01:00", utc, &tp)); + + // tests the lower limit using +00:00 offset + EXPECT_TRUE( + parse(RFC3339_sec, "-292277022657-01-27T08:29:52+00:00", utc, &tp)); + EXPECT_EQ(tp, time_point::min()); + EXPECT_FALSE( + parse(RFC3339_sec, "-292277022657-01-27T08:29:51+00:00", utc, &tp)); + + // tests the lower limit using +01:00 offset + EXPECT_TRUE( + parse(RFC3339_sec, "-292277022657-01-27T09:29:52+01:00", utc, &tp)); + EXPECT_EQ(tp, time_point::min()); + EXPECT_FALSE( + parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp)); + + // tests max/min civil-second overflow + EXPECT_FALSE(parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01", + utc, &tp)); + EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01", + utc, &tp)); +} + +TEST(Parse, TimePointOverflow) { + const time_zone utc = utc_time_zone(); + + using D = chrono::duration; + time_point tp; + + EXPECT_TRUE( + parse(RFC3339_full, "2262-04-11T23:47:16.8547758079+00:00", utc, &tp)); + EXPECT_EQ(tp, time_point::max()); + EXPECT_EQ("2262-04-11T23:47:16.854775807+00:00", + cctz::format(RFC3339_full, tp, utc)); +#if 0 + // TODO(#199): Will fail until cctz::parse() properly detects overflow. + EXPECT_FALSE( + parse(RFC3339_full, "2262-04-11T23:47:16.8547758080+00:00", utc, &tp)); + EXPECT_TRUE( + parse(RFC3339_full, "1677-09-21T00:12:43.1452241920+00:00", utc, &tp)); + EXPECT_EQ(tp, time_point::min()); + EXPECT_EQ("1677-09-21T00:12:43.145224192+00:00", + cctz::format(RFC3339_full, tp, utc)); + EXPECT_FALSE( + parse(RFC3339_full, "1677-09-21T00:12:43.1452241919+00:00", utc, &tp)); +#endif + + using DS = chrono::duration; + time_point stp; + + EXPECT_TRUE(parse(RFC3339_full, "1970-01-01T00:02:07.9+00:00", utc, &stp)); + EXPECT_EQ(stp, time_point::max()); + EXPECT_EQ("1970-01-01T00:02:07+00:00", cctz::format(RFC3339_full, stp, utc)); + EXPECT_FALSE(parse(RFC3339_full, "1970-01-01T00:02:08+00:00", utc, &stp)); + + EXPECT_TRUE(parse(RFC3339_full, "1969-12-31T23:57:52+00:00", utc, &stp)); + EXPECT_EQ(stp, time_point::min()); + EXPECT_EQ("1969-12-31T23:57:52+00:00", cctz::format(RFC3339_full, stp, utc)); + EXPECT_FALSE(parse(RFC3339_full, "1969-12-31T23:57:51.9+00:00", utc, &stp)); + + using DM = chrono::duration; + time_point mtp; + + EXPECT_TRUE(parse(RFC3339_full, "1970-01-01T02:07:59+00:00", utc, &mtp)); + EXPECT_EQ(mtp, time_point::max()); + EXPECT_EQ("1970-01-01T02:07:00+00:00", cctz::format(RFC3339_full, mtp, utc)); + EXPECT_FALSE(parse(RFC3339_full, "1970-01-01T02:08:00+00:00", utc, &mtp)); + + EXPECT_TRUE(parse(RFC3339_full, "1969-12-31T21:52:00+00:00", utc, &mtp)); + EXPECT_EQ(mtp, time_point::min()); + EXPECT_EQ("1969-12-31T21:52:00+00:00", cctz::format(RFC3339_full, mtp, utc)); + EXPECT_FALSE(parse(RFC3339_full, "1969-12-31T21:51:59+00:00", utc, &mtp)); +} + +TEST(Parse, TimePointOverflowFloor) { + const time_zone utc = utc_time_zone(); + + using D = chrono::duration; + time_point tp; + + EXPECT_TRUE( + parse(RFC3339_full, "294247-01-10T04:00:54.7758079+00:00", utc, &tp)); + EXPECT_EQ(tp, time_point::max()); + EXPECT_EQ("294247-01-10T04:00:54.775807+00:00", + cctz::format(RFC3339_full, tp, utc)); +#if 0 + // TODO(#199): Will fail until cctz::parse() properly detects overflow. + EXPECT_FALSE( + parse(RFC3339_full, "294247-01-10T04:00:54.7758080+00:00", utc, &tp)); + EXPECT_TRUE( + parse(RFC3339_full, "-290308-12-21T19:59:05.2241920+00:00", utc, &tp)); + EXPECT_EQ(tp, time_point::min()); + EXPECT_EQ("-290308-12-21T19:59:05.224192+00:00", + cctz::format(RFC3339_full, tp, utc)); + EXPECT_FALSE( + parse(RFC3339_full, "-290308-12-21T19:59:05.2241919+00:00", utc, &tp)); +#endif } // @@ -928,33 +1694,64 @@ TEST(FormatParse, RoundTrip) { time_zone lax; EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax)); const auto in = convert(civil_second(1977, 6, 28, 9, 8, 7), lax); - const auto subseconds = nanoseconds(654321); + const auto subseconds = chrono::nanoseconds(654321); + + // No format specifiers, but include NUL. + { + time_point out; + const auto fmt = std::string("\0\1\2\3\4\5\6\7abcdefgh01234567"); + const auto s = cctz::format(fmt, in, lax); + EXPECT_TRUE(parse(fmt, s, lax, &out)) << s; + } // RFC3339, which renders subseconds. { - time_point out; - const std::string s = format(RFC3339_full, in + subseconds, lax); + time_point out; + const auto s = cctz::format(RFC3339_full, in + subseconds, lax); EXPECT_TRUE(parse(RFC3339_full, s, lax, &out)) << s; EXPECT_EQ(in + subseconds, out); // RFC3339_full includes %Ez } // RFC1123, which only does whole seconds. { - time_point out; - const std::string s = format(RFC1123_full, in, lax); + time_point out; + const auto s = cctz::format(RFC1123_full, in, lax); EXPECT_TRUE(parse(RFC1123_full, s, lax, &out)) << s; EXPECT_EQ(in, out); // RFC1123_full includes %z } +#if defined(_WIN32) || defined(_WIN64) + // Initial investigations indicate the %c does not roundtrip on Windows. + // TODO: Figure out what is going on here (perhaps a locale problem). +#else // Even though we don't know what %c will produce, it should roundtrip, // but only in the 0-offset timezone. { - time_point out; + time_point out; time_zone utc = utc_time_zone(); - const std::string s = format("%c", in, utc); + const auto s = cctz::format("%c", in, utc); EXPECT_TRUE(parse("%c", s, utc, &out)) << s; EXPECT_EQ(in, out); } +#endif +} + +TEST(FormatParse, RoundTripDistantFuture) { + const time_zone utc = utc_time_zone(); + const time_point in = time_point::max(); + const std::string s = cctz::format(RFC3339_full, in, utc); + time_point out; + EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s; + EXPECT_EQ(in, out); +} + +TEST(FormatParse, RoundTripDistantPast) { + const time_zone utc = utc_time_zone(); + const time_point in = time_point::min(); + const std::string s = cctz::format(RFC3339_full, in, utc); + time_point out; + EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s; + EXPECT_EQ(in, out); } } // namespace cctz diff --git a/src/time_zone_fuzz_test.cc b/src/time_zone_fuzz_test.cc new file mode 100644 index 000000000..cf6dc56fe --- /dev/null +++ b/src/time_zone_fuzz_test.cc @@ -0,0 +1,76 @@ +// Copyright 2025 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include + +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" +#include "fuzztest/fuzztest.h" +#include "gtest/gtest.h" +#include "test_time_zone_names.h" +#include "time_zone_impl.h" + +namespace cctz { + +namespace { + +std::vector TimeZoneSeeds() { + std::vector time_zone_seeds; + for (const char* const* tzptr = kTimeZoneNames; *tzptr != nullptr; ++tzptr) { + time_zone_seeds.push_back(*tzptr); + } + return time_zone_seeds; +} + +void Fuzz(const std::string& time_zone_name, const std::int64_t year, + const std::int64_t month, const std::int64_t day, + const std::int64_t hour, const std::int64_t minute, + const std::int64_t second, const std::string& format_string, + const std::string& cctz_parse_input) { + cctz::time_zone time_zone; + if (!cctz::load_time_zone(time_zone_name, &time_zone)) { + return; + } + const cctz::civil_second cs(year, month, day, hour, minute, second); + auto time_point = cctz::convert(cs, time_zone); + cctz::format(format_string, time_point, time_zone); + cctz::time_point parsed_time_point; + cctz::parse(format_string, cctz_parse_input, time_zone, &parsed_time_point); + auto repeated_time_point = cctz::convert(cs, time_zone); + EXPECT_EQ(time_point, repeated_time_point); +} + +FUZZ_TEST(TimeZoneFuzzTest, Fuzz) + .WithDomains(fuzztest::Arbitrary().WithSeeds(TimeZoneSeeds()), + // We limit the search-space for years to avoid expected + // undefined behavior that may occur when normalizing a civil + // second outside the 64-bit representable year range. + fuzztest::InRange(std::numeric_limits::min() / 2, + std::numeric_limits::max() / + 2), // year + fuzztest::Arbitrary(), // month + fuzztest::Arbitrary(), // day + fuzztest::Arbitrary(), // hour + fuzztest::Arbitrary(), // minute + fuzztest::Arbitrary(), // second + fuzztest::Arbitrary(), // format_string + fuzztest::Arbitrary()); // cctz_parse_input + +} // namespace + +} // namespace cctz diff --git a/src/time_zone_if.cc b/src/time_zone_if.cc index 675474be0..2de47ff51 100644 --- a/src/time_zone_if.cc +++ b/src/time_zone_if.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -18,17 +18,24 @@ namespace cctz { -std::unique_ptr TimeZoneIf::Load(const std::string& name) { +std::unique_ptr TimeZoneIf::UTC() { + return TimeZoneInfo::UTC(); +} + +std::unique_ptr TimeZoneIf::Make(const std::string& name) { // Support "libc:localtime" and "libc:*" to access the legacy // localtime and UTC support respectively from the C library. + // NOTE: The "libc:*" zones are internal, test-only interfaces, and + // are subject to change/removal without notice. Do not use them. if (name.compare(0, 5, "libc:") == 0) { - return std::unique_ptr(new TimeZoneLibC(name.substr(5))); + return TimeZoneLibC::Make(name.substr(5)); } - // Otherwise use the "zoneinfo" implementation by default. - std::unique_ptr tz(new TimeZoneInfo); - if (!tz->Load(name)) tz.reset(); - return std::unique_ptr(tz.release()); + // Otherwise use the "zoneinfo" implementation. + return TimeZoneInfo::Make(name); } +// Defined out-of-line to avoid emitting a weak vtable in all TUs. +TimeZoneIf::~TimeZoneIf() {} + } // namespace cctz diff --git a/src/time_zone_if.h b/src/time_zone_if.h index 57a6cde78..8c19e1217 100644 --- a/src/time_zone_if.h +++ b/src/time_zone_if.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -15,77 +15,56 @@ #ifndef CCTZ_TIME_ZONE_IF_H_ #define CCTZ_TIME_ZONE_IF_H_ +#include #include #include #include -#include "civil_time.h" -#include "time_zone.h" +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" namespace cctz { -// The calendar and wall-clock (a.k.a. "civil time") components of a -// time_point in a certain time_zone. A better std::tm. Note that we -// cannot use time_zone::absolute_lookup because we need a 64-bit year. -struct Breakdown { - int64_t year; // year (e.g., 2013) - int month; // month of year [1:12] - int day; // day of month [1:31] - int hour; // hour of day [0:23] - int minute; // minute of hour [0:59] - int second; // second of minute [0:59] - int weekday; // 1==Mon, ..., 7=Sun - int yearday; // day of year [1:366] - - // Note: The following fields exist for backward compatibility with older - // APIs. Accessing these fields directly is a sign of imprudent logic in the - // calling code. Modern time-related code should only access this data - // indirectly by way of cctz::format(). - int offset; // seconds east of UTC - bool is_dst; // is offset non-standard? - std::string abbr; // time-zone abbreviation (e.g., "PST") -}; - -// A TimeInfo represents the conversion of year, month, day, hour, minute, -// and second values in a particular time_zone to a time instant. -struct TimeInfo { - time_zone::civil_lookup::civil_kind kind; - time_point pre; // Uses the pre-transition offset - time_point trans; - time_point post; // Uses the post-transition offset - bool normalized; -}; - // A simple interface used to hide time-zone complexities from time_zone::Impl. // Subclasses implement the functions for civil-time conversions in the zone. class TimeZoneIf { public: - // A factory function for TimeZoneIf implementations. - static std::unique_ptr Load(const std::string& name); + // Factory functions for TimeZoneIf implementations. + static std::unique_ptr UTC(); // never fails + static std::unique_ptr Make(const std::string& name); + + virtual ~TimeZoneIf(); - virtual ~TimeZoneIf() {} + virtual time_zone::absolute_lookup BreakTime( + const time_point& tp) const = 0; + virtual time_zone::civil_lookup MakeTime( + const civil_second& cs) const = 0; - virtual Breakdown BreakTime(const time_point& tp) const = 0; - virtual TimeInfo MakeTimeInfo(int64_t year, int mon, int day, - int hour, int min, int sec) const = 0; + virtual bool NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const = 0; + virtual bool PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const = 0; + + virtual std::string Version() const = 0; + virtual std::string Description() const = 0; protected: - TimeZoneIf() {} + TimeZoneIf() = default; + TimeZoneIf(const TimeZoneIf&) = delete; + TimeZoneIf& operator=(const TimeZoneIf&) = delete; }; -// Converts tp to a count of seconds since the Unix epoch. -inline int64_t ToUnixSeconds(const time_point& tp) { - return (tp - std::chrono::time_point_cast( - std::chrono::system_clock::from_time_t(0))) - .count(); +// Convert between time_point and a count of seconds since the +// Unix epoch. We assume that the std::chrono::system_clock and the +// Unix clock are second aligned, and that the results are representable. +// (That is, that they share an epoch, which is required since C++20.) +inline std::int_fast64_t ToUnixSeconds(const time_point& tp) { + return (tp - std::chrono::time_point_cast( + std::chrono::system_clock::from_time_t(0))).count(); } - -// Converts a count of seconds since the Unix epoch to a -// time_point. -inline time_point FromUnixSeconds(int64_t t) { - return std::chrono::time_point_cast( - std::chrono::system_clock::from_time_t(0)) + - sys_seconds(t); +inline time_point FromUnixSeconds(std::int_fast64_t t) { + return std::chrono::time_point_cast( + std::chrono::system_clock::from_time_t(0)) + seconds(t); } } // namespace cctz diff --git a/src/time_zone_impl.cc b/src/time_zone_impl.cc index 9eef9ea94..d72f9e007 100644 --- a/src/time_zone_impl.cc +++ b/src/time_zone_impl.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -14,113 +14,97 @@ #include "time_zone_impl.h" -#include +#include +#include #include +#include +#include +#include + +#include "time_zone_fixed.h" namespace cctz { namespace { // time_zone::Impls are linked into a map to support fast lookup by name. -typedef std::map TimeZoneImplByName; +using TimeZoneImplByName = + std::unordered_map; TimeZoneImplByName* time_zone_map = nullptr; // Mutual exclusion for time_zone_map. -std::mutex time_zone_mutex; - -// The utc_time_zone(). Also used for time zones that fail to load. -const time_zone::Impl* utc_zone = nullptr; - -// utc_zone should only be referenced in a thread that has just done -// a LoadUTCTimeZone(). -std::once_flag load_utc_once; -void LoadUTCTimeZone() { - std::call_once(load_utc_once, []() { utc_time_zone(); }); +std::mutex& TimeZoneMutex() { + // This mutex is intentionally "leaked" to avoid the static deinitialization + // order fiasco (std::mutex's destructor is not trivial on many platforms). + static std::mutex* time_zone_mutex = new std::mutex; + return *time_zone_mutex; } } // namespace +time_zone time_zone::Impl::UTC() { + return time_zone(UTCImpl()); +} + bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { - const bool is_utc = (name.compare("UTC") == 0); + const Impl* const utc_impl = UTCImpl(); + + // Check for UTC (which is never a key in time_zone_map). + auto offset = seconds::zero(); + if (FixedOffsetFromName(name, &offset) && offset == seconds::zero()) { + *tz = time_zone(utc_impl); + return true; + } - // First check, under a shared lock, whether the time zone has already - // been loaded. This is the common path. TODO: Move to shared_mutex. + // Check whether the time zone has already been loaded. { - std::lock_guard lock(time_zone_mutex); + std::lock_guard lock(TimeZoneMutex()); if (time_zone_map != nullptr) { TimeZoneImplByName::const_iterator itr = time_zone_map->find(name); if (itr != time_zone_map->end()) { *tz = time_zone(itr->second); - return is_utc || itr->second != utc_zone; + return itr->second != utc_impl; } } } - if (!is_utc) { - // Ensure that UTC is loaded before any other time zones. - LoadUTCTimeZone(); - } + // Load the new time zone (outside the lock). + std::unique_ptr new_impl(new Impl(name)); - // Now check again, under an exclusive lock. - std::lock_guard lock(time_zone_mutex); + // Add the new time zone to the map. + std::lock_guard lock(TimeZoneMutex()); if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName; - const time_zone::Impl*& impl = (*time_zone_map)[name]; - bool fallback_utc = false; - if (impl == nullptr) { - // The first thread in loads the new time zone. - time_zone::Impl* new_impl = new time_zone::Impl(name); - new_impl->zone_ = TimeZoneIf::Load(new_impl->name_); - if (new_impl->zone_ == nullptr) { - delete new_impl; // free the nascent time_zone::Impl - impl = utc_zone; // and fallback to UTC - fallback_utc = true; - } else { - if (is_utc) { - // Happens before any reference to utc_zone. - utc_zone = new_impl; - } - impl = new_impl; // install new time zone - } + const Impl*& impl = (*time_zone_map)[name]; + if (impl == nullptr) { // this thread won any load race + impl = new_impl->zone_ ? new_impl.release() : utc_impl; } *tz = time_zone(impl); - return !fallback_utc; + return impl != utc_impl; } -const time_zone::Impl& time_zone::Impl::get(const time_zone& tz) { - if (tz.impl_ == nullptr) { - // Dereferencing an implicit-UTC time_zone is expected to be - // rare, so we don't mind paying a small synchronization cost. - LoadUTCTimeZone(); - return *utc_zone; +void time_zone::Impl::ClearTimeZoneMapTestOnly() { + std::lock_guard lock(TimeZoneMutex()); + if (time_zone_map != nullptr) { + // Existing time_zone::Impl* entries are in the wild, so we can't delete + // them. Instead, we move them to a private container, where they are + // logically unreachable but not "leaked". Future requests will result + // in reloading the data. + static auto* cleared = new std::deque; + for (const auto& element : *time_zone_map) { + cleared->push_back(element.second); + } + time_zone_map->clear(); } - return *tz.impl_; } -time_zone::Impl::Impl(const std::string& name) : name_(name) {} - -time_zone::absolute_lookup time_zone::Impl::BreakTime( - const time_point& tp) const { - time_zone::absolute_lookup res; - Breakdown bd = zone_->BreakTime(tp); - // TODO: Eliminate extra normalization. - res.cs = - civil_second(bd.year, bd.month, bd.day, bd.hour, bd.minute, bd.second); - res.offset = bd.offset; - res.is_dst = bd.is_dst; - res.abbr = bd.abbr; - return res; -} +time_zone::Impl::Impl() : name_("UTC"), zone_(TimeZoneIf::UTC()) {} + +time_zone::Impl::Impl(const std::string& name) + : name_(name), zone_(TimeZoneIf::Make(name_)) {} -time_zone::civil_lookup time_zone::Impl::MakeTimeInfo(civil_second cs) const { - time_zone::civil_lookup res; - // TODO: Eliminate extra normalization. - TimeInfo t = zone_->MakeTimeInfo(cs.year(), cs.month(), cs.day(), - cs.hour(), cs.minute(), cs.second()); - res.kind = t.kind; - res.pre = t.pre; - res.trans = t.trans; - res.post = t.post; - return res; +const time_zone::Impl* time_zone::Impl::UTCImpl() { + static const Impl* utc_impl = new Impl; + return utc_impl; } } // namespace cctz diff --git a/src/time_zone_impl.h b/src/time_zone_impl.h index 67b2f35e1..8902614ab 100644 --- a/src/time_zone_impl.h +++ b/src/time_zone_impl.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -18,7 +18,9 @@ #include #include -#include "time_zone.h" +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" +#include "time_zone_if.h" #include "time_zone_info.h" namespace cctz { @@ -26,23 +28,58 @@ namespace cctz { // time_zone::Impl is the internal object referenced by a cctz::time_zone. class time_zone::Impl { public: + // The UTC time zone. Also used for other time zones that fail to load. + static time_zone UTC(); + // Load a named time zone. Returns false if the name is invalid, or if // some other kind of error occurs. Note that loading "UTC" never fails. static bool LoadTimeZone(const std::string& name, time_zone* tz); - // Dereferences the time_zone to obtain its Impl. - static const time_zone::Impl& get(const time_zone& tz); + // Clears the map of cached time zones. Primarily for use in benchmarks + // that gauge the performance of loading/parsing the time-zone data. + static void ClearTimeZoneMapTestOnly(); + + // The primary key is the time-zone ID (e.g., "America/New_York"). + const std::string& Name() const { + // TODO: It would nice if the zoneinfo data included the zone name. + return name_; + } // Breaks a time_point down to civil-time components in this time zone. - time_zone::absolute_lookup BreakTime(const time_point& tp) const; + time_zone::absolute_lookup BreakTime(const time_point& tp) const { + return zone_->BreakTime(tp); + } // Converts the civil-time components in this time zone into a time_point. // That is, the opposite of BreakTime(). The requested civil time may be // ambiguous or illegal due to a change of UTC offset. - time_zone::civil_lookup MakeTimeInfo(civil_second cs) const; + time_zone::civil_lookup MakeTime(const civil_second& cs) const { + return zone_->MakeTime(cs); + } + + // Finds the time of the next/previous offset change in this time zone. + bool NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const { + return zone_->NextTransition(tp, trans); + } + bool PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const { + return zone_->PrevTransition(tp, trans); + } + + // Returns an implementation-defined version string for this time zone. + std::string Version() const { return zone_->Version(); } + + // Returns an implementation-defined description of this time zone. + std::string Description() const { return zone_->Description(); } private: + Impl(); explicit Impl(const std::string& name); + Impl(const Impl&) = delete; + Impl& operator=(const Impl&) = delete; + + static const Impl* UTCImpl(); const std::string name_; std::unique_ptr zone_; diff --git a/src/time_zone_info.cc b/src/time_zone_info.cc index 346f42c7c..cc4b00119 100644 --- a/src/time_zone_info.cc +++ b/src/time_zone_info.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -25,7 +25,7 @@ // a grain of salt. // // For more information see tzfile(5), http://www.iana.org/time-zones, or -// http://en.wikipedia.org/wiki/Zoneinfo. +// https://en.wikipedia.org/wiki/Zoneinfo. // // Note that we assume the proleptic Gregorian calendar and 60-second // minutes throughout. @@ -33,205 +33,170 @@ #include "time_zone_info.h" #include -#include +#include #include #include #include #include #include -#include -#include - +#include +#include +#include +#include +#include +#include +#include + +#include "cctz/civil_time.h" +#include "time_zone_fixed.h" #include "time_zone_posix.h" namespace cctz { namespace { -// Convert errnum to a message, using buf[buflen] if necessary. -// buf must be non-null, and buflen non-zero. -char* errmsg(int errnum, char* buf, size_t buflen) { -#if defined(_WIN32) || defined(_WIN64) - strerror_s(buf, buflen, errnum); - return buf; -#elif defined(__APPLE__) - strerror_r(errnum, buf, buflen); - return buf; -#elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE - strerror_r(errnum, buf, buflen); - return buf; -#else - return strerror_r(errnum, buf, buflen); -#endif +inline bool IsLeap(year_t year) { + return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0); } -// Wrap the tzfile.h isleap() macro with an inline function, which will -// then have normal argument-passing semantics (i.e., single evaluation). -inline bool IsLeap(int64_t year) { return isleap(year); } +// The number of days in non-leap and leap years respectively. +const std::int_least32_t kDaysPerYear[2] = {365, 366}; -// The month lengths in non-leap and leap years respectively. -const int8_t kDaysPerMonth[2][1 + MONSPERYEAR] = { - {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {-1, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, -}; - -// The day offsets of the beginning of each (1-based) month in non-leap -// and leap years respectively. That is, sigma[1:n]:kDaysPerMonth[][i]. -// For example, in a leap year there are 335 days before December. -const int16_t kMonthOffsets[2][1 + MONSPERYEAR + 1] = { +// The day offsets of the beginning of each (1-based) month in non-leap and +// leap years respectively (e.g., 335 days before December in a leap year). +const std::int_least16_t kMonthOffsets[2][1 + 12 + 1] = { {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}, }; +// We reject leap-second encoded zoneinfo and so assume 60-second minutes. +const std::int_least32_t kSecsPerDay = 24 * 60 * 60; + // 400-year chunks always have 146097 days (20871 weeks). -const int64_t kSecPer400Years = 146097LL * SECSPERDAY; +const std::int_least64_t kSecsPer400Years = 146097LL * kSecsPerDay; -// The number of seconds in an aligned 100-year chunk, for those that -// do not begin with a leap year and those that do respectively. -const int64_t kSecPer100Years[2] = { - (76LL * DAYSPERNYEAR + 24LL * DAYSPERLYEAR) * SECSPERDAY, - (75LL * DAYSPERNYEAR + 25LL * DAYSPERLYEAR) * SECSPERDAY, +// Like kDaysPerYear[] but scaled up by a factor of kSecsPerDay. +const std::int_least32_t kSecsPerYear[2] = { + 365 * kSecsPerDay, + 366 * kSecsPerDay, }; -// The number of seconds in an aligned 4-year chunk, for those that -// do not begin with a leap year and those that do respectively. -const int32_t kSecPer4Years[2] = { - (4 * DAYSPERNYEAR + 0 * DAYSPERLYEAR) * SECSPERDAY, - (3 * DAYSPERNYEAR + 1 * DAYSPERLYEAR) * SECSPERDAY, -}; +// Convert a cctz::weekday to a POSIX TZ weekday number (0==Sun, ..., 6=Sat). +inline int ToPosixWeekday(weekday wd) { + switch (wd) { + case weekday::sunday: + return 0; + case weekday::monday: + return 1; + case weekday::tuesday: + return 2; + case weekday::wednesday: + return 3; + case weekday::thursday: + return 4; + case weekday::friday: + return 5; + case weekday::saturday: + return 6; + } + return 0; /*NOTREACHED*/ +} -// The number of seconds in non-leap and leap years respectively. -const int32_t kSecPerYear[2] = { - DAYSPERNYEAR * SECSPERDAY, - DAYSPERLYEAR * SECSPERDAY, -}; +// Single-byte, unsigned numeric values are encoded directly. +inline std::uint_fast8_t Decode8(const char* cp) { + return static_cast(*cp) & 0xff; +} -// The number of days in the 100 years starting in the mod-400 index year, -// stored as a 36524-deficit value (i.e., 0 == 36524, 1 == 36525). -const int8_t kDaysPer100Years[401] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -}; +// Multi-byte, numeric values are encoded using a MSB first, +// twos-complement representation. These helpers decode, from +// the given address, 4-byte and 8-byte values respectively. +// Note: If int_fastXX_t == intXX_t and this machine is not +// twos complement, then there will be at least one input value +// we cannot represent. +std::int_fast32_t Decode32(const char* cp) { + std::uint_fast32_t v = 0; + for (int i = 0; i != (32 / 8); ++i) v = (v << 8) | Decode8(cp++); + const std::int_fast32_t s32max = 0x7fffffff; + const auto s32maxU = static_cast(s32max); + if (v <= s32maxU) return static_cast(v); + return static_cast(v - s32maxU - 1) - s32max - 1; +} + +std::int_fast64_t Decode64(const char* cp) { + std::uint_fast64_t v = 0; + for (int i = 0; i != (64 / 8); ++i) v = (v << 8) | Decode8(cp++); + const std::int_fast64_t s64max = 0x7fffffffffffffff; + const auto s64maxU = static_cast(s64max); + if (v <= s64maxU) return static_cast(v); + return static_cast(v - s64maxU - 1) - s64max - 1; +} + +struct Header { // counts of: + std::size_t timecnt; // transition times + std::size_t typecnt; // transition types + std::size_t charcnt; // zone abbreviation characters + std::size_t leapcnt; // leap seconds (we expect none) + std::size_t ttisstdcnt; // UTC/local indicators (unused) + std::size_t ttisutcnt; // standard/wall indicators (unused) -inline int DaysPer100Years(int eyear) { - return 36524 + kDaysPer100Years[eyear]; -} - -// The number of days in the 4 years starting in the mod-400 index year, -// stored as a 1460-deficit value (i.e., 0 == 1460, 1 == 1461). -const int8_t kDaysPer4Years[401] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + bool Build(const tzhead& tzh); + std::size_t DataLength(std::size_t time_len) const; }; -inline int DaysPer4Years(int eyear) { return 1460 + kDaysPer4Years[eyear]; } - -// Like kSecPerYear[] but scaled down by a factor of SECSPERDAY. -const int32_t kDaysPerYear[2] = {DAYSPERNYEAR, DAYSPERLYEAR}; - -inline int DaysPerYear(int year) { return kDaysPerYear[IsLeap(year)]; } - -// Map a (normalized) Y/M/D to the number of days before/after 1970-01-01. -// See http://howardhinnant.github.io/date_algorithms.html#days_from_civil. -int64_t DayOrdinal(int64_t year, int month, int day) { - year -= (month <= 2 ? 1 : 0); - const int64_t era = (year >= 0 ? year : year - 399) / 400; - const int yoe = static_cast(year - era * 400); - const int doy = (153 * (month + (month > 2 ? -3 : 9)) + 2) / 5 + day - 1; - const int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; - return era * 146097 + doe - 719468; // shift epoch to 1970-01-01 -} - -// Normalize (*valp + carry_in) so that [zero <= *valp < (zero + base)], -// returning multiples of base to carry out. "zero" must be >= 0, and -// base must be sufficiently large to avoid overflowing the return value. -// Inlining admits significant gains as base and zero are literals. -inline int NormalizeField(int base, int zero, int* valp, int carry_in) { - int carry_out = 0; - int val = *valp; - if (zero != 0 && val < 0) { - val += base; - carry_out -= 1; - } - val -= zero; - carry_out += val / base; - int rem = val % base; - if (carry_in != 0) { - carry_out += carry_in / base; - rem += carry_in % base; - if (rem < 0) { - carry_out -= 1; - rem += base; - } else if (rem >= base) { - carry_out += 1; - rem -= base; - } - } - if (rem < 0) { - carry_out -= 1; - rem += base; - } - *valp = rem + zero; - return carry_out; +// Builds the in-memory header using the raw bytes from the file. +bool Header::Build(const tzhead& tzh) { + std::int_fast32_t v; + if ((v = Decode32(tzh.tzh_timecnt)) < 0) return false; + timecnt = static_cast(v); + if ((v = Decode32(tzh.tzh_typecnt)) < 0) return false; + typecnt = static_cast(v); + if ((v = Decode32(tzh.tzh_charcnt)) < 0) return false; + charcnt = static_cast(v); + if ((v = Decode32(tzh.tzh_leapcnt)) < 0) return false; + leapcnt = static_cast(v); + if ((v = Decode32(tzh.tzh_ttisstdcnt)) < 0) return false; + ttisstdcnt = static_cast(v); + if ((v = Decode32(tzh.tzh_ttisutcnt)) < 0) return false; + ttisutcnt = static_cast(v); + return true; } -// Multi-byte, numeric values are encoded using a MSB first, -// twos-complement representation. These helpers decode, from -// the given address, 4-byte and 8-byte values respectively. -int32_t Decode32(const char* cp) { - uint32_t v = 0; - for (int i = 0; i != (32 / 8); ++i) - v = (v << 8) | (static_cast(*cp++) & 0xff); - if ((v & ~(UINT32_MAX >> 1)) == 0) return v; - return -static_cast(~v) - 1; +// How many bytes of data are associated with this header. The result +// depends upon whether this is a section with 4-byte or 8-byte times. +std::size_t Header::DataLength(std::size_t time_len) const { + std::size_t len = 0; + len += (time_len + 1) * timecnt; // unix_time + type_index + len += (4 + 1 + 1) * typecnt; // utc_offset + is_dst + abbr_index + len += 1 * charcnt; // abbreviations + len += (time_len + 4) * leapcnt; // leap-time + TAI-UTC + len += 1 * ttisstdcnt; // UTC/local indicators + len += 1 * ttisutcnt; // standard/wall indicators + return len; } -int64_t Decode64(const char* cp) { - uint64_t v = 0; - for (int i = 0; i != (64 / 8); ++i) - v = (v << 8) | (static_cast(*cp++) & 0xff); - if ((v & ~(UINT64_MAX >> 1)) == 0) return v; - return -static_cast(~v) - 1; +// Does the rule for future transitions call for year-round daylight time? +// See tz/zic.c:stringzone() for the details on how such rules are encoded. +bool AllYearDST(const PosixTimeZone& posix) { + if (posix.dst_start.date.fmt != PosixTransition::N) return false; + if (posix.dst_start.date.n.day != 0) return false; + if (posix.dst_start.time.offset != 0) return false; + + if (posix.dst_end.date.fmt != PosixTransition::J) return false; + if (posix.dst_end.date.j.day != kDaysPerYear[0]) return false; + const auto offset = posix.std_offset - posix.dst_offset; + if (posix.dst_end.time.offset + offset != kSecsPerDay) return false; + + return true; } // Generate a year-relative offset for a PosixTransition. -int64_t TransOffset(bool leap_year, int jan1_weekday, - const PosixTransition& pt) { - int days = 0; +std::int_fast64_t TransOffset(bool leap_year, int jan1_weekday, + const PosixTransition& pt) { + std::int_fast64_t days = 0; switch (pt.date.fmt) { case PosixTransition::J: { days = pt.date.j.day; - if (!leap_year || days < kMonthOffsets[1][TM_MARCH + 1]) days -= 1; + if (!leap_year || days < kMonthOffsets[1][3]) days -= 1; break; } case PosixTransition::N: { @@ -241,233 +206,477 @@ int64_t TransOffset(bool leap_year, int jan1_weekday, case PosixTransition::M: { const bool last_week = (pt.date.m.week == 5); days = kMonthOffsets[leap_year][pt.date.m.month + last_week]; - const int weekday = (jan1_weekday + days) % DAYSPERWEEK; + const std::int_fast64_t weekday = (jan1_weekday + days) % 7; if (last_week) { - days -= - (weekday + DAYSPERWEEK - 1 - pt.date.m.weekday) % DAYSPERWEEK + 1; + days -= (weekday + 7 - 1 - pt.date.m.weekday) % 7 + 1; } else { - days += (pt.date.m.weekday + DAYSPERWEEK - weekday) % DAYSPERWEEK; - days += (pt.date.m.week - 1) * DAYSPERWEEK; + days += (pt.date.m.weekday + 7 - weekday) % 7; + days += (pt.date.m.week - 1) * 7; } break; } } - return (days * SECSPERDAY) + pt.time.offset; + return (days * kSecsPerDay) + pt.time.offset; } -inline TimeInfo MakeUnique(int64_t unix_time, bool normalized) { - TimeInfo ti; - ti.pre = ti.trans = ti.post = FromUnixSeconds(unix_time); - ti.kind = time_zone::civil_lookup::UNIQUE; - ti.normalized = normalized; - return ti; +inline time_zone::civil_lookup MakeUnique(const time_point& tp) { + time_zone::civil_lookup cl; + cl.kind = time_zone::civil_lookup::UNIQUE; + cl.pre = cl.trans = cl.post = tp; + return cl; } -inline TimeInfo MakeSkipped(const Transition& tr, const DateTime& dt, - bool normalized) { - TimeInfo ti; - ti.pre = FromUnixSeconds(tr.unix_time - 1 + (dt - tr.prev_date_time)); - ti.trans = FromUnixSeconds(tr.unix_time); - ti.post = FromUnixSeconds(tr.unix_time - (tr.date_time - dt)); - ti.kind = time_zone::civil_lookup::SKIPPED; - ti.normalized = normalized; - return ti; +inline time_zone::civil_lookup MakeUnique(std::int_fast64_t unix_time) { + return MakeUnique(FromUnixSeconds(unix_time)); } -inline TimeInfo MakeRepeated(const Transition& tr, const DateTime& dt, - bool normalized) { - TimeInfo ti; - ti.pre = FromUnixSeconds(tr.unix_time - 1 - (tr.prev_date_time - dt)); - ti.trans = FromUnixSeconds(tr.unix_time); - ti.post = FromUnixSeconds(tr.unix_time + (dt - tr.date_time)); - ti.kind = time_zone::civil_lookup::REPEATED; - ti.normalized = normalized; - return ti; +inline time_zone::civil_lookup MakeSkipped(const Transition& tr, + const civil_second& cs) { + time_zone::civil_lookup cl; + cl.kind = time_zone::civil_lookup::SKIPPED; + cl.pre = FromUnixSeconds(tr.unix_time - 1 + (cs - tr.prev_civil_sec)); + cl.trans = FromUnixSeconds(tr.unix_time); + cl.post = FromUnixSeconds(tr.unix_time - (tr.civil_sec - cs)); + return cl; +} + +inline time_zone::civil_lookup MakeRepeated(const Transition& tr, + const civil_second& cs) { + time_zone::civil_lookup cl; + cl.kind = time_zone::civil_lookup::REPEATED; + cl.pre = FromUnixSeconds(tr.unix_time - 1 - (tr.prev_civil_sec - cs)); + cl.trans = FromUnixSeconds(tr.unix_time); + cl.post = FromUnixSeconds(tr.unix_time + (cs - tr.civil_sec)); + return cl; +} + +inline civil_second YearShift(const civil_second& cs, year_t shift) { + return civil_second(cs.year() + shift, cs.month(), cs.day(), + cs.hour(), cs.minute(), cs.second()); } } // namespace -// Normalize from individual date/time fields. -bool DateTime::Normalize(int64_t year, int mon, int day, - int hour, int min, int sec) { - int min_carry = NormalizeField(SECSPERMIN, 0, &sec, 0); - int hour_carry = NormalizeField(MINSPERHOUR, 0, &min, min_carry); - int day_carry = NormalizeField(HOURSPERDAY, 0, &hour, hour_carry); - int year_carry = NormalizeField(MONSPERYEAR, 1, &mon, 0); - bool normalized = min_carry || hour_carry || day_carry || year_carry; - - // Normalize the number of days within a 400-year (146097-day) period. - if (int c4_carry = NormalizeField(146097, 1, &day, day_carry)) { - year_carry += c4_carry * 400; - normalized = true; - } - - // Extract a [0:399] year calendrically equivalent to (year + year_carry) - // from that sum in order to simplify year/day normalization and to defer - // the possibility of int64_t overflow until the final stage. - int eyear = year % 400; - if (year_carry != 0) { eyear += year_carry; eyear %= 400; } - if (eyear < 0) eyear += 400; - year_carry -= eyear; - - int orig_day = day; - if (day > DAYSPERNYEAR) { - eyear += (mon > 2 ? 1 : 0); - if (day > 146097 - DAYSPERNYEAR) { - // We often hit the 400th year when stepping a civil time backwards, - // so special case it to avoid counting up by 100/4/1 year chunks. - day = DaysPerYear(eyear += 400 - 1) - (146097 - day); - } else { - // Handle days in chunks of 100/4/1 years. - for (int ydays = DaysPer100Years(eyear); day > ydays; - day -= ydays, ydays = DaysPer100Years(eyear)) { - if ((eyear += 100) > 400) { eyear -= 400; year_carry += 400; } - } - for (int ydays = DaysPer4Years(eyear); day > ydays; - day -= ydays, ydays = DaysPer4Years(eyear)) { - if ((eyear += 4) > 400) { eyear -= 400; year_carry += 400; } - } - for (int ydays = DaysPerYear(eyear); day > ydays; - day -= ydays, ydays = DaysPerYear(eyear)) { - eyear += 1; - } +// Find/make a transition type with these attributes. +bool TimeZoneInfo::GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, + const std::string& abbr, + std::uint_least8_t* index) { + std::size_t type_index = 0; + std::size_t abbr_index = abbreviations_.size(); + for (; type_index != transition_types_.size(); ++type_index) { + const TransitionType& tt(transition_types_[type_index]); + const char* tt_abbr = &abbreviations_[tt.abbr_index]; + if (tt_abbr == abbr) abbr_index = tt.abbr_index; + if (tt.utc_offset == utc_offset && tt.is_dst == is_dst) { + if (abbr_index == tt.abbr_index) break; // reuse } - eyear -= (mon > 2 ? 1 : 0); - } - // Handle days within one year. - bool leap_year = IsLeap(eyear); - for (int mdays = kDaysPerMonth[leap_year][mon]; day > mdays; - day -= mdays, mdays = kDaysPerMonth[leap_year][mon]) { - if (++mon > MONSPERYEAR) { mon = 1; leap_year = IsLeap(++eyear); } - } - if (day != orig_day) normalized = true; - - // Add the updated eyear back into (year + year_carry). - year_carry += eyear; - - // Finally, set the DateTime offset. - offset = DayOrdinal(year + year_carry, mon, day); - if (offset < 0) { - offset += 1; - offset *= SECSPERHOUR * HOURSPERDAY; - offset += hour * SECSPERHOUR + min * SECSPERMIN + sec; - offset -= SECSPERHOUR * HOURSPERDAY; - } else { - offset *= SECSPERHOUR * HOURSPERDAY; - offset += hour * SECSPERHOUR + min * SECSPERMIN + sec; } - return normalized; + if (type_index > 255 || abbr_index > 255) { + // No index space (8 bits) available for a new type or abbreviation. + return false; + } + if (type_index == transition_types_.size()) { + TransitionType& tt(*transition_types_.emplace(transition_types_.end())); + tt.utc_offset = static_cast(utc_offset); + tt.is_dst = is_dst; + if (abbr_index == abbreviations_.size()) { + abbreviations_.append(abbr); + abbreviations_.append(1, '\0'); + } + tt.abbr_index = static_cast(abbr_index); + } + *index = static_cast(type_index); + return true; } -// Assign from a Breakdown, created using a TimeZoneInfo timestamp. -inline void DateTime::Assign(const Breakdown& bd) { - Normalize(bd.year, bd.month, bd.day, bd.hour, bd.minute, bd.second); +// zic(8) can generate no-op transitions when a zone changes rules at an +// instant when there is actually no discontinuity. So we check whether +// two transitions have equivalent types (same offset/is_dst/abbr). +bool TimeZoneInfo::EquivTransitions(std::uint_fast8_t tt1_index, + std::uint_fast8_t tt2_index) const { + if (tt1_index == tt2_index) return true; + const TransitionType& tt1(transition_types_[tt1_index]); + const TransitionType& tt2(transition_types_[tt2_index]); + if (tt1.utc_offset != tt2.utc_offset) return false; + if (tt1.is_dst != tt2.is_dst) return false; + if (tt1.abbr_index != tt2.abbr_index) return false; + return true; } -// What (no leap-seconds) UTC+seconds zoneinfo would look like. -void TimeZoneInfo::ResetToBuiltinUTC(int seconds) { - transition_types_.resize(1); - transition_types_[0].utc_offset = seconds; - transition_types_[0].is_dst = false; - transition_types_[0].abbr_index = 0; - transitions_.resize(1); - transitions_[0].unix_time = -(1LL << 59); // zic "BIG_BANG" - transitions_[0].type_index = 0; - transitions_[0].date_time.Assign( - LocalTime(transitions_[0].unix_time, transition_types_[0])); - transitions_[0].prev_date_time = transitions_[0].date_time; - transitions_[0].prev_date_time.offset -= 1; - default_transition_type_ = 0; - abbreviations_ = "UTC"; // TODO: Handle non-zero offset. - abbreviations_.append(1, '\0'); // add NUL - future_spec_.clear(); // never needed for a fixed-offset zone +// Use the POSIX-TZ-environment-variable-style string to handle times +// in years after the last transition stored in the zoneinfo data. +bool TimeZoneInfo::ExtendTransitions() { extended_ = false; + if (future_spec_.empty()) return true; // last transition prevails + + PosixTimeZone posix; + if (!ParsePosixSpec(future_spec_, &posix)) return false; + + // Find transition type for the future std specification. + std::uint_least8_t std_ti; + if (!GetTransitionType(posix.std_offset, false, posix.std_abbr, &std_ti)) + return false; + + if (posix.dst_abbr.empty()) { // std only + // The future specification should match the last transition, and + // that means that handling the future will fall out naturally. + return EquivTransitions(transitions_.back().type_index, std_ti); + } + + // Find transition type for the future dst specification. + std::uint_least8_t dst_ti; + if (!GetTransitionType(posix.dst_offset, true, posix.dst_abbr, &dst_ti)) + return false; + + if (AllYearDST(posix)) { // dst only + // The future specification should match the last transition, and + // that means that handling the future will fall out naturally. + return EquivTransitions(transitions_.back().type_index, dst_ti); + } + + // Extend the transitions for an additional 401 years using the future + // specification. Years beyond those can be handled by mapping back to + // a cycle-equivalent year within that range. Note that we need 401 + // (well, at least the first transition in the 401st year) so that the + // end of the 400th year is mapped back to an extended year. And first + // we may also need two additional transitions for the current year. + transitions_.reserve(transitions_.size() + 2 + 401 * 2); + extended_ = true; + + const Transition& last(transitions_.back()); + const std::int_fast64_t last_time = last.unix_time; + const TransitionType& last_tt(transition_types_[last.type_index]); + last_year_ = LocalTime(last_time, last_tt).cs.year(); + bool leap_year = IsLeap(last_year_); + const civil_second jan1(last_year_); + std::int_fast64_t jan1_time = jan1 - civil_second(); + int jan1_weekday = ToPosixWeekday(get_weekday(jan1)); + + Transition dst = {0, dst_ti, civil_second(), civil_second()}; + Transition std = {0, std_ti, civil_second(), civil_second()}; + for (const year_t limit = last_year_ + 401;; ++last_year_) { + auto dst_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_start); + auto std_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_end); + dst.unix_time = jan1_time + dst_trans_off - posix.std_offset; + std.unix_time = jan1_time + std_trans_off - posix.dst_offset; + const auto* ta = dst.unix_time < std.unix_time ? &dst : &std; + const auto* tb = dst.unix_time < std.unix_time ? &std : &dst; + if (last_time < tb->unix_time) { + if (last_time < ta->unix_time) transitions_.push_back(*ta); + transitions_.push_back(*tb); + } + if (last_year_ == limit) break; + jan1_time += kSecsPerYear[leap_year]; + jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7; + leap_year = !leap_year && IsLeap(last_year_ + 1); + } + + return true; } -// Builds the in-memory header using the raw bytes from the file. -void TimeZoneInfo::Header::Build(const tzhead& tzh) { - timecnt = Decode32(tzh.tzh_timecnt); - typecnt = Decode32(tzh.tzh_typecnt); - charcnt = Decode32(tzh.tzh_charcnt); - leapcnt = Decode32(tzh.tzh_leapcnt); - ttisstdcnt = Decode32(tzh.tzh_ttisstdcnt); - ttisgmtcnt = Decode32(tzh.tzh_ttisgmtcnt); +namespace { + +using FilePtr = std::unique_ptr; + +// fopen(3) adaptor. +inline FilePtr FOpen(const char* path, const char* mode) { +#if defined(_MSC_VER) + FILE* fp; + if (fopen_s(&fp, path, mode) != 0) fp = nullptr; + return FilePtr(fp, fclose); +#else + // TODO: Enable the close-on-exec flag. + return FilePtr(fopen(path, mode), fclose); +#endif } -void TimeZoneInfo::CheckTransition(const std::string& name, - const TransitionType& tt, int32_t offset, - bool is_dst, const std::string& abbr) const { - if (tt.utc_offset != offset || tt.is_dst != is_dst || - &abbreviations_[tt.abbr_index] != abbr) { - std::clog << name << ": Transition" - << " offset=" << tt.utc_offset << "/" - << (tt.is_dst ? "DST" : "STD") - << "/abbr=" << &abbreviations_[tt.abbr_index] - << " does not match POSIX spec '" << future_spec_ << "'\n"; +// A stdio(3)-backed implementation of ZoneInfoSource. +class FileZoneInfoSource : public ZoneInfoSource { + public: + static std::unique_ptr Open(const std::string& name); + + std::size_t Read(void* ptr, std::size_t size) override { + size = std::min(size, len_); + std::size_t nread = fread(ptr, 1, size, fp_.get()); + len_ -= nread; + return nread; + } + int Skip(std::size_t offset) override { + offset = std::min(offset, len_); + int rc = fseek(fp_.get(), static_cast(offset), SEEK_CUR); + if (rc == 0) len_ -= offset; + return rc; + } + std::string Version() const override { + // TODO: It would nice if the zoneinfo data included the tzdb version. + return std::string(); + } + + protected: + explicit FileZoneInfoSource( + FilePtr fp, std::size_t len = std::numeric_limits::max()) + : fp_(std::move(fp)), len_(len) {} + + private: + FilePtr fp_; + std::size_t len_; +}; + +std::unique_ptr FileZoneInfoSource::Open( + const std::string& name) { + // Use of the "file:" prefix is intended for testing purposes only. + const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0; + + // Map the time-zone name to a path name. + std::string path; + if (pos == name.size() || name[pos] != '/') { + const char* tzdir = "/usr/share/zoneinfo"; + char* tzdir_env = nullptr; +#if defined(_MSC_VER) + _dupenv_s(&tzdir_env, nullptr, "TZDIR"); +#else + tzdir_env = std::getenv("TZDIR"); +#endif + if (tzdir_env && *tzdir_env) tzdir = tzdir_env; + path += tzdir; + path += '/'; +#if defined(_MSC_VER) + free(tzdir_env); +#endif } + path.append(name, pos, std::string::npos); + + // Open the zoneinfo file. + auto fp = FOpen(path.c_str(), "rb"); + if (fp == nullptr) return nullptr; + return std::unique_ptr(new FileZoneInfoSource(std::move(fp))); } -// How many bytes of data are associated with this header. The result -// depends upon whether this is a section with 4-byte or 8-byte times. -size_t TimeZoneInfo::Header::DataLength(size_t time_len) const { - size_t len = 0; - len += (time_len + 1) * timecnt; // unix_time + type_index - len += (4 + 1 + 1) * typecnt; // utc_offset + is_dst + abbr_index - len += 1 * charcnt; // abbreviations - len += (time_len + 4) * leapcnt; // leap-time + TAI-UTC - len += 1 * ttisstdcnt; // UTC/local indicators - len += 1 * ttisgmtcnt; // standard/wall indicators - return len; +class AndroidZoneInfoSource : public FileZoneInfoSource { + public: + static std::unique_ptr Open(const std::string& name); + std::string Version() const override { return version_; } + + private: + explicit AndroidZoneInfoSource(FilePtr fp, std::size_t len, + std::string version) + : FileZoneInfoSource(std::move(fp), len), version_(std::move(version)) {} + std::string version_; +}; + +std::unique_ptr AndroidZoneInfoSource::Open( + const std::string& name) { + // Use of the "file:" prefix is intended for testing purposes only. + const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0; + + // See Android's libc/tzcode/bionic.cpp for additional information. + for (const char* tzdata : {"/apex/com.android.tzdata/etc/tz/tzdata", + "/data/misc/zoneinfo/current/tzdata", + "/system/usr/share/zoneinfo/tzdata"}) { + auto fp = FOpen(tzdata, "rb"); + if (fp == nullptr) continue; + + char hbuf[24]; // covers header.zonetab_offset too + if (fread(hbuf, 1, sizeof(hbuf), fp.get()) != sizeof(hbuf)) continue; + if (strncmp(hbuf, "tzdata", 6) != 0) continue; + const char* vers = (hbuf[11] == '\0') ? hbuf + 6 : ""; + const std::int_fast32_t index_offset = Decode32(hbuf + 12); + const std::int_fast32_t data_offset = Decode32(hbuf + 16); + if (index_offset < 0 || data_offset < index_offset) continue; + if (fseek(fp.get(), static_cast(index_offset), SEEK_SET) != 0) + continue; + + char ebuf[52]; // covers entry.unused too + const std::size_t index_size = + static_cast(data_offset - index_offset); + const std::size_t zonecnt = index_size / sizeof(ebuf); + if (zonecnt * sizeof(ebuf) != index_size) continue; + for (std::size_t i = 0; i != zonecnt; ++i) { + if (fread(ebuf, 1, sizeof(ebuf), fp.get()) != sizeof(ebuf)) break; + const std::int_fast32_t start = data_offset + Decode32(ebuf + 40); + const std::int_fast32_t length = Decode32(ebuf + 44); + if (start < 0 || length < 0) break; + ebuf[40] = '\0'; // ensure zone name is NUL terminated + if (strcmp(name.c_str() + pos, ebuf) == 0) { + if (fseek(fp.get(), static_cast(start), SEEK_SET) != 0) break; + return std::unique_ptr(new AndroidZoneInfoSource( + std::move(fp), static_cast(length), vers)); + } + } + } + + return nullptr; +} + +// A zoneinfo source for use inside Fuchsia components. This attempts to +// read zoneinfo files from one of several known paths in a component's +// incoming namespace. [Config data][1] is preferred, but package-specific +// resources are also supported. +// +// Fuchsia's implementation supports `FileZoneInfoSource::Version()`. +// +// [1]: https://fuchsia.dev/fuchsia-src/development/components/data#using_config_data_in_your_component +class FuchsiaZoneInfoSource : public FileZoneInfoSource { + public: + static std::unique_ptr Open(const std::string& name); + std::string Version() const override { return version_; } + + private: + explicit FuchsiaZoneInfoSource(FilePtr fp, std::string version) + : FileZoneInfoSource(std::move(fp)), version_(std::move(version)) {} + std::string version_; +}; + +std::unique_ptr FuchsiaZoneInfoSource::Open( + const std::string& name) { + // Use of the "file:" prefix is intended for testing purposes only. + const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0; + + // Prefixes where a Fuchsia component might find zoneinfo files, + // in descending order of preference. + const auto kTzdataPrefixes = { + // The tzdata from `config-data`. + "/config/data/tzdata/", + // The tzdata bundled in the component's package. + "/pkg/data/tzdata/", + // General data storage. + "/data/tzdata/", + // The recommended path for routed-in tzdata files. + // See for details: + // https://fuchsia.dev/fuchsia-src/concepts/process/namespaces?hl=en#typical_directory_structure + "/config/tzdata/", + }; + const auto kEmptyPrefix = {""}; + const bool name_absolute = (pos != name.size() && name[pos] == '/'); + const auto prefixes = name_absolute ? kEmptyPrefix : kTzdataPrefixes; + + // Fuchsia builds place zoneinfo files at "". + for (const std::string prefix : prefixes) { + std::string path = prefix; + if (!prefix.empty()) path += "zoneinfo/tzif2/"; // format + path.append(name, pos, std::string::npos); + + auto fp = FOpen(path.c_str(), "rb"); + if (fp == nullptr) continue; + + std::string version; + if (!prefix.empty()) { + // Fuchsia builds place the version in "revision.txt". + std::ifstream version_stream(prefix + "revision.txt"); + if (version_stream.is_open()) { + // revision.txt should contain no newlines, but to be + // defensive we read just the first line. + std::getline(version_stream, version); + } + } + + return std::unique_ptr( + new FuchsiaZoneInfoSource(std::move(fp), std::move(version))); + } + + return nullptr; +} + +} // namespace + +// What (no leap-seconds) UTC+seconds zoneinfo would look like. +bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { + transition_types_.resize(1); + TransitionType& tt(transition_types_.back()); + tt.utc_offset = static_cast(offset.count()); + tt.is_dst = false; + tt.abbr_index = 0; + + // We temporarily add some redundant, contemporary (2015 through 2025) + // transitions for performance reasons. See TimeZoneInfo::LocalTime(). + // TODO: Fix the performance issue and remove the extra transitions. + transitions_.clear(); + transitions_.reserve(12); + for (const std::int_fast64_t unix_time : { + -(1LL << 59), // a "first half" transition + 1420070400LL, // 2015-01-01T00:00:00+00:00 + 1451606400LL, // 2016-01-01T00:00:00+00:00 + 1483228800LL, // 2017-01-01T00:00:00+00:00 + 1514764800LL, // 2018-01-01T00:00:00+00:00 + 1546300800LL, // 2019-01-01T00:00:00+00:00 + 1577836800LL, // 2020-01-01T00:00:00+00:00 + 1609459200LL, // 2021-01-01T00:00:00+00:00 + 1640995200LL, // 2022-01-01T00:00:00+00:00 + 1672531200LL, // 2023-01-01T00:00:00+00:00 + 1704067200LL, // 2024-01-01T00:00:00+00:00 + 1735689600LL, // 2025-01-01T00:00:00+00:00 + }) { + Transition& tr(*transitions_.emplace(transitions_.end())); + tr.unix_time = unix_time; + tr.type_index = 0; + tr.civil_sec = LocalTime(tr.unix_time, tt).cs; + tr.prev_civil_sec = tr.civil_sec - 1; + } + + default_transition_type_ = 0; + abbreviations_ = FixedOffsetToAbbr(offset); + abbreviations_.append(1, '\0'); + future_spec_.clear(); // never needed for a fixed-offset zone + extended_ = false; + + tt.civil_max = LocalTime(seconds::max().count(), tt).cs; + tt.civil_min = LocalTime(seconds::min().count(), tt).cs; + + transitions_.shrink_to_fit(); + return true; } -bool TimeZoneInfo::Load(const std::string& name, FILE* fp) { +bool TimeZoneInfo::Load(ZoneInfoSource* zip) { // Read and validate the header. tzhead tzh; - if (fread(&tzh, 1, sizeof tzh, fp) != sizeof tzh) + if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false; if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) return false; Header hdr; - hdr.Build(tzh); - size_t time_len = 4; + if (!hdr.Build(tzh)) + return false; + std::size_t time_len = 4; if (tzh.tzh_version[0] != '\0') { // Skip the 4-byte data. - if (fseek(fp, static_cast(hdr.DataLength(time_len)), SEEK_CUR) != 0) + if (zip->Skip(hdr.DataLength(time_len)) != 0) return false; // Read and validate the header for the 8-byte data. - if (fread(&tzh, 1, sizeof tzh, fp) != sizeof tzh) + if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false; if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) return false; if (tzh.tzh_version[0] == '\0') return false; - hdr.Build(tzh); + if (!hdr.Build(tzh)) + return false; time_len = 8; } - if (hdr.timecnt < 0 || hdr.typecnt <= 0) + if (hdr.typecnt == 0) return false; if (hdr.leapcnt != 0) { // This code assumes 60-second minutes so we do not want // the leap-second encoded zoneinfo. We could reverse the - // compensation, but it's never in a Google zoneinfo anyway, + // compensation, but the "right" encoding is rarely used // so currently we simply reject such data. return false; } if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) return false; - if (hdr.ttisgmtcnt != 0 && hdr.ttisgmtcnt != hdr.typecnt) + if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt) return false; // Read the data into a local buffer. - size_t len = hdr.DataLength(time_len); + std::size_t len = hdr.DataLength(time_len); std::vector tbuf(len); - if (fread(tbuf.data(), 1, len, fp) != len) + if (zip->Read(tbuf.data(), len) != len) return false; const char* bp = tbuf.data(); // Decode and validate the transitions. + transitions_.reserve(hdr.timecnt + 2); transitions_.resize(hdr.timecnt); - for (int32_t i = 0; i != hdr.timecnt; ++i) { + for (std::size_t i = 0; i != hdr.timecnt; ++i) { transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp); bp += time_len; if (i != 0) { @@ -477,8 +686,8 @@ bool TimeZoneInfo::Load(const std::string& name, FILE* fp) { } } bool seen_type_0 = false; - for (int32_t i = 0; i != hdr.timecnt; ++i) { - transitions_[i].type_index = (static_cast(*bp++) & 0xff); + for (std::size_t i = 0; i != hdr.timecnt; ++i) { + transitions_[i].type_index = Decode8(bp++); if (transitions_[i].type_index >= hdr.typecnt) return false; if (transitions_[i].type_index == 0) @@ -486,15 +695,17 @@ bool TimeZoneInfo::Load(const std::string& name, FILE* fp) { } // Decode and validate the transition types. + transition_types_.reserve(hdr.typecnt + 2); transition_types_.resize(hdr.typecnt); - for (int32_t i = 0; i != hdr.typecnt; ++i) { - transition_types_[i].utc_offset = Decode32(bp); - if (transition_types_[i].utc_offset >= SECSPERDAY || - transition_types_[i].utc_offset <= -SECSPERDAY) + for (std::size_t i = 0; i != hdr.typecnt; ++i) { + transition_types_[i].utc_offset = + static_cast(Decode32(bp)); + if (transition_types_[i].utc_offset >= kSecsPerDay || + transition_types_[i].utc_offset <= -kSecsPerDay) return false; bp += 4; - transition_types_[i].is_dst = ((static_cast(*bp++) & 0xff) != 0); - transition_types_[i].abbr_index = (static_cast(*bp++) & 0xff); + transition_types_[i].is_dst = (Decode8(bp++) != 0); + transition_types_[i].abbr_index = Decode8(bp++); if (transition_types_[i].abbr_index >= hdr.charcnt) return false; } @@ -502,7 +713,7 @@ bool TimeZoneInfo::Load(const std::string& name, FILE* fp) { // Determine the before-first-transition type. default_transition_type_ = 0; if (seen_type_0 && hdr.timecnt != 0) { - uint8_t index = 0; + std::uint_fast8_t index = 0; if (transition_types_[0].is_dst) { index = transitions_[0].type_index; while (index != 0 && transition_types_[index].is_dst) @@ -515,6 +726,7 @@ bool TimeZoneInfo::Load(const std::string& name, FILE* fp) { } // Copy all the abbreviations. + abbreviations_.reserve(hdr.charcnt + 10); abbreviations_.assign(bp, hdr.charcnt); bp += hdr.charcnt; @@ -522,405 +734,349 @@ bool TimeZoneInfo::Load(const std::string& name, FILE* fp) { // encoded zoneinfo. The ttisstd/ttisgmt indicators only apply when // interpreting a POSIX spec that does not include start/end rules, and // that isn't the case here (see "zic -p"). - bp += (8 + 4) * hdr.leapcnt; // leap-time + TAI-UTC - bp += 1 * hdr.ttisstdcnt; // UTC/local indicators - bp += 1 * hdr.ttisgmtcnt; // standard/wall indicators + bp += (time_len + 4) * hdr.leapcnt; // leap-time + TAI-UTC + bp += 1 * hdr.ttisstdcnt; // UTC/local indicators + bp += 1 * hdr.ttisutcnt; // standard/wall indicators + assert(bp == tbuf.data() + tbuf.size()); future_spec_.clear(); if (tzh.tzh_version[0] != '\0') { // Snarf up the NL-enclosed future POSIX spec. Note // that version '3' files utilize an extended format. - if (fgetc(fp) != '\n') + auto get_char = [](ZoneInfoSource* azip) -> int { + unsigned char ch; // all non-EOF results are positive + return (azip->Read(&ch, 1) == 1) ? ch : EOF; + }; + if (get_char(zip) != '\n') return false; - for (int c = fgetc(fp); c != '\n'; c = fgetc(fp)) { + for (int c = get_char(zip); c != '\n'; c = get_char(zip)) { if (c == EOF) return false; - future_spec_.push_back(c); + future_spec_.push_back(static_cast(c)); } } // We don't check for EOF so that we're forwards compatible. - // Use the POSIX-TZ-environment-variable-style string to handle times - // in years after the last transition stored in the zoneinfo data. - extended_ = false; - if (!future_spec_.empty()) { - PosixTimeZone posix; - if (!ParsePosixSpec(future_spec_, &posix)) { - std::clog << name << ": Failed to parse '" << future_spec_ << "'\n"; - } else if (posix.dst_abbr.empty()) { // std only - // The future specification should match the last/default transition, - // and that means that handling the future will fall out naturally. - int index = default_transition_type_; - if (hdr.timecnt != 0) index = transitions_[hdr.timecnt - 1].type_index; - const TransitionType& tt(transition_types_[index]); - CheckTransition(name, tt, posix.std_offset, false, posix.std_abbr); - } else if (hdr.timecnt < 2) { - std::clog << name << ": Too few transitions for POSIX spec\n"; - } else if (transitions_[hdr.timecnt - 1].unix_time < 0) { - std::clog << name << ": Old transitions for POSIX spec\n"; - } else { // std and dst - // Extend the transitions for an additional 400 years using the - // future specification. Years beyond those can be handled by - // mapping back to a cycle-equivalent year within that range. - // zic(8) should probably do this so that we don't have to. - transitions_.resize(hdr.timecnt + 400 * 2); - extended_ = true; - - // The future specification should match the last two transitions, - // and those transitions should have different is_dst flags but be - // in the same calendar year. - const Transition& tr0(transitions_[hdr.timecnt - 1]); - const Transition& tr1(transitions_[hdr.timecnt - 2]); - const TransitionType& tt0(transition_types_[tr0.type_index]); - const TransitionType& tt1(transition_types_[tr1.type_index]); - const TransitionType& spring(tt0.is_dst ? tt0 : tt1); - const TransitionType& autumn(tt0.is_dst ? tt1 : tt0); - CheckTransition(name, spring, posix.dst_offset, true, posix.dst_abbr); - CheckTransition(name, autumn, posix.std_offset, false, posix.std_abbr); - last_year_ = LocalTime(tr0.unix_time, tt0).year; - if (LocalTime(tr1.unix_time, tt1).year != last_year_) { - std::clog << name << ": Final transitions not in same year\n"; - } + // If we did not find version information during the standard loading + // process (as of tzh_version '3' that is unsupported), then ask the + // ZoneInfoSource for any out-of-bound version string it may be privy to. + if (version_.empty()) { + version_ = zip->Version(); + } - // Add the transitions to tr1 and back to tr0 for each extra year. - const PosixTransition& pt1(tt0.is_dst ? posix.dst_end : posix.dst_start); - const PosixTransition& pt0(tt0.is_dst ? posix.dst_start : posix.dst_end); - Transition* tr = &transitions_[hdr.timecnt]; // next trans to fill - const int64_t jan1_ord = DayOrdinal(last_year_, 1, 1); - int64_t jan1_time = jan1_ord * SECSPERDAY; - int jan1_weekday = (EPOCH_WDAY + jan1_ord) % DAYSPERWEEK; - if (jan1_weekday < 0) jan1_weekday += DAYSPERWEEK; - bool leap_year = IsLeap(last_year_); - for (const int64_t limit = last_year_ + 400; last_year_ < limit;) { - last_year_ += 1; // an additional year of generated transitions - jan1_time += kSecPerYear[leap_year]; - jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % DAYSPERWEEK; - leap_year = !leap_year && IsLeap(last_year_); - const int64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1); - tr->unix_time = jan1_time + tr1_offset - tt0.utc_offset; - tr++->type_index = tr1.type_index; - const int64_t tr0_offset = TransOffset(leap_year, jan1_weekday, pt0); - tr->unix_time = jan1_time + tr0_offset - tt1.utc_offset; - tr++->type_index = tr0.type_index; - } - } + // Ensure that there is always a transition in the first half of the + // time line (the second half is handled below) so that the signed + // difference between a civil_second and the civil_second of its + // previous transition is always representable, without overflow. + if (transitions_.empty() || transitions_.front().unix_time >= 0) { + Transition& tr(*transitions_.emplace(transitions_.begin())); + tr.unix_time = -(1LL << 59); // -18267312070-10-26T17:01:52+00:00 + tr.type_index = default_transition_type_; + } + + // Extend the transitions using the future specification. + if (!ExtendTransitions()) return false; + + // Ensure that there is always a transition in the second half of the + // time line (the first half is handled above) so that the signed + // difference between a civil_second and the civil_second of its + // previous transition is always representable, without overflow. + const Transition& last(transitions_.back()); + if (last.unix_time < 0) { + const std::uint_fast8_t type_index = last.type_index; + Transition& tr(*transitions_.emplace(transitions_.end())); + tr.unix_time = 2147483647; // 2038-01-19T03:14:07+00:00 + tr.type_index = type_index; } - // Compute the local civil time for each transition and the preceeding - // second. These will be used for reverse conversions in MakeTimeInfo(). + // Compute the local civil time for each transition and the preceding + // second. These will be used for reverse conversions in MakeTime(). const TransitionType* ttp = &transition_types_[default_transition_type_]; - for (size_t i = 0; i != transitions_.size(); ++i) { + for (std::size_t i = 0; i != transitions_.size(); ++i) { Transition& tr(transitions_[i]); - tr.prev_date_time.Assign(LocalTime(tr.unix_time, *ttp)); - tr.prev_date_time.offset -= 1; + tr.prev_civil_sec = LocalTime(tr.unix_time, *ttp).cs - 1; ttp = &transition_types_[tr.type_index]; - tr.date_time.Assign(LocalTime(tr.unix_time, *ttp)); + tr.civil_sec = LocalTime(tr.unix_time, *ttp).cs; if (i != 0) { - // Check that the transitions are ordered by date/time. Essentially + // Check that the transitions are ordered by civil time. Essentially // this means that an offset change cannot cross another such change. - // No one does this in practice, and we depend on it in MakeTimeInfo(). - if (!Transition::ByDateTime()(transitions_[i - 1], tr)) + // No one does this in practice, and we depend on it in MakeTime(). + if (!Transition::ByCivilTime()(transitions_[i - 1], tr)) return false; // out of order } } - // We remember the transitions found during the last BreakTime() and - // MakeTimeInfo() calls. If the next request is for the same transition - // we will avoid re-searching. - local_time_hint_ = 0; - time_local_hint_ = 0; + // Compute the maximum/minimum civil times that can be converted to a + // time_point for each of the zone's transition types. + for (auto& tt : transition_types_) { + tt.civil_max = LocalTime(seconds::max().count(), tt).cs; + tt.civil_min = LocalTime(seconds::min().count(), tt).cs; + } + transitions_.shrink_to_fit(); return true; } bool TimeZoneInfo::Load(const std::string& name) { // We can ensure that the loading of UTC or any other fixed-offset - // zone never fails because the simple, no-transition state can be + // zone never fails because the simple, fixed-offset state can be // internally generated. Note that this depends on our choice to not // accept leap-second encoded ("right") zoneinfo. - if (name == "UTC") { - ResetToBuiltinUTC(0); - return true; + auto offset = seconds::zero(); + if (FixedOffsetFromName(name, &offset)) { + return ResetToBuiltinUTC(offset); } - // Map time-zone name to its machine-specific path. - std::string path; - if (name == "localtime") { -#if defined(_WIN32) || defined(_WIN64) - char* localtime = nullptr; - _dupenv_s(&localtime, nullptr, "LOCALTIME"); - path = localtime ? localtime : "/etc/localtime"; - free(localtime); -#else - const char* localtime = std::getenv("LOCALTIME"); - path = localtime ? localtime : "/etc/localtime"; -#endif - } else if (!name.empty() && name[0] == '/') { - path = name; - } else { -#if defined(_WIN32) || defined(_WIN64) - char* tzdir = nullptr; - _dupenv_s(&tzdir, nullptr, "TZDIR"); - path = tzdir ? tzdir : "/usr/share/zoneinfo"; - free(tzdir); -#else - const char* tzdir = std::getenv("TZDIR"); - path = tzdir ? tzdir : "/usr/share/zoneinfo"; -#endif - path += '/'; - path += name; - } + // Find and use a ZoneInfoSource to load the named zone. + auto zip = cctz_extension::zone_info_source_factory( + name, [](const std::string& n) -> std::unique_ptr { + if (auto z = FileZoneInfoSource::Open(n)) return z; + if (auto z = AndroidZoneInfoSource::Open(n)) return z; + if (auto z = FuchsiaZoneInfoSource::Open(n)) return z; + return nullptr; + }); + return zip != nullptr && Load(zip.get()); +} - // Load the time-zone data. - bool loaded = false; -#if defined(_WIN32) || defined(_WIN64) - FILE* fp; - if (fopen_s(&fp, path.c_str(), "rb") != 0) fp = nullptr; -#else - FILE* fp = fopen(path.c_str(), "rb"); -#endif - if (fp != nullptr) { - loaded = Load(name, fp); - fclose(fp); - } else { - char ebuf[64]; - std::clog << path << ": " << errmsg(errno, ebuf, sizeof ebuf) << "\n"; - } - return loaded; +std::unique_ptr TimeZoneInfo::UTC() { + auto tz = std::unique_ptr(new TimeZoneInfo); + tz->ResetToBuiltinUTC(seconds::zero()); + return tz; } -// BreakTime() translation for a particular transition type. -Breakdown TimeZoneInfo::LocalTime(int64_t unix_time, - const TransitionType& tt) const { - Breakdown bd; - - bd.year = EPOCH_YEAR; - bd.weekday = EPOCH_WDAY; // Thu - int64_t seconds = unix_time; - - // Shift to a base year that is 400-year aligned. - static_assert(EPOCH_YEAR == 1970, "Unexpected value for EPOCH_YEAR"); - if (seconds >= 0) { - seconds -= 10957LL * SECSPERDAY; - bd.year += 30; // == 2000 - } else { - seconds += (146097LL - 10957LL) * SECSPERDAY; - bd.year -= 370; // == 1600 - } - bd.weekday += 2; // Sat +std::unique_ptr TimeZoneInfo::Make(const std::string& name) { + auto tz = std::unique_ptr(new TimeZoneInfo); + if (!tz->Load(name)) tz.reset(); // fallback to UTC + return tz; +} +// BreakTime() translation for a particular transition type. +time_zone::absolute_lookup TimeZoneInfo::LocalTime( + std::int_fast64_t unix_time, const TransitionType& tt) const { // A civil time in "+offset" looks like (time+offset) in UTC. - if (seconds >= 0) { - if (tt.utc_offset > 0 && seconds > INT64_MAX - tt.utc_offset) { - seconds -= kSecPer400Years; - bd.year += 400; - } + // Note: We perform two additions in the civil_second domain to + // sidestep the chance of overflow in (unix_time + tt.utc_offset). + return {(civil_second() + unix_time) + tt.utc_offset, + tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]}; +} + +// BreakTime() translation for a particular transition. +time_zone::absolute_lookup TimeZoneInfo::LocalTime( + std::int_fast64_t unix_time, const Transition& tr) const { + const TransitionType& tt = transition_types_[tr.type_index]; + // Note: (unix_time - tr.unix_time) will never overflow as we + // have ensured that there is always a "nearby" transition. + return {tr.civil_sec + (unix_time - tr.unix_time), // TODO: Optimize. + tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]}; +} + +// MakeTime() translation with a conversion-preserving +N * 400-year shift. +time_zone::civil_lookup TimeZoneInfo::TimeLocal(const civil_second& cs, + year_t c4_shift) const { + assert(last_year_ - 400 < cs.year() && cs.year() <= last_year_); + time_zone::civil_lookup cl = MakeTime(cs); + if (c4_shift > seconds::max().count() / kSecsPer400Years) { + cl.pre = cl.trans = cl.post = time_point::max(); } else { - if (tt.utc_offset < 0 && seconds < INT64_MIN - tt.utc_offset) { - seconds += kSecPer400Years; - bd.year -= 400; - } - } - seconds += tt.utc_offset; - - // Handle years in chunks of 400/100/4/1. - bd.year += 400 * (seconds / kSecPer400Years); - seconds %= kSecPer400Years; - if (seconds < 0) { - seconds += kSecPer400Years; - bd.year -= 400; - } - bool leap_year = true; // 4-century aligned - int64_t sec_per_100years = kSecPer100Years[leap_year]; - while (seconds >= sec_per_100years) { - seconds -= sec_per_100years; - bd.year += 100; - bd.weekday += 5 + leap_year; - leap_year = false; // 1-century, non 4-century aligned - sec_per_100years = kSecPer100Years[leap_year]; - } - int32_t sec_per_4years = kSecPer4Years[leap_year]; - while (seconds >= sec_per_4years) { - seconds -= sec_per_4years; - bd.year += 4; - bd.weekday += 4 + leap_year; - leap_year = true; // 4-year, non century aligned - sec_per_4years = kSecPer4Years[leap_year]; - } - int32_t sec_per_year = kSecPerYear[leap_year]; - while (seconds >= sec_per_year) { - seconds -= sec_per_year; - bd.year += 1; - bd.weekday += 1 + leap_year; - leap_year = false; // non 4-year aligned - sec_per_year = kSecPerYear[leap_year]; - } - - // Handle months and days. - bd.yearday = static_cast(seconds / SECSPERDAY) + 1; - seconds %= SECSPERDAY; - bd.month = TM_DECEMBER + 1; - bd.day = bd.yearday; - bd.weekday += bd.day - 1; - while (bd.month != TM_JANUARY + 1) { - int month_offset = kMonthOffsets[leap_year][bd.month]; - if (bd.day > month_offset) { - bd.day -= month_offset; - break; + const auto offset = seconds(c4_shift * kSecsPer400Years); + const auto limit = time_point::max() - offset; + for (auto* tp : {&cl.pre, &cl.trans, &cl.post}) { + if (*tp > limit) { + *tp = time_point::max(); + } else { + *tp += offset; + } } - bd.month -= 1; } - - // Handle hours, minutes, and seconds. - bd.hour = static_cast(seconds / SECSPERHOUR); - seconds %= SECSPERHOUR; - bd.minute = static_cast(seconds / SECSPERMIN); - bd.second = seconds % SECSPERMIN; - - // Shift weekday to [1==Mon, ..., 7=Sun]. - bd.weekday -= 1; - bd.weekday %= DAYSPERWEEK; - bd.weekday += 1; - - // Handle offset, is_dst, and abbreviation. - bd.offset = tt.utc_offset; - bd.is_dst = tt.is_dst; - bd.abbr = &abbreviations_[tt.abbr_index]; - - return bd; + return cl; } -// MakeTimeInfo() translation with a conversion-preserving offset. -TimeInfo TimeZoneInfo::TimeLocal(int64_t year, int mon, int day, int hour, - int min, int sec, int64_t offset) const { - TimeInfo ti = MakeTimeInfo(year, mon, day, hour, min, sec); - ti.pre = FromUnixSeconds(ToUnixSeconds(ti.pre) + offset); - ti.trans = FromUnixSeconds(ToUnixSeconds(ti.trans) + offset); - ti.post = FromUnixSeconds(ToUnixSeconds(ti.post) + offset); - return ti; -} +time_zone::absolute_lookup TimeZoneInfo::BreakTime( + const time_point& tp) const { + std::int_fast64_t unix_time = ToUnixSeconds(tp); + const std::size_t timecnt = transitions_.size(); + assert(timecnt != 0); // We always add a transition. -Breakdown TimeZoneInfo::BreakTime(const time_point& tp) const { - int64_t unix_time = ToUnixSeconds(tp); - const size_t timecnt = transitions_.size(); - if (timecnt == 0 || unix_time < transitions_[0].unix_time) { - const int type_index = default_transition_type_; - return LocalTime(unix_time, transition_types_[type_index]); + if (unix_time < transitions_[0].unix_time) { + return LocalTime(unix_time, transition_types_[default_transition_type_]); } if (unix_time >= transitions_[timecnt - 1].unix_time) { // After the last transition. If we extended the transitions using // future_spec_, shift back to a supported year using the 400-year // cycle of calendaric equivalence and then compensate accordingly. if (extended_) { - const int64_t diff = unix_time - transitions_[timecnt - 1].unix_time; - const int64_t shift = diff / kSecPer400Years + 1; - const auto d = sys_seconds(shift * kSecPer400Years); - Breakdown bd = BreakTime(tp - d); - bd.year += shift * 400; - return bd; + const std::int_fast64_t diff = + unix_time - transitions_[timecnt - 1].unix_time; + const year_t shift = diff / kSecsPer400Years + 1; + const auto d = seconds(shift * kSecsPer400Years); + time_zone::absolute_lookup al = BreakTime(tp - d); + al.cs = YearShift(al.cs, shift * 400); + return al; } - const int type_index = transitions_[timecnt - 1].type_index; - return LocalTime(unix_time, transition_types_[type_index]); + return LocalTime(unix_time, transitions_[timecnt - 1]); } - const size_t hint = local_time_hint_.load(std::memory_order_relaxed); + const std::size_t hint = local_time_hint_.load(std::memory_order_relaxed); if (0 < hint && hint < timecnt) { - if (unix_time < transitions_[hint].unix_time) { - if (!(unix_time < transitions_[hint - 1].unix_time)) { - const int type_index = transitions_[hint - 1].type_index; - return LocalTime(unix_time, transition_types_[type_index]); + if (transitions_[hint - 1].unix_time <= unix_time) { + if (unix_time < transitions_[hint].unix_time) { + return LocalTime(unix_time, transitions_[hint - 1]); } } } - const Transition target = {unix_time, 0, {0}, {0}}; + const Transition target = {unix_time, 0, civil_second(), civil_second()}; const Transition* begin = &transitions_[0]; const Transition* tr = std::upper_bound(begin, begin + timecnt, target, Transition::ByUnixTime()); - local_time_hint_.store(tr - begin, std::memory_order_relaxed); - const int type_index = (--tr)->type_index; - return LocalTime(unix_time, transition_types_[type_index]); + local_time_hint_.store(static_cast(tr - begin), + std::memory_order_relaxed); + return LocalTime(unix_time, *--tr); } -TimeInfo TimeZoneInfo::MakeTimeInfo(int64_t year, int mon, int day, - int hour, int min, int sec) const { - Transition target; - DateTime& dt(target.date_time); - const bool normalized = dt.Normalize(year, mon, day, hour, min, sec); - - const size_t timecnt = transitions_.size(); - if (timecnt == 0) { - // Use the default offset. - int32_t offset = transition_types_[default_transition_type_].utc_offset; - int64_t unix_time = (dt - DateTime{0}) - offset; - return MakeUnique(unix_time, normalized); - } +time_zone::civil_lookup TimeZoneInfo::MakeTime(const civil_second& cs) const { + const std::size_t timecnt = transitions_.size(); + assert(timecnt != 0); // We always add a transition. - // Find the first transition after our target date/time. + // Find the first transition after our target civil time. const Transition* tr = nullptr; const Transition* begin = &transitions_[0]; const Transition* end = begin + timecnt; - if (dt < begin->date_time) { + if (cs < begin->civil_sec) { tr = begin; - } else if (!(dt < transitions_[timecnt - 1].date_time)) { + } else if (cs >= transitions_[timecnt - 1].civil_sec) { tr = end; } else { - const size_t hint = time_local_hint_.load(std::memory_order_relaxed); + const std::size_t hint = time_local_hint_.load(std::memory_order_relaxed); if (0 < hint && hint < timecnt) { - if (dt < transitions_[hint].date_time) { - if (!(dt < transitions_[hint - 1].date_time)) { + if (transitions_[hint - 1].civil_sec <= cs) { + if (cs < transitions_[hint].civil_sec) { tr = begin + hint; } } } if (tr == nullptr) { - tr = std::upper_bound(begin, end, target, Transition::ByDateTime()); - time_local_hint_.store(tr - begin, std::memory_order_relaxed); + const Transition target = {0, 0, cs, civil_second()}; + tr = std::upper_bound(begin, end, target, Transition::ByCivilTime()); + time_local_hint_.store(static_cast(tr - begin), + std::memory_order_relaxed); } } if (tr == begin) { - if (!(tr->prev_date_time < dt)) { + if (tr->prev_civil_sec >= cs) { // Before first transition, so use the default offset. - int offset = transition_types_[default_transition_type_].utc_offset; - int64_t unix_time = (dt - DateTime{0}) - offset; - return MakeUnique(unix_time, normalized); + const TransitionType& tt(transition_types_[default_transition_type_]); + if (cs < tt.civil_min) return MakeUnique(time_point::min()); + return MakeUnique(cs - (civil_second() + tt.utc_offset)); } - // tr->prev_date_time < dt < tr->date_time - return MakeSkipped(*tr, dt, normalized); + // tr->prev_civil_sec < cs < tr->civil_sec + return MakeSkipped(*tr, cs); } if (tr == end) { - if ((--tr)->prev_date_time < dt) { + if (cs > (--tr)->prev_civil_sec) { // After the last transition. If we extended the transitions using // future_spec_, shift back to a supported year using the 400-year // cycle of calendaric equivalence and then compensate accordingly. - if (extended_ && year > last_year_) { - const int64_t shift = (year - last_year_) / 400 + 1; - return TimeLocal(year - shift * 400, mon, day, hour, min, sec, - shift * kSecPer400Years); + if (extended_ && cs.year() > last_year_) { + const year_t shift = (cs.year() - last_year_ - 1) / 400 + 1; + return TimeLocal(YearShift(cs, shift * -400), shift); } - int64_t unix_time = tr->unix_time + (dt - tr->date_time); - return MakeUnique(unix_time, normalized); + const TransitionType& tt(transition_types_[tr->type_index]); + if (cs > tt.civil_max) return MakeUnique(time_point::max()); + return MakeUnique(tr->unix_time + (cs - tr->civil_sec)); } - // tr->date_time <= dt <= tr->prev_date_time - return MakeRepeated(*tr, dt, normalized); + // tr->civil_sec <= cs <= tr->prev_civil_sec + return MakeRepeated(*tr, cs); } - if (tr->prev_date_time < dt) { - // tr->prev_date_time < dt < tr->date_time - return MakeSkipped(*tr, dt, normalized); + if (tr->prev_civil_sec < cs) { + // tr->prev_civil_sec < cs < tr->civil_sec + return MakeSkipped(*tr, cs); } - if (!((--tr)->prev_date_time < dt)) { - // tr->date_time <= dt <= tr->prev_date_time - return MakeRepeated(*tr, dt, normalized); + if (cs <= (--tr)->prev_civil_sec) { + // tr->civil_sec <= cs <= tr->prev_civil_sec + return MakeRepeated(*tr, cs); } // In between transitions. - int64_t unix_time = tr->unix_time + (dt - tr->date_time); - return MakeUnique(unix_time, normalized); + return MakeUnique(tr->unix_time + (cs - tr->civil_sec)); +} + +std::string TimeZoneInfo::Version() const { + return version_; +} + +std::string TimeZoneInfo::Description() const { + std::ostringstream oss; + oss << "#trans=" << transitions_.size(); + oss << " #types=" << transition_types_.size(); + oss << " spec='" << future_spec_ << "'"; + return oss.str(); +} + +bool TimeZoneInfo::NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const { + if (transitions_.empty()) return false; + const Transition* begin = &transitions_[0]; + const Transition* end = begin + transitions_.size(); + if (begin->unix_time <= -(1LL << 59)) { + // Do not report the BIG_BANG found in some zoneinfo data as it is + // really a sentinel, not a transition. See pre-2018f tz/zic.c. + ++begin; + } + std::int_fast64_t unix_time = ToUnixSeconds(tp); + const Transition target = {unix_time, 0, civil_second(), civil_second()}; + const Transition* tr = std::upper_bound(begin, end, target, + Transition::ByUnixTime()); + for (; tr != end; ++tr) { // skip no-op transitions + std::uint_fast8_t prev_type_index = + (tr == begin) ? default_transition_type_ : tr[-1].type_index; + if (!EquivTransitions(prev_type_index, tr[0].type_index)) break; + } + // When tr == end we return false, ignoring future_spec_. + if (tr == end) return false; + trans->from = tr->prev_civil_sec + 1; + trans->to = tr->civil_sec; + return true; +} + +bool TimeZoneInfo::PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const { + if (transitions_.empty()) return false; + const Transition* begin = &transitions_[0]; + const Transition* end = begin + transitions_.size(); + if (begin->unix_time <= -(1LL << 59)) { + // Do not report the BIG_BANG found in some zoneinfo data as it is + // really a sentinel, not a transition. See pre-2018f tz/zic.c. + ++begin; + } + std::int_fast64_t unix_time = ToUnixSeconds(tp); + if (FromUnixSeconds(unix_time) != tp) { + if (unix_time == std::numeric_limits::max()) { + if (end == begin) return false; // Ignore future_spec_. + trans->from = (--end)->prev_civil_sec + 1; + trans->to = end->civil_sec; + return true; + } + unix_time += 1; // ceils + } + const Transition target = {unix_time, 0, civil_second(), civil_second()}; + const Transition* tr = std::lower_bound(begin, end, target, + Transition::ByUnixTime()); + for (; tr != begin; --tr) { // skip no-op transitions + std::uint_fast8_t prev_type_index = + (tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index; + if (!EquivTransitions(prev_type_index, tr[-1].type_index)) break; + } + // When tr == end we return the "last" transition, ignoring future_spec_. + if (tr == begin) return false; + trans->from = (--tr)->prev_civil_sec + 1; + trans->to = tr->civil_sec; + return true; } } // namespace cctz diff --git a/src/time_zone_info.h b/src/time_zone_info.h index 4a1dce909..6e0001993 100644 --- a/src/time_zone_info.h +++ b/src/time_zone_info.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -16,124 +16,105 @@ #define CCTZ_TIME_ZONE_INFO_H_ #include +#include #include -#include +#include #include #include +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" +#include "cctz/zone_info_source.h" #include "time_zone_if.h" #include "tzfile.h" namespace cctz { -// A zone-independent date/time. A DateTime represents a "Y/M/D H:M:S" -// as an offset in seconds from some epoch DateTime, without taking into -// account the value of, or changes in any time_zone's UTC offset (i.e., as -// if the date/time was in UTC). This allows "Y/M/D H:M:S" values to be -// quickly ordered by offset (although this may not be the same ordering as -// their corresponding times in a time_zone). Also, if two DateTimes are not -// separated by a UTC-offset change in some time_zone, then the number of -// seconds between them can be computed as a simple difference of offsets. -// -// Note: Because the DateTime epoch does not correspond to the time_point -// epoch (even if only because of the unknown UTC offset) there can be valid -// times that will not be representable as DateTimes when DateTime only has -// the same number of "seconds" bits. We accept this at the moment (so as -// to avoid extended arithmetic) and lose a little range as a result. -struct DateTime { - int64_t offset; // seconds from some epoch DateTime - bool Normalize(int64_t year, int mon, int day, int hour, int min, int sec); - void Assign(const Breakdown& bd); -}; - -inline bool operator<(const DateTime& lhs, const DateTime& rhs) { - return lhs.offset < rhs.offset; -} - -// The difference between two DateTimes in seconds. Requires that all -// intervening DateTimes share the same UTC offset (i.e., no transitions). -inline int64_t operator-(const DateTime& lhs, const DateTime& rhs) { - return lhs.offset - rhs.offset; -} - // A transition to a new UTC offset. struct Transition { - int64_t unix_time; // the instant of this transition - uint8_t type_index; // index of the transition type - DateTime date_time; // local date/time of transition - DateTime prev_date_time; // local date/time one second earlier + std::int_least64_t unix_time; // the instant of this transition + std::uint_least8_t type_index; // index of the transition type + civil_second civil_sec; // local civil time of transition + civil_second prev_civil_sec; // local civil time one second earlier struct ByUnixTime { inline bool operator()(const Transition& lhs, const Transition& rhs) const { return lhs.unix_time < rhs.unix_time; } }; - struct ByDateTime { + struct ByCivilTime { inline bool operator()(const Transition& lhs, const Transition& rhs) const { - return lhs.date_time < rhs.date_time; + return lhs.civil_sec < rhs.civil_sec; } }; }; // The characteristics of a particular transition. struct TransitionType { - int32_t utc_offset; // the new prevailing UTC offset - bool is_dst; // did we move into daylight-saving time - uint8_t abbr_index; // index of the new abbreviation + std::int_least32_t utc_offset; // the new prevailing UTC offset + civil_second civil_max; // max convertible civil time for offset + civil_second civil_min; // min convertible civil time for offset + bool is_dst; // did we move into daylight-saving time + std::uint_least8_t abbr_index; // index of the new abbreviation }; - // A time zone backed by the IANA Time Zone Database (zoneinfo). class TimeZoneInfo : public TimeZoneIf { public: - TimeZoneInfo() = default; - TimeZoneInfo(const TimeZoneInfo&) = delete; - TimeZoneInfo& operator=(const TimeZoneInfo&) = delete; - - // Loads the zoneinfo for the given name, returning true if successful. - bool Load(const std::string& name); + // Factories. + static std::unique_ptr UTC(); // never fails + static std::unique_ptr Make(const std::string& name); // TimeZoneIf implementations. - Breakdown BreakTime(const time_point& tp) const override; - TimeInfo MakeTimeInfo(int64_t year, int mon, int day, - int hour, int min, int sec) const override; + time_zone::absolute_lookup BreakTime( + const time_point& tp) const override; + time_zone::civil_lookup MakeTime( + const civil_second& cs) const override; + bool NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const override; + bool PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const override; + std::string Version() const override; + std::string Description() const override; private: - struct Header { // counts of: - int32_t timecnt; // transition times - int32_t typecnt; // transition types - int32_t charcnt; // zone abbreviation characters - int32_t leapcnt; // leap seconds (we expect none) - int32_t ttisstdcnt; // UTC/local indicators (unused) - int32_t ttisgmtcnt; // standard/wall indicators (unused) - - void Build(const tzhead& tzh); - size_t DataLength(size_t time_len) const; - }; + TimeZoneInfo() = default; + TimeZoneInfo(const TimeZoneInfo&) = delete; + TimeZoneInfo& operator=(const TimeZoneInfo&) = delete; - void CheckTransition(const std::string& name, const TransitionType& tt, - int32_t offset, bool is_dst, - const std::string& abbr) const; + bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, + const std::string& abbr, std::uint_least8_t* index); + bool EquivTransitions(std::uint_fast8_t tt1_index, + std::uint_fast8_t tt2_index) const; + bool ExtendTransitions(); - void ResetToBuiltinUTC(int seconds); - bool Load(const std::string& name, FILE* fp); + bool ResetToBuiltinUTC(const seconds& offset); + bool Load(const std::string& name); + bool Load(ZoneInfoSource* zip); - // Helpers for BreakTime() and MakeTimeInfo() respectively. - Breakdown LocalTime(int64_t unix_time, const TransitionType& tt) const; - TimeInfo TimeLocal(int64_t year, int mon, int day, - int hour, int min, int sec, int64_t offset) const; + // Helpers for BreakTime() and MakeTime(). + time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, + const TransitionType& tt) const; + time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, + const Transition& tr) const; + time_zone::civil_lookup TimeLocal(const civil_second& cs, + year_t c4_shift) const; - std::vector transitions_; // ordered by unix_time and date_time + std::vector transitions_; // ordered by unix_time and civil_sec std::vector transition_types_; // distinct transition types - int default_transition_type_; // for before the first transition + std::uint_fast8_t default_transition_type_; // for before first transition std::string abbreviations_; // all the NUL-terminated abbreviations + std::string version_; // the tzdata version if available std::string future_spec_; // for after the last zic transition bool extended_; // future_spec_ was used to generate transitions - int64_t last_year_; // the final year of the generated transitions + year_t last_year_; // the final year of the generated transitions - mutable std::atomic local_time_hint_; // BreakTime() search hint - mutable std::atomic time_local_hint_; // MakeTimeInfo() search hint + // We remember the transitions found during the last BreakTime() and + // MakeTime() calls. If the next request is for the same transition we + // will avoid re-searching. + mutable std::atomic local_time_hint_ = {}; // BreakTime() hint + mutable std::atomic time_local_hint_ = {}; // MakeTime() hint }; } // namespace cctz diff --git a/src/time_zone_libc.cc b/src/time_zone_libc.cc index ea19540c6..61eaf7bb3 100644 --- a/src/time_zone_libc.cc +++ b/src/time_zone_libc.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,175 +12,318 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_WIN32) +#define _CRT_SECURE_NO_WARNINGS 1 +#endif + #include "time_zone_libc.h" #include -#include #include +#include +#include -// Define OFFSET(tm) and ABBR(tm) for your platform to return the UTC -// offset and zone abbreviation after a call to localtime_r(). -#if defined(linux) -# if defined(__USE_BSD) -# define OFFSET(tm) ((tm).tm_gmtoff) -# define ABBR(tm) ((tm).tm_zone) -# else -# define OFFSET(tm) ((tm).__tm_gmtoff) -# define ABBR(tm) ((tm).__tm_zone) -# endif -#elif defined(__APPLE__) -# define OFFSET(tm) ((tm).tm_gmtoff) -# define ABBR(tm) ((tm).tm_zone) -#elif defined(__sun) -# define OFFSET(tm) ((tm).tm_isdst > 0 ? altzone : timezone) -# define ABBR(tm) (tzname[(tm).tm_isdst > 0]) -#elif defined(_WIN32) || defined(_WIN64) -# define OFFSET(tm) (_timezone + ((tm).tm_isdst > 0 ? 60 * 60 : 0)) -# define ABBR(tm) (_tzname[(tm).tm_isdst > 0]) -#else -# define OFFSET(tm) (timezone + ((tm).tm_isdst > 0 ? 60 * 60 : 0)) -# define ABBR(tm) (tzname[(tm).tm_isdst > 0]) +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" + +#if defined(_AIX) +extern "C" { + extern long altzone; +} #endif namespace cctz { -TimeZoneLibC::TimeZoneLibC(const std::string& name) { - local_ = (name == "localtime"); - if (!local_) { - // TODO: Support "UTC-05:00", for example. - offset_ = 0; - abbr_ = "UTC"; - } +namespace { + +#if defined(_WIN32) || defined(_WIN64) +// Uses the globals: '_timezone', '_dstbias' and '_tzname'. +auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + _dstbias) { + const bool is_dst = tm.tm_isdst > 0; + return _timezone + (is_dst ? _dstbias : 0); +} +auto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return _tzname[is_dst]; +} +#elif defined(__sun) || defined(_AIX) +// Uses the globals: 'timezone', 'altzone' and 'tzname'. +auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) { + const bool is_dst = tm.tm_isdst > 0; + return is_dst ? altzone : timezone; +} +auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return tzname[is_dst]; +} +#elif defined(__native_client__) || defined(__myriad2__) || \ + defined(__EMSCRIPTEN__) +// Uses the globals: '_timezone' and 'tzname'. +auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) { + const bool is_dst = tm.tm_isdst > 0; + return _timezone + (is_dst ? 60 * 60 : 0); +} +auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return tzname[is_dst]; +} +#elif defined(__VXWORKS__) +// Uses the globals: 'timezone' and 'tzname'. +auto tm_gmtoff(const std::tm& tm) -> decltype(timezone + 0) { + const bool is_dst = tm.tm_isdst > 0; + return timezone + (is_dst ? 60 * 60 : 0); +} +auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return tzname[is_dst]; +} +#else +// Adapt to different spellings of the struct std::tm extension fields. +#if defined(tm_gmtoff) +auto tm_gmtoff(const std::tm& tm) -> decltype(tm.tm_gmtoff) { + return tm.tm_gmtoff; +} +#elif defined(__tm_gmtoff) +auto tm_gmtoff(const std::tm& tm) -> decltype(tm.__tm_gmtoff) { + return tm.__tm_gmtoff; +} +#else +template +auto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) { + return tm.tm_gmtoff; +} +template +auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) { + return tm.__tm_gmtoff; +} +#endif // tm_gmtoff +#if defined(tm_zone) +auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { + return tm.tm_zone; +} +#elif defined(__tm_zone) +auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) { + return tm.__tm_zone; +} +#else +template +auto tm_zone(const T& tm) -> decltype(tm.tm_zone) { + return tm.tm_zone; } +template +auto tm_zone(const T& tm) -> decltype(tm.__tm_zone) { + return tm.__tm_zone; +} +#endif // tm_zone +#endif +using tm_gmtoff_t = decltype(tm_gmtoff(std::tm{})); -Breakdown TimeZoneLibC::BreakTime(const time_point& tp) const { - Breakdown bd; - std::time_t t = ToUnixSeconds(tp); - std::tm tm; - if (local_) { +inline std::tm* gm_time(const std::time_t *timep, std::tm *result) { #if defined(_WIN32) || defined(_WIN64) - localtime_s(&tm, &t); + return gmtime_s(result, timep) ? nullptr : result; #else - localtime_r(&t, &tm); + return gmtime_r(timep, result); #endif - bd.offset = OFFSET(tm); - bd.abbr = ABBR(tm); - } else { +} + +inline std::tm* local_time(const std::time_t *timep, std::tm *result) { #if defined(_WIN32) || defined(_WIN64) - gmtime_s(&tm, &t); + return localtime_s(result, timep) ? nullptr : result; #else - gmtime_r(&t, &tm); + return localtime_r(timep, result); #endif - bd.offset = offset_; - bd.abbr = abbr_; - } - bd.year = tm.tm_year + 1900; - bd.month = tm.tm_mon + 1; - bd.day = tm.tm_mday; - bd.hour = tm.tm_hour; - bd.minute = tm.tm_min; - bd.second = tm.tm_sec; - bd.weekday = (tm.tm_wday ? tm.tm_wday : 7); - bd.yearday = tm.tm_yday + 1; - bd.is_dst = tm.tm_isdst > 0; - return bd; } -namespace { +// Converts a civil second and "dst" flag into a time_t and a struct tm. +// Returns false if time_t cannot represent the requested civil second. +// Caller must have already checked that cs.year() will fit into a tm_year. +bool make_time(const civil_second& cs, int is_dst, std::time_t* t, + std::tm* tm) { + tm->tm_year = static_cast(cs.year() - year_t{1900}); + tm->tm_mon = cs.month() - 1; + tm->tm_mday = cs.day(); + tm->tm_hour = cs.hour(); + tm->tm_min = cs.minute(); + tm->tm_sec = cs.second(); + tm->tm_isdst = is_dst; + *t = std::mktime(tm); + if (*t == std::time_t{-1}) { + std::tm tm2; + const std::tm* tmp = local_time(t, &tm2); + if (tmp == nullptr || tmp->tm_year != tm->tm_year || + tmp->tm_mon != tm->tm_mon || tmp->tm_mday != tm->tm_mday || + tmp->tm_hour != tm->tm_hour || tmp->tm_min != tm->tm_min || + tmp->tm_sec != tm->tm_sec) { + // A true error (not just one second before the epoch). + return false; + } + } + return true; +} -// Normalize *val so that 0 <= *val < base, returning any carry. -int NormalizeField(int base, int* val, bool* normalized) { - int carry = *val / base; - *val %= base; - if (*val < 0) { - carry -= 1; - *val += base; +// Find the least time_t in [lo:hi] where local time matches offset, given: +// (1) lo doesn't match, (2) hi does, and (3) there is only one transition. +std::time_t find_trans(std::time_t lo, std::time_t hi, tm_gmtoff_t offset) { + std::tm tm; + while (lo + 1 != hi) { + const std::time_t mid = lo + (hi - lo) / 2; + std::tm* tmp = local_time(&mid, &tm); + if (tmp != nullptr) { + if (tm_gmtoff(*tmp) == offset) { + hi = mid; + } else { + lo = mid; + } + } else { + // If std::tm cannot hold some result we resort to a linear search, + // ignoring all failed conversions. Slow, but never really happens. + while (++lo != hi) { + tmp = local_time(&lo, &tm); + if (tmp != nullptr) { + if (tm_gmtoff(*tmp) == offset) break; + } + } + return lo; + } } - if (carry != 0) *normalized = true; - return carry; + return hi; } -bool IsLeap(int64_t year) { - return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); +} // namespace + +std::unique_ptr TimeZoneLibC::Make(const std::string& name) { + return std::unique_ptr(new TimeZoneLibC(name)); } -// The month lengths in non-leap and leap years respectively. -const int kDaysPerMonth[2][1+12] = { - {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {-1, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, -}; +time_zone::absolute_lookup TimeZoneLibC::BreakTime( + const time_point& tp) const { + time_zone::absolute_lookup al; + al.offset = 0; + al.is_dst = false; + al.abbr = "-00"; + + const std::int_fast64_t s = ToUnixSeconds(tp); -// The number of days in non-leap and leap years respectively. -const int kDaysPerYear[2] = {365, 366}; + // If std::time_t cannot hold the input we saturate the output. + if (s < std::numeric_limits::min()) { + al.cs = civil_second::min(); + return al; + } + if (s > std::numeric_limits::max()) { + al.cs = civil_second::max(); + return al; + } -// Map a (normalized) Y/M/D to the number of days before/after 1970-01-01. -// See http://howardhinnant.github.io/date_algorithms.html#days_from_civil. -std::time_t DayOrdinal(int64_t year, int month, int day) { - year -= (month <= 2 ? 1 : 0); - const std::time_t era = (year >= 0 ? year : year - 399) / 400; - const int yoe = static_cast(year - era * 400); - const int doy = (153 * (month + (month > 2 ? -3 : 9)) + 2) / 5 + day - 1; - const int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; - return era * 146097 + doe - 719468; // shift epoch to 1970-01-01 + const std::time_t t = static_cast(s); + std::tm tm; + std::tm* tmp = local_ ? local_time(&t, &tm) : gm_time(&t, &tm); + + // If std::tm cannot hold the result we saturate the output. + if (tmp == nullptr) { + al.cs = (s < 0) ? civil_second::min() : civil_second::max(); + return al; + } + + const year_t year = tmp->tm_year + year_t{1900}; + al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + al.offset = static_cast(tm_gmtoff(*tmp)); + al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz + al.is_dst = tmp->tm_isdst > 0; + return al; } -} // namespace +time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const { + if (!local_) { + // If time_point cannot hold the result we saturate. + static const civil_second min_tp_cs = + civil_second() + ToUnixSeconds(time_point::min()); + static const civil_second max_tp_cs = + civil_second() + ToUnixSeconds(time_point::max()); + const time_point tp = + (cs < min_tp_cs) + ? time_point::min() + : (cs > max_tp_cs) ? time_point::max() + : FromUnixSeconds(cs - civil_second()); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } -TimeInfo TimeZoneLibC::MakeTimeInfo(int64_t year, int mon, int day, - int hour, int min, int sec) const { - bool normalized = false; - std::time_t t; - if (local_) { - // Does not handle SKIPPED/AMBIGUOUS or huge years. - std::tm tm; - tm.tm_year = static_cast(year - 1900); - tm.tm_mon = mon - 1; - tm.tm_mday = day; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - tm.tm_isdst = -1; - t = std::mktime(&tm); - if (tm.tm_year != year - 1900 || tm.tm_mon != mon - 1 || - tm.tm_mday != day || tm.tm_hour != hour || - tm.tm_min != min || tm.tm_sec != sec) { - normalized = true; + // If tm_year cannot hold the requested year we saturate the result. + if (cs.year() < 0) { + if (cs.year() < std::numeric_limits::min() + year_t{1900}) { + const time_point tp = time_point::min(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; } } else { - min += NormalizeField(60, &sec, &normalized); - hour += NormalizeField(60, &min, &normalized); - day += NormalizeField(24, &hour, &normalized); - mon -= 1; // months are one-based - year += NormalizeField(12, &mon, &normalized); - mon += 1; // restore [1:12] - year += (mon > 2 ? 1 : 0); - int year_len = kDaysPerYear[IsLeap(year)]; - while (day > year_len) { - day -= year_len; - year += 1; - year_len = kDaysPerYear[IsLeap(year)]; + if (cs.year() - year_t{1900} > std::numeric_limits::max()) { + const time_point tp = time_point::max(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; } - while (day <= 0) { - year -= 1; - day += kDaysPerYear[IsLeap(year)]; + } + + // We probe with "is_dst" values of 0 and 1 to try to distinguish unique + // civil seconds from skipped or repeated ones. This is not always possible + // however, as the "dst" flag does not change over some offset transitions. + // We are also subject to the vagaries of mktime() implementations. For + // example, some implementations treat "tm_isdst" as a demand (useless), + // and some as a disambiguator (useful). + std::time_t t0, t1; + std::tm tm0, tm1; + if (make_time(cs, 0, &t0, &tm0) && make_time(cs, 1, &t1, &tm1)) { + if (tm0.tm_isdst == tm1.tm_isdst) { + // The civil time was singular (pre == trans == post). + const time_point tp = FromUnixSeconds(tm0.tm_isdst ? t1 : t0); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; } - year -= (mon > 2 ? 1 : 0); - bool leap_year = IsLeap(year); - while (day > kDaysPerMonth[leap_year][mon]) { - day -= kDaysPerMonth[leap_year][mon]; - if (++mon > 12) { - mon = 1; - year += 1; - leap_year = IsLeap(year); - } + + tm_gmtoff_t offset = tm_gmtoff(tm0); + if (t0 < t1) { // negative DST + std::swap(t0, t1); + offset = tm_gmtoff(tm1); } - t = ((((DayOrdinal(year, mon, day) * 24) + hour) * 60) + min) * 60 + sec; + + const std::time_t tt = find_trans(t1, t0, offset); + const time_point trans = FromUnixSeconds(tt); + + if (tm0.tm_isdst) { + // The civil time did not exist (pre >= trans > post). + const time_point pre = FromUnixSeconds(t0); + const time_point post = FromUnixSeconds(t1); + return {time_zone::civil_lookup::SKIPPED, pre, trans, post}; + } + + // The civil time was ambiguous (pre < trans <= post). + const time_point pre = FromUnixSeconds(t1); + const time_point post = FromUnixSeconds(t0); + return {time_zone::civil_lookup::REPEATED, pre, trans, post}; } - TimeInfo ti; - ti.kind = time_zone::civil_lookup::UNIQUE; - ti.pre = ti.trans = ti.post = FromUnixSeconds(t); - ti.normalized = normalized; - return ti; + + // make_time() failed somehow so we saturate the result. + const time_point tp = (cs < civil_second()) + ? time_point::min() + : time_point::max(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; } +bool TimeZoneLibC::NextTransition(const time_point&, + time_zone::civil_transition*) const { + return false; +} + +bool TimeZoneLibC::PrevTransition(const time_point&, + time_zone::civil_transition*) const { + return false; +} + +std::string TimeZoneLibC::Version() const { + return std::string(); // unknown +} + +std::string TimeZoneLibC::Description() const { + return local_ ? "localtime" : "UTC"; +} + +TimeZoneLibC::TimeZoneLibC(const std::string& name) + : local_(name == "localtime") {} + } // namespace cctz diff --git a/src/time_zone_libc.h b/src/time_zone_libc.h index 77fbc5057..0d7e5c99c 100644 --- a/src/time_zone_libc.h +++ b/src/time_zone_libc.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -15,28 +15,38 @@ #ifndef CCTZ_TIME_ZONE_LIBC_H_ #define CCTZ_TIME_ZONE_LIBC_H_ -#include +#include #include #include "time_zone_if.h" namespace cctz { -// A time zone backed by gmtime_r(3), localtime_r(3), and mktime(3), and -// which therefore only supports "localtime" and fixed offsets from UTC. +// A time zone backed by gmtime_r(3), localtime_r(3), and mktime(3), +// and which therefore only supports UTC and the local time zone. class TimeZoneLibC : public TimeZoneIf { public: - explicit TimeZoneLibC(const std::string& name); + // Factory. + static std::unique_ptr Make(const std::string& name); // TimeZoneIf implementations. - Breakdown BreakTime(const time_point& tp) const override; - TimeInfo MakeTimeInfo(int64_t year, int mon, int day, - int hour, int min, int sec) const override; + time_zone::absolute_lookup BreakTime( + const time_point& tp) const override; + time_zone::civil_lookup MakeTime( + const civil_second& cs) const override; + bool NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const override; + bool PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const override; + std::string Version() const override; + std::string Description() const override; private: - bool local_; // localtime or UTC - int offset_; // UTC offset when !local_ - std::string abbr_; // abbreviation when !local_ + explicit TimeZoneLibC(const std::string& name); + TimeZoneLibC(const TimeZoneLibC&) = delete; + TimeZoneLibC& operator=(const TimeZoneLibC&) = delete; + + const bool local_; // localtime or UTC }; } // namespace cctz diff --git a/src/time_zone_lookup.cc b/src/time_zone_lookup.cc index 449c3f5e7..02b69dab5 100644 --- a/src/time_zone_lookup.cc +++ b/src/time_zone_lookup.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,54 +12,202 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "time_zone.h" +#include "cctz/time_zone.h" +#if defined(__ANDROID__) +#include +#endif + +#if defined(__APPLE__) +#include +#include +#endif + +#if defined(__Fuchsia__) +#include +#include +#include +#include +#endif + +#include +#include #include +#include +#include +#include "time_zone_fixed.h" #include "time_zone_impl.h" +#if defined(_WIN32) +#include "time_zone_name_win.h" +#endif // _WIN32 + namespace cctz { +std::string time_zone::name() const { + return effective_impl().Name(); +} + +time_zone::absolute_lookup time_zone::lookup( + const time_point& tp) const { + return effective_impl().BreakTime(tp); +} + +time_zone::civil_lookup time_zone::lookup(const civil_second& cs) const { + return effective_impl().MakeTime(cs); +} + +bool time_zone::next_transition(const time_point& tp, + civil_transition* trans) const { + return effective_impl().NextTransition(tp, trans); +} + +bool time_zone::prev_transition(const time_point& tp, + civil_transition* trans) const { + return effective_impl().PrevTransition(tp, trans); +} + +std::string time_zone::version() const { + return effective_impl().Version(); +} + +std::string time_zone::description() const { + return effective_impl().Description(); +} + +const time_zone::Impl& time_zone::effective_impl() const { + if (impl_ == nullptr) { + // Dereferencing an implicit-UTC time_zone is expected to be + // rare, so we don't mind paying a small synchronization cost. + return *time_zone::Impl::UTC().impl_; + } + return *impl_; +} + +bool load_time_zone(const std::string& name, time_zone* tz) { + return time_zone::Impl::LoadTimeZone(name, tz); +} + time_zone utc_time_zone() { + return time_zone::Impl::UTC(); // avoid name lookup +} + +time_zone fixed_time_zone(const seconds& offset) { time_zone tz; - load_time_zone("UTC", &tz); + load_time_zone(FixedOffsetToName(offset), &tz); return tz; } time_zone local_time_zone() { -#if defined(_WIN32) || defined(_WIN64) - char* tz_env = nullptr; - _dupenv_s(*tz_env, nullptr, "TZ"); - const char* zone = tz_env; -#else - const char* zone = std::getenv("TZ"); + const char* zone = ":localtime"; +#if defined(__ANDROID__) + char sysprop[PROP_VALUE_MAX]; + if (__system_property_get("persist.sys.timezone", sysprop) > 0) { + zone = sysprop; + } #endif - if (zone != nullptr) { - if (*zone == ':') ++zone; - } else { - zone = "localtime"; +#if defined(__APPLE__) + std::vector buffer; + CFTimeZoneRef tz_default = CFTimeZoneCopyDefault(); + if (CFStringRef tz_name = CFTimeZoneGetName(tz_default)) { + CFStringEncoding encoding = kCFStringEncodingUTF8; + CFIndex length = CFStringGetLength(tz_name); + CFIndex max_size = CFStringGetMaximumSizeForEncoding(length, encoding) + 1; + buffer.resize(static_cast(max_size)); + if (CFStringGetCString(tz_name, &buffer[0], max_size, encoding)) { + zone = &buffer[0]; + } } - time_zone tz; - if (!load_time_zone(zone, &tz)) { - load_time_zone("UTC", &tz); + CFRelease(tz_default); +#endif +#if defined(__Fuchsia__) + std::string primary_tz; + [&]() { + // Note: We can't use the synchronous FIDL API here because it doesn't + // allow timeouts; if the FIDL call failed, local_time_zone() would never + // return. + + const zx::duration kTimeout = zx::msec(500); + + // Don't attach to the thread because otherwise the thread's dispatcher + // would be set to null when the loop is destroyed, causing any other FIDL + // code running on the same thread to crash. + async::Loop loop(&kAsyncLoopConfigNeverAttachToThread); + + fuchsia::intl::PropertyProviderHandle handle; + zx_status_t status = fdio_service_connect_by_name( + fuchsia::intl::PropertyProvider::Name_, + handle.NewRequest().TakeChannel().release()); + if (status != ZX_OK) { + return; + } + + fuchsia::intl::PropertyProviderPtr intl_provider; + status = intl_provider.Bind(std::move(handle), loop.dispatcher()); + if (status != ZX_OK) { + return; + } + + intl_provider->GetProfile( + [&loop, &primary_tz](fuchsia::intl::Profile profile) { + if (!profile.time_zones().empty()) { + primary_tz = profile.time_zones()[0].id; + } + loop.Quit(); + }); + loop.Run(zx::deadline_after(kTimeout)); + }(); + + if (!primary_tz.empty()) { + zone = primary_tz.c_str(); + } +#endif +#if defined(_WIN32) + std::string win32_tz = GetWindowsLocalTimeZone(); + if (!win32_tz.empty()) { + zone = win32_tz.c_str(); } -#if defined(_WIN32) || defined(_WIN64) - free(tz_env); #endif - return tz; -} -bool load_time_zone(const std::string& name, time_zone* tz) { - return time_zone::Impl::LoadTimeZone(name, tz); -} + // Allow ${TZ} to override to default zone. + char* tz_env = nullptr; +#if defined(_MSC_VER) + _dupenv_s(&tz_env, nullptr, "TZ"); +#else + tz_env = std::getenv("TZ"); +#endif + if (tz_env) zone = tz_env; -time_zone::absolute_lookup time_zone::lookup( - const time_point& tp) const { - return time_zone::Impl::get(*this).BreakTime(tp); -} + // We only support the "[:]" form. + if (*zone == ':') ++zone; -time_zone::civil_lookup time_zone::lookup(const civil_second& cs) const { - return time_zone::Impl::get(*this).MakeTimeInfo(cs); + // Map "localtime" to a system-specific name, but + // allow ${LOCALTIME} to override the default name. + char* localtime_env = nullptr; + if (strcmp(zone, "localtime") == 0) { +#if defined(_MSC_VER) + // System-specific default is just "localtime". + _dupenv_s(&localtime_env, nullptr, "LOCALTIME"); +#else + zone = "/etc/localtime"; // System-specific default. + localtime_env = std::getenv("LOCALTIME"); +#endif + if (localtime_env) zone = localtime_env; + } + + const std::string name = zone; +#if defined(_MSC_VER) + free(localtime_env); + free(tz_env); +#endif + + time_zone tz; + load_time_zone(name, &tz); // Falls back to UTC. + // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and + // arrange for %z to generate "-0000" when we don't know the local + // offset because the load_time_zone() failed and we're using UTC. + return tz; } } // namespace cctz diff --git a/src/time_zone_lookup_test.cc b/src/time_zone_lookup_test.cc index 816feec43..ffcbcaf19 100644 --- a/src/time_zone_lookup_test.cc +++ b/src/time_zone_lookup_test.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,610 +12,30 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "time_zone.h" +#include "cctz/time_zone.h" #include +#include +#include #include #include #include #include #include +#if defined(__linux__) +#include +#endif +#include "cctz/civil_time.h" #include "gtest/gtest.h" +#include "test_time_zone_names.h" -using std::chrono::system_clock; +namespace chrono = std::chrono; namespace cctz { namespace { -// A list of known time-zone names. -const char* const kTimeZoneNames[] = { - "Africa/Abidjan", - "Africa/Accra", - "Africa/Addis_Ababa", - "Africa/Algiers", - "Africa/Asmara", - "Africa/Asmera", - "Africa/Bamako", - "Africa/Bangui", - "Africa/Banjul", - "Africa/Bissau", - "Africa/Blantyre", - "Africa/Brazzaville", - "Africa/Bujumbura", - "Africa/Cairo", - "Africa/Casablanca", - "Africa/Ceuta", - "Africa/Conakry", - "Africa/Dakar", - "Africa/Dar_es_Salaam", - "Africa/Djibouti", - "Africa/Douala", - "Africa/El_Aaiun", - "Africa/Freetown", - "Africa/Gaborone", - "Africa/Harare", - "Africa/Johannesburg", - "Africa/Juba", - "Africa/Kampala", - "Africa/Khartoum", - "Africa/Kigali", - "Africa/Kinshasa", - "Africa/Lagos", - "Africa/Libreville", - "Africa/Lome", - "Africa/Luanda", - "Africa/Lubumbashi", - "Africa/Lusaka", - "Africa/Malabo", - "Africa/Maputo", - "Africa/Maseru", - "Africa/Mbabane", - "Africa/Mogadishu", - "Africa/Monrovia", - "Africa/Nairobi", - "Africa/Ndjamena", - "Africa/Niamey", - "Africa/Nouakchott", - "Africa/Ouagadougou", - "Africa/Porto-Novo", - "Africa/Sao_Tome", - "Africa/Timbuktu", - "Africa/Tripoli", - "Africa/Tunis", - "Africa/Windhoek", - "America/Adak", - "America/Anchorage", - "America/Anguilla", - "America/Antigua", - "America/Araguaina", - "America/Argentina/Buenos_Aires", - "America/Argentina/Catamarca", - "America/Argentina/ComodRivadavia", - "America/Argentina/Cordoba", - "America/Argentina/Jujuy", - "America/Argentina/La_Rioja", - "America/Argentina/Mendoza", - "America/Argentina/Rio_Gallegos", - "America/Argentina/Salta", - "America/Argentina/San_Juan", - "America/Argentina/San_Luis", - "America/Argentina/Tucuman", - "America/Argentina/Ushuaia", - "America/Aruba", - "America/Asuncion", - "America/Atikokan", - "America/Atka", - "America/Bahia", - "America/Bahia_Banderas", - "America/Barbados", - "America/Belem", - "America/Belize", - "America/Blanc-Sablon", - "America/Boa_Vista", - "America/Bogota", - "America/Boise", - "America/Buenos_Aires", - "America/Cambridge_Bay", - "America/Campo_Grande", - "America/Cancun", - "America/Caracas", - "America/Catamarca", - "America/Cayenne", - "America/Cayman", - "America/Chicago", - "America/Chihuahua", - "America/Coral_Harbour", - "America/Cordoba", - "America/Costa_Rica", - "America/Creston", - "America/Cuiaba", - "America/Curacao", - "America/Danmarkshavn", - "America/Dawson", - "America/Dawson_Creek", - "America/Denver", - "America/Detroit", - "America/Dominica", - "America/Edmonton", - "America/Eirunepe", - "America/El_Salvador", - "America/Ensenada", - "America/Fort_Wayne", - "America/Fortaleza", - "America/Glace_Bay", - "America/Godthab", - "America/Goose_Bay", - "America/Grand_Turk", - "America/Grenada", - "America/Guadeloupe", - "America/Guatemala", - "America/Guayaquil", - "America/Guyana", - "America/Halifax", - "America/Havana", - "America/Hermosillo", - "America/Indiana/Indianapolis", - "America/Indiana/Knox", - "America/Indiana/Marengo", - "America/Indiana/Petersburg", - "America/Indiana/Tell_City", - "America/Indiana/Vevay", - "America/Indiana/Vincennes", - "America/Indiana/Winamac", - "America/Indianapolis", - "America/Inuvik", - "America/Iqaluit", - "America/Jamaica", - "America/Jujuy", - "America/Juneau", - "America/Kentucky/Louisville", - "America/Kentucky/Monticello", - "America/Knox_IN", - "America/Kralendijk", - "America/La_Paz", - "America/Lima", - "America/Los_Angeles", - "America/Louisville", - "America/Lower_Princes", - "America/Maceio", - "America/Managua", - "America/Manaus", - "America/Marigot", - "America/Martinique", - "America/Matamoros", - "America/Mazatlan", - "America/Mendoza", - "America/Menominee", - "America/Merida", - "America/Metlakatla", - "America/Mexico_City", - "America/Miquelon", - "America/Moncton", - "America/Monterrey", - "America/Montevideo", - "America/Montreal", - "America/Montserrat", - "America/Nassau", - "America/New_York", - "America/Nipigon", - "America/Nome", - "America/Noronha", - "America/North_Dakota/Beulah", - "America/North_Dakota/Center", - "America/North_Dakota/New_Salem", - "America/Ojinaga", - "America/Panama", - "America/Pangnirtung", - "America/Paramaribo", - "America/Phoenix", - "America/Port-au-Prince", - "America/Port_of_Spain", - "America/Porto_Acre", - "America/Porto_Velho", - "America/Puerto_Rico", - "America/Rainy_River", - "America/Rankin_Inlet", - "America/Recife", - "America/Regina", - "America/Resolute", - "America/Rio_Branco", - "America/Rosario", - "America/Santa_Isabel", - "America/Santarem", - "America/Santiago", - "America/Santo_Domingo", - "America/Sao_Paulo", - "America/Scoresbysund", - "America/Shiprock", - "America/Sitka", - "America/St_Barthelemy", - "America/St_Johns", - "America/St_Kitts", - "America/St_Lucia", - "America/St_Thomas", - "America/St_Vincent", - "America/Swift_Current", - "America/Tegucigalpa", - "America/Thule", - "America/Thunder_Bay", - "America/Tijuana", - "America/Toronto", - "America/Tortola", - "America/Vancouver", - "America/Virgin", - "America/Whitehorse", - "America/Winnipeg", - "America/Yakutat", - "America/Yellowknife", - "Antarctica/Casey", - "Antarctica/Davis", - "Antarctica/DumontDUrville", - "Antarctica/Macquarie", - "Antarctica/Mawson", - "Antarctica/McMurdo", - "Antarctica/Palmer", - "Antarctica/Rothera", - "Antarctica/South_Pole", - "Antarctica/Syowa", - "Antarctica/Troll", - "Antarctica/Vostok", - "Arctic/Longyearbyen", - "Asia/Aden", - "Asia/Almaty", - "Asia/Amman", - "Asia/Anadyr", - "Asia/Aqtau", - "Asia/Aqtobe", - "Asia/Ashgabat", - "Asia/Ashkhabad", - "Asia/Baghdad", - "Asia/Bahrain", - "Asia/Baku", - "Asia/Bangkok", - "Asia/Beirut", - "Asia/Bishkek", - "Asia/Brunei", - "Asia/Calcutta", - "Asia/Chita", - "Asia/Choibalsan", - "Asia/Chongqing", - "Asia/Chungking", - "Asia/Colombo", - "Asia/Dacca", - "Asia/Damascus", - "Asia/Dhaka", - "Asia/Dili", - "Asia/Dubai", - "Asia/Dushanbe", - "Asia/Gaza", - "Asia/Harbin", - "Asia/Hebron", - "Asia/Ho_Chi_Minh", - "Asia/Hong_Kong", - "Asia/Hovd", - "Asia/Irkutsk", - "Asia/Istanbul", - "Asia/Jakarta", - "Asia/Jayapura", - "Asia/Jerusalem", - "Asia/Kabul", - "Asia/Kamchatka", - "Asia/Karachi", - "Asia/Kashgar", - "Asia/Kathmandu", - "Asia/Katmandu", - "Asia/Khandyga", - "Asia/Kolkata", - "Asia/Krasnoyarsk", - "Asia/Kuala_Lumpur", - "Asia/Kuching", - "Asia/Kuwait", - "Asia/Macao", - "Asia/Macau", - "Asia/Magadan", - "Asia/Makassar", - "Asia/Manila", - "Asia/Muscat", - "Asia/Nicosia", - "Asia/Novokuznetsk", - "Asia/Novosibirsk", - "Asia/Omsk", - "Asia/Oral", - "Asia/Phnom_Penh", - "Asia/Pontianak", - "Asia/Pyongyang", - "Asia/Qatar", - "Asia/Qyzylorda", - "Asia/Rangoon", - "Asia/Riyadh", - "Asia/Saigon", - "Asia/Sakhalin", - "Asia/Samarkand", - "Asia/Seoul", - "Asia/Shanghai", - "Asia/Singapore", - "Asia/Srednekolymsk", - "Asia/Taipei", - "Asia/Tashkent", - "Asia/Tbilisi", - "Asia/Tehran", - "Asia/Tel_Aviv", - "Asia/Thimbu", - "Asia/Thimphu", - "Asia/Tokyo", - "Asia/Ujung_Pandang", - "Asia/Ulaanbaatar", - "Asia/Ulan_Bator", - "Asia/Urumqi", - "Asia/Ust-Nera", - "Asia/Vientiane", - "Asia/Vladivostok", - "Asia/Yakutsk", - "Asia/Yekaterinburg", - "Asia/Yerevan", - "Atlantic/Azores", - "Atlantic/Bermuda", - "Atlantic/Canary", - "Atlantic/Cape_Verde", - "Atlantic/Faeroe", - "Atlantic/Faroe", - "Atlantic/Jan_Mayen", - "Atlantic/Madeira", - "Atlantic/Reykjavik", - "Atlantic/South_Georgia", - "Atlantic/St_Helena", - "Atlantic/Stanley", - "Australia/ACT", - "Australia/Adelaide", - "Australia/Brisbane", - "Australia/Broken_Hill", - "Australia/Canberra", - "Australia/Currie", - "Australia/Darwin", - "Australia/Eucla", - "Australia/Hobart", - "Australia/LHI", - "Australia/Lindeman", - "Australia/Lord_Howe", - "Australia/Melbourne", - "Australia/NSW", - "Australia/North", - "Australia/Perth", - "Australia/Queensland", - "Australia/South", - "Australia/Sydney", - "Australia/Tasmania", - "Australia/Victoria", - "Australia/West", - "Australia/Yancowinna", - "Brazil/Acre", - "Brazil/DeNoronha", - "Brazil/East", - "Brazil/West", - "CET", - "CST6CDT", - "Canada/Atlantic", - "Canada/Central", - "Canada/East-Saskatchewan", - "Canada/Eastern", - "Canada/Mountain", - "Canada/Newfoundland", - "Canada/Pacific", - "Canada/Saskatchewan", - "Canada/Yukon", - "Chile/Continental", - "Chile/EasterIsland", - "Cuba", - "EET", - "EST", - "EST5EDT", - "Egypt", - "Eire", - "Etc/GMT", - "Etc/GMT+0", - "Etc/GMT+1", - "Etc/GMT+10", - "Etc/GMT+11", - "Etc/GMT+12", - "Etc/GMT+2", - "Etc/GMT+3", - "Etc/GMT+4", - "Etc/GMT+5", - "Etc/GMT+6", - "Etc/GMT+7", - "Etc/GMT+8", - "Etc/GMT+9", - "Etc/GMT-0", - "Etc/GMT-1", - "Etc/GMT-10", - "Etc/GMT-11", - "Etc/GMT-12", - "Etc/GMT-13", - "Etc/GMT-14", - "Etc/GMT-2", - "Etc/GMT-3", - "Etc/GMT-4", - "Etc/GMT-5", - "Etc/GMT-6", - "Etc/GMT-7", - "Etc/GMT-8", - "Etc/GMT-9", - "Etc/GMT0", - "Etc/Greenwich", - "Etc/UCT", - "Etc/UTC", - "Etc/Universal", - "Etc/Zulu", - "Europe/Amsterdam", - "Europe/Andorra", - "Europe/Athens", - "Europe/Belfast", - "Europe/Belgrade", - "Europe/Berlin", - "Europe/Bratislava", - "Europe/Brussels", - "Europe/Bucharest", - "Europe/Budapest", - "Europe/Busingen", - "Europe/Chisinau", - "Europe/Copenhagen", - "Europe/Dublin", - "Europe/Gibraltar", - "Europe/Guernsey", - "Europe/Helsinki", - "Europe/Isle_of_Man", - "Europe/Istanbul", - "Europe/Jersey", - "Europe/Kaliningrad", - "Europe/Kiev", - "Europe/Lisbon", - "Europe/Ljubljana", - "Europe/London", - "Europe/Luxembourg", - "Europe/Madrid", - "Europe/Malta", - "Europe/Mariehamn", - "Europe/Minsk", - "Europe/Monaco", - "Europe/Moscow", - "Europe/Nicosia", - "Europe/Oslo", - "Europe/Paris", - "Europe/Podgorica", - "Europe/Prague", - "Europe/Riga", - "Europe/Rome", - "Europe/Samara", - "Europe/San_Marino", - "Europe/Sarajevo", - "Europe/Simferopol", - "Europe/Skopje", - "Europe/Sofia", - "Europe/Stockholm", - "Europe/Tallinn", - "Europe/Tirane", - "Europe/Tiraspol", - "Europe/Uzhgorod", - "Europe/Vaduz", - "Europe/Vatican", - "Europe/Vienna", - "Europe/Vilnius", - "Europe/Volgograd", - "Europe/Warsaw", - "Europe/Zagreb", - "Europe/Zaporozhye", - "Europe/Zurich", - "GB", - "GB-Eire", - "GMT", - "GMT+0", - "GMT-0", - "GMT0", - "Greenwich", - "HST", - "Hongkong", - "Iceland", - "Indian/Antananarivo", - "Indian/Chagos", - "Indian/Christmas", - "Indian/Cocos", - "Indian/Comoro", - "Indian/Kerguelen", - "Indian/Mahe", - "Indian/Maldives", - "Indian/Mauritius", - "Indian/Mayotte", - "Indian/Reunion", - "Iran", - "Israel", - "Jamaica", - "Japan", - "Kwajalein", - "Libya", - "MET", - "MST", - "MST7MDT", - "Mexico/BajaNorte", - "Mexico/BajaSur", - "Mexico/General", - "NZ", - "NZ-CHAT", - "Navajo", - "PRC", - "PST8PDT", - "Pacific/Apia", - "Pacific/Auckland", - "Pacific/Bougainville", - "Pacific/Chatham", - "Pacific/Chuuk", - "Pacific/Easter", - "Pacific/Efate", - "Pacific/Enderbury", - "Pacific/Fakaofo", - "Pacific/Fiji", - "Pacific/Funafuti", - "Pacific/Galapagos", - "Pacific/Gambier", - "Pacific/Guadalcanal", - "Pacific/Guam", - "Pacific/Honolulu", - "Pacific/Johnston", - "Pacific/Kiritimati", - "Pacific/Kosrae", - "Pacific/Kwajalein", - "Pacific/Majuro", - "Pacific/Marquesas", - "Pacific/Midway", - "Pacific/Nauru", - "Pacific/Niue", - "Pacific/Norfolk", - "Pacific/Noumea", - "Pacific/Pago_Pago", - "Pacific/Palau", - "Pacific/Pitcairn", - "Pacific/Pohnpei", - "Pacific/Ponape", - "Pacific/Port_Moresby", - "Pacific/Rarotonga", - "Pacific/Saipan", - "Pacific/Samoa", - "Pacific/Tahiti", - "Pacific/Tarawa", - "Pacific/Tongatapu", - "Pacific/Truk", - "Pacific/Wake", - "Pacific/Wallis", - "Pacific/Yap", - "Poland", - "Portugal", - "ROC", - "ROK", - "Singapore", - "Turkey", - "UCT", - "US/Alaska", - "US/Aleutian", - "US/Arizona", - "US/Central", - "US/East-Indiana", - "US/Eastern", - "US/Hawaii", - "US/Indiana-Starke", - "US/Michigan", - "US/Mountain", - "US/Pacific", - "US/Pacific-New", - "US/Samoa", - "UTC", - "Universal", - "W-SU", - "WET", - "Zulu", - nullptr -}; - // Helper to return a loaded time zone by value (UTC on error). time_zone LoadZone(const std::string& name) { time_zone tz; @@ -636,35 +56,101 @@ time_zone LoadZone(const std::string& name) { EXPECT_EQ(ss, al.cs.second()); \ EXPECT_EQ(off, al.offset); \ EXPECT_TRUE(isdst == al.is_dst); \ - EXPECT_EQ(zone, al.abbr); \ + /* EXPECT_STREQ(zone, al.abbr); */ \ } while (0) +// These tests sometimes run on platforms that have zoneinfo data so old +// that the transition we are attempting to check does not exist, most +// notably Android emulators. Fortunately, AndroidZoneInfoSource supports +// time_zone::version() so, in cases where we've learned that it matters, +// we can make the check conditionally. +int VersionCmp(time_zone tz, const std::string& target) { + std::string version = tz.version(); + if (version.empty() && !target.empty()) return 1; // unknown > known + return version.compare(target); +} + } // namespace TEST(TimeZones, LoadZonesConcurrently) { std::promise ready_promise; std::shared_future ready_future(ready_promise.get_future()); - auto load_zones = [ready_future](std::promise* started) { + auto load_zones = [ready_future](std::promise* started, + std::set* failures) { started->set_value(); ready_future.wait(); - time_zone tz; for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { - EXPECT_TRUE(load_time_zone(*np, &tz)); + std::string zone = *np; + time_zone tz; + if (load_time_zone(zone, &tz)) { + EXPECT_EQ(zone, tz.name()); + } else { + failures->insert(zone); + } } }; + const std::size_t n_threads = 128; std::vector threads; - for (size_t i = 0; i != 256; ++i) { + std::vector> thread_failures(n_threads); + for (std::size_t i = 0; i != n_threads; ++i) { std::promise started; - threads.emplace_back(load_zones, &started); + threads.emplace_back(load_zones, &started, &thread_failures[i]); started.get_future().wait(); } - ready_promise.set_value(); - for (auto& thread : threads) { thread.join(); } + + // Allow a small number of failures to account for skew between + // the contents of kTimeZoneNames and the zoneinfo data source. +#if defined(__ANDROID__) + // Cater to the possibility of using an even older zoneinfo data + // source when running on Android, where it is difficult to override + // the bionic tzdata provided by the test environment. + const std::size_t max_failures = 20; +#else + const std::size_t max_failures = 3; +#endif + std::set failures; + for (const auto& thread_failure : thread_failures) { + failures.insert(thread_failure.begin(), thread_failure.end()); + } + EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures); +} + +TEST(TimeZone, UTC) { + const time_zone utc = utc_time_zone(); + + time_zone loaded_utc; + EXPECT_TRUE(load_time_zone("UTC", &loaded_utc)); + EXPECT_EQ(loaded_utc, utc); + + time_zone loaded_utc0; + EXPECT_TRUE(load_time_zone("UTC0", &loaded_utc0)); + EXPECT_EQ(loaded_utc0, utc); + + time_zone loaded_bad; + EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &loaded_bad)); + EXPECT_EQ(loaded_bad, utc); +} + +TEST(TimeZone, NamedTimeZones) { + const time_zone utc = utc_time_zone(); + EXPECT_EQ("UTC", utc.name()); + const time_zone nyc = LoadZone("America/New_York"); + EXPECT_EQ("America/New_York", nyc.name()); + const time_zone syd = LoadZone("Australia/Sydney"); + EXPECT_EQ("Australia/Sydney", syd.name()); + const time_zone fixed0 = fixed_time_zone(cctz::seconds::zero()); + EXPECT_EQ("UTC", fixed0.name()); + const time_zone fixed_pos = fixed_time_zone( + chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45)); + EXPECT_EQ("Fixed/UTC+03:25:45", fixed_pos.name()); + const time_zone fixed_neg = fixed_time_zone( + -(chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56))); + EXPECT_EQ("Fixed/UTC-12:34:56", fixed_neg.name()); } TEST(TimeZone, Failures) { @@ -673,126 +159,187 @@ TEST(TimeZone, Failures) { tz = LoadZone("America/Los_Angeles"); EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &tz)); - EXPECT_EQ(system_clock::from_time_t(0), + EXPECT_EQ(chrono::system_clock::from_time_t(0), convert(civil_second(1970, 1, 1, 0, 0, 0), tz)); // UTC // Ensures that the load still fails on a subsequent attempt. tz = LoadZone("America/Los_Angeles"); EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &tz)); - EXPECT_EQ(system_clock::from_time_t(0), + EXPECT_EQ(chrono::system_clock::from_time_t(0), convert(civil_second(1970, 1, 1, 0, 0, 0), tz)); // UTC // Loading an empty string timezone should fail. tz = LoadZone("America/Los_Angeles"); EXPECT_FALSE(load_time_zone("", &tz)); - EXPECT_EQ(system_clock::from_time_t(0), + EXPECT_EQ(chrono::system_clock::from_time_t(0), convert(civil_second(1970, 1, 1, 0, 0, 0), tz)); // UTC } +TEST(TimeZone, Equality) { + const time_zone a; + const time_zone b; + EXPECT_EQ(a, b); + EXPECT_EQ(a.name(), b.name()); + + const time_zone implicit_utc; + const time_zone explicit_utc = utc_time_zone(); + EXPECT_EQ(implicit_utc, explicit_utc); + EXPECT_EQ(implicit_utc.name(), explicit_utc.name()); + + const time_zone fixed_zero = fixed_time_zone(cctz::seconds::zero()); + EXPECT_EQ(fixed_zero, LoadZone(fixed_zero.name())); + EXPECT_EQ(fixed_zero, explicit_utc); + + const time_zone fixed_utc = LoadZone("Fixed/UTC+00:00:00"); + EXPECT_EQ(fixed_utc, LoadZone(fixed_utc.name())); + EXPECT_EQ(fixed_utc, explicit_utc); + + const time_zone fixed_pos = fixed_time_zone( + chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45)); + EXPECT_EQ(fixed_pos, LoadZone(fixed_pos.name())); + EXPECT_NE(fixed_pos, explicit_utc); + const time_zone fixed_neg = fixed_time_zone( + -(chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56))); + EXPECT_EQ(fixed_neg, LoadZone(fixed_neg.name())); + EXPECT_NE(fixed_neg, explicit_utc); + + const time_zone fixed_lim = fixed_time_zone(chrono::hours(24)); + EXPECT_EQ(fixed_lim, LoadZone(fixed_lim.name())); + EXPECT_NE(fixed_lim, explicit_utc); + const time_zone fixed_ovfl = + fixed_time_zone(chrono::hours(24) + chrono::seconds(1)); + EXPECT_EQ(fixed_ovfl, LoadZone(fixed_ovfl.name())); + EXPECT_EQ(fixed_ovfl, explicit_utc); + + EXPECT_EQ(fixed_time_zone(chrono::seconds(1)), + fixed_time_zone(chrono::seconds(1))); + + const time_zone local = local_time_zone(); + EXPECT_EQ(local, LoadZone(local.name())); + + time_zone la = LoadZone("America/Los_Angeles"); + time_zone nyc = LoadZone("America/New_York"); + EXPECT_NE(la, nyc); +} + TEST(StdChronoTimePoint, TimeTAlignment) { // Ensures that the Unix epoch and the system clock epoch are an integral // number of seconds apart. This simplifies conversions to/from time_t. - using TP = std::chrono::system_clock::time_point; - auto diff = TP() - std::chrono::system_clock::from_time_t(0); - EXPECT_EQ(TP::duration::zero(), diff % std::chrono::seconds(1)); + auto diff = chrono::system_clock::time_point() - + chrono::system_clock::from_time_t(0); + EXPECT_EQ(chrono::system_clock::time_point::duration::zero(), + diff % chrono::seconds(1)); } TEST(BreakTime, TimePointResolution) { - using std::chrono::time_point_cast; const time_zone utc = utc_time_zone(); - const auto t0 = system_clock::from_time_t(0); + const auto t0 = chrono::system_clock::from_time_t(0); - ExpectTime(time_point_cast(t0), utc, + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(time_point_cast(t0), utc, + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(time_point_cast(t0), utc, + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(time_point_cast(t0), utc, + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(time_point_cast(t0), utc, + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(time_point_cast(t0), utc, + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(time_point_cast(t0), utc, + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); } TEST(BreakTime, LocalTimeInUTC) { - const auto tp = system_clock::from_time_t(0); - const time_zone::absolute_lookup al = utc_time_zone().lookup(tp); - ExpectTime(tp, utc_time_zone(), 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - EXPECT_EQ(weekday::thursday, - get_weekday(civil_day(convert(tp, utc_time_zone())))); + const time_zone tz = utc_time_zone(); + const auto tp = chrono::system_clock::from_time_t(0); + ExpectTime(tp, tz, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz))); +} + +TEST(BreakTime, LocalTimeInUTCUnaligned) { + const time_zone tz = utc_time_zone(); + const auto tp = + chrono::system_clock::from_time_t(0) - chrono::milliseconds(500); + ExpectTime(tp, tz, 1969, 12, 31, 23, 59, 59, 0, false, "UTC"); + EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); } TEST(BreakTime, LocalTimePosix) { // See IEEE Std 1003.1-1988 B.2.3 General Terms, Epoch. - const auto tp = system_clock::from_time_t(536457599); - const time_zone::absolute_lookup al = utc_time_zone().lookup(tp); - ExpectTime(tp, utc_time_zone(), 1986, 12, 31, 23, 59, 59, 0, false, "UTC"); - EXPECT_EQ(weekday::wednesday, - get_weekday(civil_day(convert(tp, utc_time_zone())))); + const time_zone tz = utc_time_zone(); + const auto tp = chrono::system_clock::from_time_t(536457599); + ExpectTime(tp, tz, 1986, 12, 31, 23, 59, 59, 0, false, "UTC"); + EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); +} + +TEST(TimeZoneImpl, LocalTimeInFixed) { + const cctz::seconds offset = + -(chrono::hours(8) + chrono::minutes(33) + chrono::seconds(47)); + const time_zone tz = fixed_time_zone(offset); + const auto tp = chrono::system_clock::from_time_t(0); + ExpectTime(tp, tz, 1969, 12, 31, 15, 26, 13, offset.count(), false, + "-083347"); + EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); } TEST(BreakTime, LocalTimeInNewYork) { const time_zone tz = LoadZone("America/New_York"); - const auto tp = system_clock::from_time_t(45); + const auto tp = chrono::system_clock::from_time_t(45); ExpectTime(tp, tz, 1969, 12, 31, 19, 0, 45, -5 * 60 * 60, false, "EST"); - EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz)))); + EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); } TEST(BreakTime, LocalTimeInMTV) { const time_zone tz = LoadZone("America/Los_Angeles"); - const auto tp = system_clock::from_time_t(1380855729); + const auto tp = chrono::system_clock::from_time_t(1380855729); ExpectTime(tp, tz, 2013, 10, 3, 20, 2, 9, -7 * 60 * 60, true, "PDT"); - EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz)))); + EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz))); } TEST(BreakTime, LocalTimeInSydney) { const time_zone tz = LoadZone("Australia/Sydney"); - const auto tp = system_clock::from_time_t(90); - const time_zone::absolute_lookup al = tz.lookup(tp); + const auto tp = chrono::system_clock::from_time_t(90); ExpectTime(tp, tz, 1970, 1, 1, 10, 1, 30, 10 * 60 * 60, false, "AEST"); - EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz)))); + EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz))); } TEST(MakeTime, TimePointResolution) { const time_zone utc = utc_time_zone(); - const time_point tp_ns = + const time_point tp_ns = convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_ns, utc)); - const time_point tp_us = + EXPECT_EQ("04:05", cctz::format("%M:%E*S", tp_ns, utc)); + const time_point tp_us = convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_us, utc)); - const time_point tp_ms = + EXPECT_EQ("04:05", cctz::format("%M:%E*S", tp_us, utc)); + const time_point tp_ms = convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_ms, utc)); - const time_point tp_s = + EXPECT_EQ("04:05", cctz::format("%M:%E*S", tp_ms, utc)); + const time_point tp_s = convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_s, utc)); - const time_point tp_s64 = + EXPECT_EQ("04:05", cctz::format("%M:%E*S", tp_s, utc)); + const time_point tp_s64 = convert(civil_second(2015, 1, 2, 3, 4, 5), utc); - EXPECT_EQ("04:05", format("%M:%E*S", tp_s64, utc)); - - // These next two require time_point_cast because the conversion from a - // resolution of seconds (the return value of convert()) to a coarser - // resolution requires an explicit cast. - using std::chrono::time_point_cast; - const time_point tp_m = - time_point_cast( + EXPECT_EQ("04:05", cctz::format("%M:%E*S", tp_s64, utc)); + + // These next two require chrono::time_point_cast because the conversion + // from a resolution of seconds (the return value of convert()) to a + // coarser resolution requires an explicit cast. + const time_point tp_m = + chrono::time_point_cast( convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); - EXPECT_EQ("04:00", format("%M:%E*S", tp_m, utc)); - const time_point tp_h = - time_point_cast( + EXPECT_EQ("04:00", cctz::format("%M:%E*S", tp_m, utc)); + const time_point tp_h = + chrono::time_point_cast( convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); - EXPECT_EQ("00:00", format("%M:%E*S", tp_h, utc)); + EXPECT_EQ("00:00", cctz::format("%M:%E*S", tp_h, utc)); } TEST(MakeTime, Normalization) { const time_zone tz = LoadZone("America/New_York"); const auto tp = convert(civil_second(2009, 2, 13, 18, 31, 30), tz); - EXPECT_EQ(system_clock::from_time_t(1234567890), tp); + EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp); // Now requests for the same time_point but with out-of-range fields. EXPECT_EQ(tp, convert(civil_second(2008, 14, 13, 18, 31, 30), tz)); // month @@ -802,19 +349,315 @@ TEST(MakeTime, Normalization) { EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 18, 30, 90), tz)); // second } +// NOTE: Run this with -ftrapv to detect overflow problems. +TEST(MakeTime, SysSecondsLimits) { + const char RFC3339[] = "%Y-%m-%d%ET%H:%M:%S%Ez"; + const time_zone utc = utc_time_zone(); + const time_zone east = fixed_time_zone(chrono::hours(14)); + const time_zone west = fixed_time_zone(-chrono::hours(14)); + time_point tp; + + // Approach the maximal time_point value from below. + tp = convert(civil_second(292277026596, 12, 4, 15, 30, 6), utc); + EXPECT_EQ("292277026596-12-04T15:30:06+00:00", + cctz::format(RFC3339, tp, utc)); + tp = convert(civil_second(292277026596, 12, 4, 15, 30, 7), utc); + EXPECT_EQ("292277026596-12-04T15:30:07+00:00", + cctz::format(RFC3339, tp, utc)); + EXPECT_EQ(time_point::max(), tp); + tp = convert(civil_second(292277026596, 12, 4, 15, 30, 8), utc); + EXPECT_EQ(time_point::max(), tp); + tp = convert(civil_second::max(), utc); + EXPECT_EQ(time_point::max(), tp); + + // Checks that we can also get the maximal value for a far-east zone. + tp = convert(civil_second(292277026596, 12, 5, 5, 30, 7), east); + EXPECT_EQ("292277026596-12-05T05:30:07+14:00", + cctz::format(RFC3339, tp, east)); + EXPECT_EQ(time_point::max(), tp); + tp = convert(civil_second(292277026596, 12, 5, 5, 30, 8), east); + EXPECT_EQ(time_point::max(), tp); + tp = convert(civil_second::max(), east); + EXPECT_EQ(time_point::max(), tp); + + // Checks that we can also get the maximal value for a far-west zone. + tp = convert(civil_second(292277026596, 12, 4, 1, 30, 7), west); + EXPECT_EQ("292277026596-12-04T01:30:07-14:00", + cctz::format(RFC3339, tp, west)); + EXPECT_EQ(time_point::max(), tp); + tp = convert(civil_second(292277026596, 12, 4, 7, 30, 8), west); + EXPECT_EQ(time_point::max(), tp); + tp = convert(civil_second::max(), west); + EXPECT_EQ(time_point::max(), tp); + + // Approach the minimal time_point value from above. + tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 53), utc); + EXPECT_EQ("-292277022657-01-27T08:29:53+00:00", + cctz::format(RFC3339, tp, utc)); + tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 52), utc); + EXPECT_EQ("-292277022657-01-27T08:29:52+00:00", + cctz::format(RFC3339, tp, utc)); + EXPECT_EQ(time_point::min(), tp); + tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 51), utc); + EXPECT_EQ(time_point::min(), tp); + tp = convert(civil_second::min(), utc); + EXPECT_EQ(time_point::min(), tp); + + // Checks that we can also get the minimal value for a far-east zone. + tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 52), east); + EXPECT_EQ("-292277022657-01-27T22:29:52+14:00", + cctz::format(RFC3339, tp, east)); + EXPECT_EQ(time_point::min(), tp); + tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 51), east); + EXPECT_EQ(time_point::min(), tp); + tp = convert(civil_second::min(), east); + EXPECT_EQ(time_point::min(), tp); + + // Checks that we can also get the minimal value for a far-west zone. + tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 52), west); + EXPECT_EQ("-292277022657-01-26T18:29:52-14:00", + cctz::format(RFC3339, tp, west)); + EXPECT_EQ(time_point::min(), tp); + tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 51), west); + EXPECT_EQ(time_point::min(), tp); + tp = convert(civil_second::min(), west); + EXPECT_EQ(time_point::min(), tp); + + // Some similar checks for the "libc" time-zone implementation. + if (sizeof(std::time_t) >= 8) { + // Checks that "tm_year + 1900", as used by the "libc" implementation, + // can produce year values beyond the range on an int without overflow. +#if defined(_WIN32) || defined(_WIN64) + // localtime_s() and gmtime_s() don't believe in years outside [1970:3000]. +#else + const time_zone cut = LoadZone("libc:UTC"); + const year_t max_tm_year = year_t{std::numeric_limits::max()} + 1900; + tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), cut); +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__) + // Some gmtime_r() impls fail on extreme positive values. +#else + EXPECT_EQ("2147485547-12-31T23:59:59+00:00", + cctz::format(RFC3339, tp, cut)); +#endif + const year_t min_tm_year = year_t{std::numeric_limits::min()} + 1900; + tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), cut); +#if defined(__Fuchsia__) || defined(__EMSCRIPTEN__) + // Some gmtime_r() impls fail on extreme negative values (fxbug.dev/78527). +#else + EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", + cctz::format(RFC3339, tp, cut)); +#endif +#endif + } +} + +TEST(MakeTime, LocalTimeLibC) { + // Checks that cctz and libc agree on transition points in [1970:2037]. + // + // We limit this test case to environments where: + // 1) we know how to change the time zone used by localtime()/mktime(), + // 2) cctz and localtime()/mktime() will use similar-enough tzdata, and + // 3) we have some idea about how mktime() behaves during transitions. +#if defined(__linux__) && defined(__GLIBC__) && !defined(__ANDROID__) + const char* const ep = getenv("TZ"); + std::string tz_name = (ep != nullptr) ? ep : ""; + for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { + ASSERT_EQ(0, setenv("TZ", *np, 1)); // change what "localtime" means + const auto zi = local_time_zone(); + const auto lc = LoadZone("libc:localtime"); + time_zone::civil_transition transition; + for (auto tp = zi.lookup(civil_second()).trans; + zi.next_transition(tp, &transition); + tp = zi.lookup(transition.to).trans) { + const auto fcl = zi.lookup(transition.from); + const auto tcl = zi.lookup(transition.to); + civil_second cs, us; // compare cs and us in zi and lc + if (fcl.kind == time_zone::civil_lookup::UNIQUE) { + if (tcl.kind == time_zone::civil_lookup::UNIQUE) { + // Both unique; must be an is_dst or abbr change. + ASSERT_EQ(transition.from, transition.to); + const auto trans = fcl.trans; + const auto tal = zi.lookup(trans); + const auto tprev = trans - cctz::seconds(1); + const auto pal = zi.lookup(tprev); + if (pal.is_dst == tal.is_dst) { + ASSERT_STRNE(pal.abbr, tal.abbr); + } + continue; + } + ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind); + cs = transition.to; + us = transition.from; + } else { + ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind); + ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind); + cs = transition.from; + us = transition.to; + } + if (us.year() > 2037) break; // limit test time (and to 32-bit time_t) + const auto cl_zi = zi.lookup(cs); + if (zi.lookup(cl_zi.pre).is_dst == zi.lookup(cl_zi.post).is_dst) { + // The "libc" implementation cannot correctly classify transitions + // that don't change the "tm_isdst" flag. In Europe/Volgograd, for + // example, there is a SKIPPED transition from +03 to +04 with dst=F + // on both sides ... + // 1540681199 = 2018-10-28 01:59:59 +03:00:00 [dst=F off=10800] + // 1540681200 = 2018-10-28 03:00:00 +04:00:00 [dst=F off=14400] + // but std::mktime(2018-10-28 02:00:00, tm_isdst=0) fails, unlike, + // say, the similar Europe/Chisinau transition from +02 to +03 ... + // 1521935999 = 2018-03-25 01:59:59 +02:00:00 [dst=F off=7200] + // 1521936000 = 2018-03-25 03:00:00 +03:00:00 [dst=T off=10800] + // where std::mktime(2018-03-25 02:00:00, tm_isdst=0) succeeds and + // returns 1521936000. + continue; + } + if (cs == civil_second(2037, 10, 4, 2, 0, 0)) { + const std::string tzname = *np; + if (tzname == "Africa/Casablanca" || tzname == "Africa/El_Aaiun") { + // The "libc" implementation gets this transition wrong (at least + // until 2018g when it was removed), returning an offset of 3600 + // instead of 0. TODO: Revert this when 2018g is ubiquitous. + continue; + } + } + const auto cl_lc = lc.lookup(cs); + SCOPED_TRACE(testing::Message() << "For " << cs << " in " << *np); + EXPECT_EQ(cl_zi.kind, cl_lc.kind); + EXPECT_EQ(cl_zi.pre, cl_lc.pre); + EXPECT_EQ(cl_zi.trans, cl_lc.trans); + EXPECT_EQ(cl_zi.post, cl_lc.post); + const auto ucl_zi = zi.lookup(us); + const auto ucl_lc = lc.lookup(us); + SCOPED_TRACE(testing::Message() << "For " << us << " in " << *np); + EXPECT_EQ(ucl_zi.kind, ucl_lc.kind); + EXPECT_EQ(ucl_zi.pre, ucl_lc.pre); + EXPECT_EQ(ucl_zi.trans, ucl_lc.trans); + EXPECT_EQ(ucl_zi.post, ucl_lc.post); + } + } + if (ep == nullptr) { + ASSERT_EQ(0, unsetenv("TZ")); + } else { + ASSERT_EQ(0, setenv("TZ", tz_name.c_str(), 1)); + } +#endif +} + +TEST(NextTransition, UTC) { + const auto tz = utc_time_zone(); + time_zone::civil_transition trans; + + auto tp = time_point::min(); + EXPECT_FALSE(tz.next_transition(tp, &trans)); + + tp = time_point::max(); + EXPECT_FALSE(tz.next_transition(tp, &trans)); +} + +TEST(PrevTransition, UTC) { + const auto tz = utc_time_zone(); + time_zone::civil_transition trans; + + auto tp = time_point::max(); + EXPECT_FALSE(tz.prev_transition(tp, &trans)); + + tp = time_point::min(); + EXPECT_FALSE(tz.prev_transition(tp, &trans)); +} + +TEST(NextTransition, AmericaNewYork) { + const auto tz = LoadZone("America/New_York"); + time_zone::civil_transition trans; + + auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz); + EXPECT_TRUE(tz.next_transition(tp, &trans)); + EXPECT_EQ(civil_second(2018, 11, 4, 2, 0, 0), trans.from); + EXPECT_EQ(civil_second(2018, 11, 4, 1, 0, 0), trans.to); + + tp = time_point::max(); + EXPECT_FALSE(tz.next_transition(tp, &trans)); + + tp = time_point::min(); + EXPECT_TRUE(tz.next_transition(tp, &trans)); + if (trans.from == civil_second(1918, 3, 31, 2, 0, 0)) { + // It looks like the tzdata is only 32 bit (probably macOS), + // which bottoms out at 1901-12-13T20:45:52+00:00. + EXPECT_EQ(civil_second(1918, 3, 31, 3, 0, 0), trans.to); + } else { + EXPECT_EQ(civil_second(1883, 11, 18, 12, 3, 58), trans.from); + EXPECT_EQ(civil_second(1883, 11, 18, 12, 0, 0), trans.to); + } +} + +TEST(PrevTransition, AmericaNewYork) { + const auto tz = LoadZone("America/New_York"); + time_zone::civil_transition trans; + + auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz); + EXPECT_TRUE(tz.prev_transition(tp, &trans)); + EXPECT_EQ(civil_second(2018, 3, 11, 2, 0, 0), trans.from); + EXPECT_EQ(civil_second(2018, 3, 11, 3, 0, 0), trans.to); + + tp = time_point::min(); + EXPECT_FALSE(tz.prev_transition(tp, &trans)); + + tp = time_point::max(); + EXPECT_TRUE(tz.prev_transition(tp, &trans)); + // We have a transition but we don't know which one. +} + +TEST(NextTransition, Scan) { + for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { + SCOPED_TRACE(testing::Message() << "In " << *np); + time_zone tz; + // EXPECT_TRUE(load_time_zone(*np, &tz)); + if (!load_time_zone(*np, &tz)) { + continue; // tolerate kTimeZoneNames/zoneinfo skew + } + + auto tp = time_point::min(); + time_zone::civil_transition trans; + while (tz.next_transition(tp, &trans)) { + time_zone::civil_lookup from_cl = tz.lookup(trans.from); + EXPECT_NE(from_cl.kind, time_zone::civil_lookup::REPEATED); + time_zone::civil_lookup to_cl = tz.lookup(trans.to); + EXPECT_NE(to_cl.kind, time_zone::civil_lookup::SKIPPED); + + auto trans_tp = to_cl.trans; + time_zone::absolute_lookup trans_al = tz.lookup(trans_tp); + EXPECT_EQ(trans_al.cs, trans.to); + auto pre_trans_tp = trans_tp - cctz::seconds(1); + time_zone::absolute_lookup pre_trans_al = tz.lookup(pre_trans_tp); + EXPECT_EQ(pre_trans_al.cs + 1, trans.from); + + auto offset_delta = trans_al.offset - pre_trans_al.offset; + EXPECT_EQ(offset_delta, trans.to - trans.from); + if (offset_delta == 0) { + // This "transition" is only an is_dst or abbr change. + EXPECT_EQ(to_cl.kind, time_zone::civil_lookup::UNIQUE); + if (trans_al.is_dst == pre_trans_al.is_dst) { + EXPECT_STRNE(trans_al.abbr, pre_trans_al.abbr); + } + } + + tp = trans_tp; // continue scan from transition + } + } +} + TEST(TimeZoneEdgeCase, AmericaNewYork) { const time_zone tz = LoadZone("America/New_York"); // Spring 1:59:59 -> 3:00:00 auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz); ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -5 * 3600, false, "EST"); - tp += std::chrono::seconds(1); + tp += cctz::seconds(1); ExpectTime(tp, tz, 2013, 3, 10, 3, 0, 0, -4 * 3600, true, "EDT"); // Fall 1:59:59 -> 1:00:00 tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz); ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -4 * 3600, true, "EDT"); - tp += std::chrono::seconds(1); + tp += cctz::seconds(1); ExpectTime(tp, tz, 2013, 11, 3, 1, 0, 0, -5 * 3600, false, "EST"); } @@ -824,13 +667,13 @@ TEST(TimeZoneEdgeCase, AmericaLosAngeles) { // Spring 1:59:59 -> 3:00:00 auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz); ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -8 * 3600, false, "PST"); - tp += std::chrono::seconds(1); + tp += cctz::seconds(1); ExpectTime(tp, tz, 2013, 3, 10, 3, 0, 0, -7 * 3600, true, "PDT"); // Fall 1:59:59 -> 1:00:00 tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz); ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -7 * 3600, true, "PDT"); - tp += std::chrono::seconds(1); + tp += cctz::seconds(1); ExpectTime(tp, tz, 2013, 11, 3, 1, 0, 0, -8 * 3600, false, "PST"); } @@ -840,13 +683,13 @@ TEST(TimeZoneEdgeCase, ArizonaNoTransition) { // No transition in Spring. auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz); ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -7 * 3600, false, "MST"); - tp += std::chrono::seconds(1); + tp += cctz::seconds(1); ExpectTime(tp, tz, 2013, 3, 10, 2, 0, 0, -7 * 3600, false, "MST"); // No transition in Fall. tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz); ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -7 * 3600, false, "MST"); - tp += std::chrono::seconds(1); + tp += cctz::seconds(1); ExpectTime(tp, tz, 2013, 11, 3, 2, 0, 0, -7 * 3600, false, "MST"); } @@ -855,12 +698,12 @@ TEST(TimeZoneEdgeCase, AsiaKathmandu) { // A non-DST offset change from +0530 to +0545 // - // 504901799 == Tue, 31 Dec 1985 23:59:59 +0530 (IST) - // 504901800 == Wed, 1 Jan 1986 00:15:00 +0545 (NPT) + // 504901799 == Tue, 31 Dec 1985 23:59:59 +0530 (+0530) + // 504901800 == Wed, 1 Jan 1986 00:15:00 +0545 (+0545) auto tp = convert(civil_second(1985, 12, 31, 23, 59, 59), tz); - ExpectTime(tp, tz, 1985, 12, 31, 23, 59, 59, 5.5 * 3600, false, "IST"); - tp += std::chrono::seconds(1); - ExpectTime(tp, tz, 1986, 1, 1, 0, 15, 0, 5.75 * 3600, false, "NPT"); + ExpectTime(tp, tz, 1985, 12, 31, 23, 59, 59, 5.5 * 3600, false, "+0530"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 1986, 1, 1, 0, 15, 0, 5.75 * 3600, false, "+0545"); } TEST(TimeZoneEdgeCase, PacificChatham) { @@ -868,20 +711,19 @@ TEST(TimeZoneEdgeCase, PacificChatham) { // One-hour DST offset changes, but at atypical values // - // 1365256799 == Sun, 7 Apr 2013 03:44:59 +1345 (CHADT) - // 1365256800 == Sun, 7 Apr 2013 02:45:00 +1245 (CHAST) + // 1365256799 == Sun, 7 Apr 2013 03:44:59 +1345 (+1345) + // 1365256800 == Sun, 7 Apr 2013 02:45:00 +1245 (+1245) auto tp = convert(civil_second(2013, 4, 7, 3, 44, 59), tz); - ExpectTime(tp, tz, 2013, 4, 7, 3, 44, 59, 13.75 * 3600, true, "CHADT"); - tp += std::chrono::seconds(1); - ExpectTime(tp, tz, 2013, 4, 7, 2, 45, 0, 12.75 * 3600, false, "CHAST"); + ExpectTime(tp, tz, 2013, 4, 7, 3, 44, 59, 13.75 * 3600, true, "+1345"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 4, 7, 2, 45, 0, 12.75 * 3600, false, "+1245"); - // 1380376799 == Sun, 29 Sep 2013 02:44:59 +1245 (CHAST) - // 1380376800 == Sun, 29 Sep 2013 03:45:00 +1345 (CHADT) + // 1380376799 == Sun, 29 Sep 2013 02:44:59 +1245 (+1245) + // 1380376800 == Sun, 29 Sep 2013 03:45:00 +1345 (+1345) tp = convert(civil_second(2013, 9, 29, 2, 44, 59), tz); - ExpectTime(tp, tz, 2013, 9, 29, 2, 44, 59, 12.75 * 3600, false, - "CHAST"); - tp += std::chrono::seconds(1); - ExpectTime(tp, tz, 2013, 9, 29, 3, 45, 0, 13.75 * 3600, true, "CHADT"); + ExpectTime(tp, tz, 2013, 9, 29, 2, 44, 59, 12.75 * 3600, false, "+1245"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 9, 29, 3, 45, 0, 13.75 * 3600, true, "+1345"); } TEST(TimeZoneEdgeCase, AustraliaLordHowe) { @@ -889,19 +731,19 @@ TEST(TimeZoneEdgeCase, AustraliaLordHowe) { // Half-hour DST offset changes // - // 1365260399 == Sun, 7 Apr 2013 01:59:59 +1100 (LHDT) - // 1365260400 == Sun, 7 Apr 2013 01:30:00 +1030 (LHST) + // 1365260399 == Sun, 7 Apr 2013 01:59:59 +1100 (+11) + // 1365260400 == Sun, 7 Apr 2013 01:30:00 +1030 (+1030) auto tp = convert(civil_second(2013, 4, 7, 1, 59, 59), tz); - ExpectTime(tp, tz, 2013, 4, 7, 1, 59, 59, 11 * 3600, true, "LHDT"); - tp += std::chrono::seconds(1); - ExpectTime(tp, tz, 2013, 4, 7, 1, 30, 0, 10.5 * 3600, false, "LHST"); + ExpectTime(tp, tz, 2013, 4, 7, 1, 59, 59, 11 * 3600, true, "+11"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 4, 7, 1, 30, 0, 10.5 * 3600, false, "+1030"); - // 1380986999 == Sun, 6 Oct 2013 01:59:59 +1030 (LHST) - // 1380987000 == Sun, 6 Oct 2013 02:30:00 +1100 (LHDT) + // 1380986999 == Sun, 6 Oct 2013 01:59:59 +1030 (+1030) + // 1380987000 == Sun, 6 Oct 2013 02:30:00 +1100 (+11) tp = convert(civil_second(2013, 10, 6, 1, 59, 59), tz); - ExpectTime(tp, tz, 2013, 10, 6, 1, 59, 59, 10.5 * 3600, false, "LHST"); - tp += std::chrono::seconds(1); - ExpectTime(tp, tz, 2013, 10, 6, 2, 30, 0, 11 * 3600, true, "LHDT"); + ExpectTime(tp, tz, 2013, 10, 6, 1, 59, 59, 10.5 * 3600, false, "+1030"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 10, 6, 2, 30, 0, 11 * 3600, true, "+11"); } TEST(TimeZoneEdgeCase, PacificApia) { @@ -913,40 +755,44 @@ TEST(TimeZoneEdgeCase, PacificApia) { // // A one-day, non-DST offset change // - // 1325239199 == Thu, 29 Dec 2011 23:59:59 -1000 (SDT) - // 1325239200 == Sat, 31 Dec 2011 00:00:00 +1400 (WSDT) + // 1325239199 == Thu, 29 Dec 2011 23:59:59 -1000 (-10) + // 1325239200 == Sat, 31 Dec 2011 00:00:00 +1400 (+14) auto tp = convert(civil_second(2011, 12, 29, 23, 59, 59), tz); - ExpectTime(tp, tz, 2011, 12, 29, 23, 59, 59, -10 * 3600, true, "SDT"); - EXPECT_EQ(363, get_yearday(civil_day(convert(tp, tz)))); - tp += std::chrono::seconds(1); - ExpectTime(tp, tz, 2011, 12, 31, 0, 0, 0, 14 * 3600, true, "WSDT"); - EXPECT_EQ(365, get_yearday(civil_day(convert(tp, tz)))); + ExpectTime(tp, tz, 2011, 12, 29, 23, 59, 59, -10 * 3600, true, "-10"); + EXPECT_EQ(363, get_yearday(convert(tp, tz))); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2011, 12, 31, 0, 0, 0, 14 * 3600, true, "+14"); + EXPECT_EQ(365, get_yearday(convert(tp, tz))); } TEST(TimeZoneEdgeCase, AfricaCairo) { const time_zone tz = LoadZone("Africa/Cairo"); - // An interesting case of midnight not existing. - // - // 1400191199 == Thu, 15 May 2014 23:59:59 +0200 (EET) - // 1400191200 == Fri, 16 May 2014 01:00:00 +0300 (EEST) - auto tp = convert(civil_second(2014, 5, 15, 23, 59, 59), tz); - ExpectTime(tp, tz, 2014, 5, 15, 23, 59, 59, 2 * 3600, false, "EET"); - tp += std::chrono::seconds(1); - ExpectTime(tp, tz, 2014, 5, 16, 1, 0, 0, 3 * 3600, true, "EEST"); + if (VersionCmp(tz, "2014c") >= 0) { + // An interesting case of midnight not existing. + // + // 1400191199 == Thu, 15 May 2014 23:59:59 +0200 (EET) + // 1400191200 == Fri, 16 May 2014 01:00:00 +0300 (EEST) + auto tp = convert(civil_second(2014, 5, 15, 23, 59, 59), tz); + ExpectTime(tp, tz, 2014, 5, 15, 23, 59, 59, 2 * 3600, false, "EET"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2014, 5, 16, 1, 0, 0, 3 * 3600, true, "EEST"); + } } TEST(TimeZoneEdgeCase, AfricaMonrovia) { const time_zone tz = LoadZone("Africa/Monrovia"); - // Strange offset change -00:44:30 -> +00:00:00 (non-DST) - // - // 73529069 == Sun, 30 Apr 1972 23:59:59 -0044 (LRT) - // 73529070 == Mon, 1 May 1972 00:44:30 +0000 (GMT) - auto tp = convert(civil_second(1972, 4, 30, 23, 59, 59), tz); - ExpectTime(tp, tz, 1972, 4, 30, 23, 59, 59, -44.5 * 60, false, "LRT"); - tp += std::chrono::seconds(1); - ExpectTime(tp, tz, 1972, 5, 1, 0, 44, 30, 0 * 60, false, "GMT"); + if (VersionCmp(tz, "2017b") >= 0) { + // Strange offset change -00:44:30 -> +00:00:00 (non-DST) + // + // 63593069 == Thu, 6 Jan 1972 23:59:59 -0044 (MMT) + // 63593070 == Fri, 7 Jan 1972 00:44:30 +0000 (GMT) + auto tp = convert(civil_second(1972, 1, 6, 23, 59, 59), tz); + ExpectTime(tp, tz, 1972, 1, 6, 23, 59, 59, -44.5 * 60, false, "MMT"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 1972, 1, 7, 0, 44, 30, 0 * 60, false, "GMT"); + } } TEST(TimeZoneEdgeCase, AmericaJamaica) { @@ -958,25 +804,31 @@ TEST(TimeZoneEdgeCase, AmericaJamaica) { const time_zone tz = LoadZone("America/Jamaica"); // Before the first transition. - auto tp = convert(civil_second(1889, 12, 31, 0, 0, 0), tz); - ExpectTime(tp, tz, 1889, 12, 31, 0, 0, 0, -18431, false, - tz.lookup(tp).abbr); - - // Over the first (abbreviation-change only) transition. - // -2524503170 == Tue, 31 Dec 1889 23:59:59 -0507 (LMT) - // -2524503169 == Wed, 1 Jan 1890 00:00:00 -0507 (KMT) - tp = convert(civil_second(1889, 12, 31, 23, 59, 59), tz); - ExpectTime(tp, tz, 1889, 12, 31, 23, 59, 59, -18431, false, - tz.lookup(tp).abbr); - tp += std::chrono::seconds(1); - ExpectTime(tp, tz, 1890, 1, 1, 0, 0, 0, -18431, false, "KMT"); + if (!tz.version().empty() && VersionCmp(tz, "2018d") >= 0) { + // We avoid the expectations on the -18430 offset below unless we are + // certain we have commit 907241e (Fix off-by-1 error for Jamaica and + // T&C before 1913) from 2018d. TODO: Remove the "version() not empty" + // part when 2018d is generally available from /usr/share/zoneinfo. + auto tp = convert(civil_second(1889, 12, 31, 0, 0, 0), tz); + ExpectTime(tp, tz, 1889, 12, 31, 0, 0, 0, -18430, false, + tz.lookup(tp).abbr); + + // Over the first (abbreviation-change only) transition. + // -2524503170 == Tue, 31 Dec 1889 23:59:59 -0507 (LMT) + // -2524503169 == Wed, 1 Jan 1890 00:00:00 -0507 (KMT) + tp = convert(civil_second(1889, 12, 31, 23, 59, 59), tz); + ExpectTime(tp, tz, 1889, 12, 31, 23, 59, 59, -18430, false, + tz.lookup(tp).abbr); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 1890, 1, 1, 0, 0, 0, -18430, false, "KMT"); + } // Over the last (DST) transition. // 436341599 == Sun, 30 Oct 1983 01:59:59 -0400 (EDT) // 436341600 == Sun, 30 Oct 1983 01:00:00 -0500 (EST) - tp = convert(civil_second(1983, 10, 30, 1, 59, 59), tz); + auto tp = convert(civil_second(1983, 10, 30, 1, 59, 59), tz); ExpectTime(tp, tz, 1983, 10, 30, 1, 59, 59, -4 * 3600, true, "EDT"); - tp += std::chrono::seconds(1); + tp += cctz::seconds(1); ExpectTime(tp, tz, 1983, 10, 30, 1, 0, 0, -5 * 3600, false, "EST"); // After the last transition. @@ -984,59 +836,47 @@ TEST(TimeZoneEdgeCase, AmericaJamaica) { ExpectTime(tp, tz, 1983, 12, 31, 23, 59, 59, -5 * 3600, false, "EST"); } -TEST(TimeZoneEdgeCase, WET) { - // Cover some non-existent times within forward transitions. - const time_zone tz = LoadZone("WET"); +TEST(TimeZoneEdgeCase, EuropeLisbon) { + // Cover a non-existent time within a forward transition. + const time_zone tz = LoadZone("Europe/Lisbon"); - // Before the first transition. - auto tp = convert(civil_second(1977, 1, 1, 0, 0, 0), tz); - ExpectTime(tp, tz, 1977, 1, 1, 0, 0, 0, 0, false, "WET"); - - // Over the first transition. - // 228877199 == Sun, 3 Apr 1977 00:59:59 +0000 (WET) - // 228877200 == Sun, 3 Apr 1977 02:00:00 +0100 (WEST) - tp = convert(civil_second(1977, 4, 3, 0, 59, 59), tz); - ExpectTime(tp, tz, 1977, 4, 3, 0, 59, 59, 0, false, "WET"); - tp += std::chrono::seconds(1); - ExpectTime(tp, tz, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST"); - - // A non-existent time within the first transition. - time_zone::civil_lookup cl1 = tz.lookup(civil_second(1977, 4, 3, 1, 15, 0)); + // Over a forward transition. + // 354671999 == Sat, 28 Mar 1981 23:59:59 +0000 (WET) + // 354672000 == Sun, 29 Mar 1981 01:00:00 +0100 (WEST) + auto tp = convert(civil_second(1981, 3, 28, 23, 59, 59), tz); + ExpectTime(tp, tz, 1981, 3, 28, 23, 59, 59, 0, false, "WET"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 1981, 3, 29, 1, 0, 0, 1 * 3600, true, "WEST"); + + // A non-existent time within the transition. + time_zone::civil_lookup cl1 = tz.lookup(civil_second(1981, 3, 29, 0, 15, 0)); EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl1.kind); - ExpectTime(cl1.pre, tz, 1977, 4, 3, 2, 15, 0, 1 * 3600, true, "WEST"); - ExpectTime(cl1.trans, tz, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST"); - ExpectTime(cl1.post, tz, 1977, 4, 3, 0, 15, 0, 0 * 3600, false, "WET"); - - // A non-existent time within the second forward transition. - time_zone::civil_lookup cl2 = tz.lookup(civil_second(1978, 4, 2, 1, 15, 0)); - EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl2.kind); - ExpectTime(cl2.pre, tz, 1978, 4, 2, 2, 15, 0, 1 * 3600, true, "WEST"); - ExpectTime(cl2.trans, tz, 1978, 4, 2, 2, 0, 0, 1 * 3600, true, "WEST"); - ExpectTime(cl2.post, tz, 1978, 4, 2, 0, 15, 0, 0 * 3600, false, "WET"); + ExpectTime(cl1.pre, tz, 1981, 3, 29, 1, 15, 0, 1 * 3600, true, "WEST"); + ExpectTime(cl1.trans, tz, 1981, 3, 29, 1, 0, 0, 1 * 3600, true, "WEST"); + ExpectTime(cl1.post, tz, 1981, 3, 28, 23, 15, 0, 0 * 3600, false, "WET"); } TEST(TimeZoneEdgeCase, FixedOffsets) { const time_zone gmtm5 = LoadZone("Etc/GMT+5"); // -0500 auto tp = convert(civil_second(1970, 1, 1, 0, 0, 0), gmtm5); - ExpectTime(tp, gmtm5, 1970, 1, 1, 0, 0, 0, -5 * 3600, false, "GMT+5"); - EXPECT_EQ(system_clock::from_time_t(5 * 3600), tp); + ExpectTime(tp, gmtm5, 1970, 1, 1, 0, 0, 0, -5 * 3600, false, "-05"); + EXPECT_EQ(chrono::system_clock::from_time_t(5 * 3600), tp); const time_zone gmtp5 = LoadZone("Etc/GMT-5"); // +0500 tp = convert(civil_second(1970, 1, 1, 0, 0, 0), gmtp5); - ExpectTime(tp, gmtp5, 1970, 1, 1, 0, 0, 0, 5 * 3600, false, "GMT-5"); - EXPECT_EQ(system_clock::from_time_t(-5 * 3600), tp); + ExpectTime(tp, gmtp5, 1970, 1, 1, 0, 0, 0, 5 * 3600, false, "+05"); + EXPECT_EQ(chrono::system_clock::from_time_t(-5 * 3600), tp); } TEST(TimeZoneEdgeCase, NegativeYear) { // Tests transition from year 0 (aka 1BCE) to year -1. const time_zone tz = utc_time_zone(); auto tp = convert(civil_second(0, 1, 1, 0, 0, 0), tz); - time_zone::absolute_lookup al = tz.lookup(tp); ExpectTime(tp, tz, 0, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC"); - EXPECT_EQ(weekday::saturday, get_weekday(civil_day(convert(tp, tz)))); - tp -= std::chrono::seconds(1); + EXPECT_EQ(weekday::saturday, get_weekday(convert(tp, tz))); + tp -= cctz::seconds(1); ExpectTime(tp, tz, -1, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC"); - EXPECT_EQ(weekday::friday, get_weekday(civil_day(convert(tp, tz)))); + EXPECT_EQ(weekday::friday, get_weekday(convert(tp, tz))); } TEST(TimeZoneEdgeCase, UTC32bitLimit) { @@ -1048,7 +888,7 @@ TEST(TimeZoneEdgeCase, UTC32bitLimit) { // 2147483648 == Tue, 19 Jan 2038 03:14:08 +0000 (UTC) auto tp = convert(civil_second(2038, 1, 19, 3, 14, 7), tz); ExpectTime(tp, tz, 2038, 1, 19, 3, 14, 7, 0 * 3600, false, "UTC"); - tp += std::chrono::seconds(1); + tp += cctz::seconds(1); ExpectTime(tp, tz, 2038, 1, 19, 3, 14, 8, 0 * 3600, false, "UTC"); } @@ -1061,7 +901,7 @@ TEST(TimeZoneEdgeCase, UTC5DigitYear) { // 253402300800 == Sat, 1 Jan 1000 00:00:00 +0000 (UTC) auto tp = convert(civil_second(9999, 12, 31, 23, 59, 59), tz); ExpectTime(tp, tz, 9999, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC"); - tp += std::chrono::seconds(1); + tp += cctz::seconds(1); ExpectTime(tp, tz, 10000, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC"); } diff --git a/src/time_zone_name_win.cc b/src/time_zone_name_win.cc new file mode 100644 index 000000000..daa9a56d7 --- /dev/null +++ b/src/time_zone_name_win.cc @@ -0,0 +1,176 @@ +// Copyright 2025 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "time_zone_name_win.h" + +#if !defined(NOMINMAX) +#define NOMINMAX +#endif // !defined(NOMINMAX) +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace cctz { +namespace { + +// Define UChar as wchar_t here because Win32 APIs receive UTF-16 strings as +// wchar_t* instead of char16_t*. Using char16_t would require additional casts. +using UChar = wchar_t; + +enum UErrorCode : std::int32_t { + U_ZERO_ERROR = 0, + U_BUFFER_OVERFLOW_ERROR = 15, +}; + +bool U_SUCCESS(UErrorCode error) { return error <= U_ZERO_ERROR; } + +using ucal_getTimeZoneIDForWindowsID_func = std::int32_t(__cdecl*)( + const UChar* winid, std::int32_t len, const char* region, UChar* id, + std::int32_t id_capacity, UErrorCode* status); + +std::atomic g_unavailable; +std::atomic + g_ucal_getTimeZoneIDForWindowsID; + +template static T AsProcAddress(HMODULE module, const char* name) { + static_assert( + std::is_pointer::value && + std::is_function::type>::value, + "T must be a function pointer type"); + const auto proc_address = ::GetProcAddress(module, name); + return reinterpret_cast(reinterpret_cast(proc_address)); +} + +std::wstring GetSystem32Dir() { + std::wstring result; + std::uint32_t len = std::max( + static_cast(std::min( + result.capacity(), std::numeric_limits::max())), + 1); + do { + result.resize(len); + len = ::GetSystemDirectoryW(&result[0], len); + } while (len > result.size()); + result.resize(len); + return result; +} + +ucal_getTimeZoneIDForWindowsID_func LoadIcuGetTimeZoneIDForWindowsID() { + // This function is intended to be lock free to avoid potential deadlocks + // with loader-lock taken inside LoadLibraryW. As LoadLibraryW and + // GetProcAddress are idempotent unless the DLL is unloaded, we just need to + // make sure global variables are read/written atomically, where + // memory_order_relaxed is also acceptable. + + if (g_unavailable.load(std::memory_order_relaxed)) { + return nullptr; + } + + { + const auto ucal_getTimeZoneIDForWindowsIDRef = + g_ucal_getTimeZoneIDForWindowsID.load(std::memory_order_relaxed); + if (ucal_getTimeZoneIDForWindowsIDRef != nullptr) { + return ucal_getTimeZoneIDForWindowsIDRef; + } + } + + const std::wstring system32_dir = GetSystem32Dir(); + if (system32_dir.empty()) { + g_unavailable.store(true, std::memory_order_relaxed); + return nullptr; + } + + // Here LoadLibraryExW(L"icu.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32) does + // not work if "icu.dll" is already loaded from somewhere other than the + // system32 directory. Specifying the full path with LoadLibraryW is more + // reliable. + const std::wstring icu_dll_path = system32_dir + L"\\icu.dll"; + const HMODULE icu_dll = ::LoadLibraryW(icu_dll_path.c_str()); + if (icu_dll == nullptr) { + g_unavailable.store(true, std::memory_order_relaxed); + return nullptr; + } + + const auto ucal_getTimeZoneIDForWindowsIDRef = + AsProcAddress( + icu_dll, "ucal_getTimeZoneIDForWindowsID"); + if (ucal_getTimeZoneIDForWindowsIDRef != nullptr) { + g_unavailable.store(true, std::memory_order_relaxed); + return nullptr; + } + + g_ucal_getTimeZoneIDForWindowsID.store(ucal_getTimeZoneIDForWindowsIDRef, + std::memory_order_relaxed); + + return ucal_getTimeZoneIDForWindowsIDRef; +} + +// Convert wchar_t array (UTF-16) to UTF-8 string +std::string Utf16ToUtf8(const wchar_t* ptr, size_t size) { + if (size > static_cast(std::numeric_limits::max())) { + return std::string(); + } + const int chars_len = static_cast(size); + std::string result; + std::size_t len = std::max( + std::min(result.capacity(), std::numeric_limits::max()), 1); + do { + result.resize(len); + len = static_cast(::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, ptr, chars_len, &result[0], + static_cast(len), nullptr, nullptr)); + } while (len > result.size()); + result.resize(len); + return result; +} + +} // namespace + +std::string GetWindowsLocalTimeZone() { + const auto getTimeZoneIDForWindowsID = LoadIcuGetTimeZoneIDForWindowsID(); + if (getTimeZoneIDForWindowsID == nullptr) { + return std::string(); + } + + DYNAMIC_TIME_ZONE_INFORMATION info = {}; + if (::GetDynamicTimeZoneInformation(&info) == TIME_ZONE_ID_INVALID) { + return std::string(); + } + + std::wstring result; + std::size_t len = std::max( + std::min(result.capacity(), std::numeric_limits::max()), 1); + for (;;) { + UErrorCode status = U_ZERO_ERROR; + result.resize(len); + len = static_cast( + getTimeZoneIDForWindowsID(info.TimeZoneKeyName, -1, nullptr, &result[0], + static_cast(len), &status)); + if (U_SUCCESS(status)) { + return Utf16ToUtf8(result.data(), len); + } + if (status != U_BUFFER_OVERFLOW_ERROR) { + return std::string(); + } + } +} + +} // namespace cctz diff --git a/src/time_zone_name_win.h b/src/time_zone_name_win.h new file mode 100644 index 000000000..4a9de03d3 --- /dev/null +++ b/src/time_zone_name_win.h @@ -0,0 +1,29 @@ +// Copyright 2025 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CCTZ_TIME_ZONE_NAME_WIN_H_ +#define CCTZ_TIME_ZONE_NAME_WIN_H_ + +#include + +namespace cctz { + +// Returns the local time zone ID in IANA format (e.g. "America/Los_Angeles"), +// or the empty string on failure. Not supported on Windows 10 1809 and earlier, +// where "icu.dll" is not available in the System32 directory. +std::string GetWindowsLocalTimeZone(); + +} // namespace cctz + +#endif // CCTZ_TIME_ZONE_NAME_WIN_H_ diff --git a/src/time_zone_posix.cc b/src/time_zone_posix.cc index 5f0cc1ffb..847db17cb 100644 --- a/src/time_zone_posix.cc +++ b/src/time_zone_posix.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ #include "time_zone_posix.h" +#include #include #include #include @@ -48,7 +49,7 @@ const char* ParseAbbr(const char* p, std::string* abbr) { while (*++p != '>') { if (*p == '\0') return nullptr; } - abbr->assign(op + 1, p - op - 1); + abbr->assign(op + 1, static_cast(p - op) - 1); return ++p; } while (*p != '\0') { @@ -57,13 +58,13 @@ const char* ParseAbbr(const char* p, std::string* abbr) { ++p; } if (p - op < 3) return nullptr; - abbr->assign(op, p - op); + abbr->assign(op, static_cast(p - op)); return p; } // offset = [+|-]hh[:mm[:ss]] (aggregated into single seconds value) const char* ParseOffset(const char* p, int min_hour, int max_hour, int sign, - int* offset) { + std::int_fast32_t* offset) { if (p == nullptr) return nullptr; if (*p == '+' || *p == '-') { if (*p++ == '-') sign = -sign; @@ -71,6 +72,7 @@ const char* ParseOffset(const char* p, int min_hour, int max_hour, int sign, int hours = 0; int minutes = 0; int seconds = 0; + p = ParseInt(p, min_hour, max_hour, &hours); if (p == nullptr) return nullptr; if (*p == ':') { @@ -96,9 +98,9 @@ const char* ParseDateTime(const char* p, PosixTransition* res) { int weekday = 0; if ((p = ParseInt(p + 1, 0, 6, &weekday)) != nullptr) { res->date.fmt = PosixTransition::M; - res->date.m.month = month; - res->date.m.week = week; - res->date.m.weekday = weekday; + res->date.m.month = static_cast(month); + res->date.m.week = static_cast(week); + res->date.m.weekday = static_cast(weekday); } } } @@ -106,13 +108,13 @@ const char* ParseDateTime(const char* p, PosixTransition* res) { int day = 0; if ((p = ParseInt(p + 1, 1, 365, &day)) != nullptr) { res->date.fmt = PosixTransition::J; - res->date.j.day = day; + res->date.j.day = static_cast(day); } } else { int day = 0; if ((p = ParseInt(p, 0, 365, &day)) != nullptr) { res->date.fmt = PosixTransition::N; - res->date.j.day = day; + res->date.n.day = static_cast(day); } } } diff --git a/src/time_zone_posix.h b/src/time_zone_posix.h index 64f937bea..33e63f28e 100644 --- a/src/time_zone_posix.h +++ b/src/time_zone_posix.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -66,39 +66,49 @@ namespace cctz { // it would take us to another day, and perhaps week, or even month. struct PosixTransition { enum DateFormat { J, N, M }; - struct { + + struct Date { + struct NonLeapDay { + std::int_fast16_t day; // day of non-leap year [1:365] + }; + struct Day { + std::int_fast16_t day; // day of year [0:365] + }; + struct MonthWeekWeekday { + std::int_fast8_t month; // month of year [1:12] + std::int_fast8_t week; // week of month [1:5] (5==last) + std::int_fast8_t weekday; // 0==Sun, ..., 6=Sat + }; + DateFormat fmt; + union { - struct { - int16_t day; // day of non-leap year [1:365] - } j; - struct { - int16_t day; // day of year [0:365] - } n; - struct { - int8_t month; // month of year [1:12] - int8_t week; // week of month [1:5] (5==last) - int8_t weekday; // 0==Sun, ..., 6=Sat - } m; + NonLeapDay j; + Day n; + MonthWeekWeekday m; }; - } date; - struct { - int offset; // seconds before/after 00:00:00 - } time; + }; + + struct Time { + std::int_fast32_t offset; // seconds before/after 00:00:00 + }; + + Date date; + Time time; }; // The entirety of a POSIX-string specified time-zone rule. The standard // abbreviation and offset are always given. If the time zone includes -// daylight saving, then the daylight abbrevation is non-empty and the +// daylight saving, then the daylight abbreviation is non-empty and the // remaining fields are also valid. Note that the start/end transitions // are not ordered---in the southern hemisphere the transition to end // daylight time occurs first in any particular year. struct PosixTimeZone { std::string std_abbr; - int std_offset; + std::int_fast32_t std_offset; std::string dst_abbr; - int dst_offset; + std::int_fast32_t dst_offset; PosixTransition dst_start; PosixTransition dst_end; }; diff --git a/src/tzfile.h b/src/tzfile.h index ebecd6832..1941bc3b7 100644 --- a/src/tzfile.h +++ b/src/tzfile.h @@ -1,3 +1,5 @@ +/* Layout and location of TZif files. */ + #ifndef TZFILE_H #define TZFILE_H @@ -15,33 +17,20 @@ ** Thank you! */ -/* -** Information about time zone files. -*/ - -#ifndef TZDIR -#define TZDIR "/usr/local/etc/zoneinfo" /* Time zone object file directory */ -#endif /* !defined TZDIR */ - -#ifndef TZDEFAULT -#define TZDEFAULT "localtime" -#endif /* !defined TZDEFAULT */ - -#ifndef TZDEFRULES -#define TZDEFRULES "posixrules" -#endif /* !defined TZDEFRULES */ +/* Information about time zone files. + See Internet RFC 9636 for more details about the following format. */ /* ** Each file begins with. . . */ -#define TZ_MAGIC "TZif" +#define TZ_MAGIC "TZif" struct tzhead { char tzh_magic[4]; /* TZ_MAGIC */ - char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */ + char tzh_version[1]; /* '\0' or '2'-'4' as of 2021 */ char tzh_reserved[15]; /* reserved; must be zero */ - char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ + char tzh_ttisutcnt[4]; /* coded number of trans. time flags */ char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ char tzh_leapcnt[4]; /* coded number of leap seconds */ char tzh_timecnt[4]; /* coded number of transition times */ @@ -64,28 +53,31 @@ struct tzhead { ** one (char [4]) total correction after above ** tzh_ttisstdcnt (char)s indexed by type; if 1, transition ** time is standard time, if 0, -** transition time is wall clock time -** if absent, transition times are -** assumed to be wall clock time -** tzh_ttisgmtcnt (char)s indexed by type; if 1, transition -** time is UT, if 0, -** transition time is local time -** if absent, transition times are +** transition time is local (wall clock) +** time; if absent, transition times are ** assumed to be local time +** tzh_ttisutcnt (char)s indexed by type; if 1, transition +** time is UT, if 0, transition time is +** local time; if absent, transition +** times are assumed to be local time. +** When this is 1, the corresponding +** std/wall indicator must also be 1. */ /* ** If tzh_version is '2' or greater, the above is followed by a second instance ** of tzhead and a second instance of the data in which each coded transition ** time uses 8 rather than 4 chars, -** then a POSIX-TZ-environment-variable-style string for use in handling +** then a POSIX.1-2017 proleptic TZ string for use in handling ** instants after the last transition time stored in the file -** (with nothing between the newlines if there is no POSIX representation for -** such instants). +** (with nothing between the newlines if there is no POSIX.1-2017 +** representation for such instants). ** -** If tz_version is '3' or greater, the above is extended as follows. -** First, the POSIX TZ string's hour offset may range from -167 -** through 167 as compared to the POSIX-required 0 through 24. +** If tz_version is '3' or greater, the TZ string can be any POSIX.1-2024 +** proleptic TZ string, which means the above is extended as follows. +** First, the TZ string's hour offset may range from -167 +** through 167 as compared to the range 0 through 24 required +** by POSIX.1-2017 and earlier. ** Second, its DST start time may be January 1 at 00:00 and its stop ** time December 31 at 24:00 plus the difference between DST and ** standard time, indicating DST all year. @@ -97,73 +89,27 @@ struct tzhead { */ #ifndef TZ_MAX_TIMES -#define TZ_MAX_TIMES 2000 +/* The following limit applies to localtime.c; zic has no such limit. + The limit must be at least 310 for Asia/Hebron with 'zic -b fat'. */ +# define TZ_MAX_TIMES 2000 #endif /* !defined TZ_MAX_TIMES */ #ifndef TZ_MAX_TYPES -/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */ -#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ +/* This must be at least 18 for Europe/Vilnius with 'zic -b fat'. */ +# define TZ_MAX_TYPES 256 /* Limited to 256 by Internet RFC 9636. */ #endif /* !defined TZ_MAX_TYPES */ #ifndef TZ_MAX_CHARS -#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ - /* (limited by what unsigned chars can hold) */ +/* This must be at least 40 for America/Anchorage. */ +# define TZ_MAX_CHARS 256 /* Maximum number of abbreviation characters */ + /* (limited to 256 by Internet RFC 9636) */ #endif /* !defined TZ_MAX_CHARS */ #ifndef TZ_MAX_LEAPS -#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ +/* The following limit applies to localtime.c; zic has no such limit. + The limit must be at least 27 for leap seconds from 1972 through mid-2023. + There's a plan to discontinue leap seconds by 2035. */ +# define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ #endif /* !defined TZ_MAX_LEAPS */ -#define SECSPERMIN 60 -#define MINSPERHOUR 60 -#define HOURSPERDAY 24 -#define DAYSPERWEEK 7 -#define DAYSPERNYEAR 365 -#define DAYSPERLYEAR 366 -#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) -#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY) -#define MONSPERYEAR 12 - -#define TM_SUNDAY 0 -#define TM_MONDAY 1 -#define TM_TUESDAY 2 -#define TM_WEDNESDAY 3 -#define TM_THURSDAY 4 -#define TM_FRIDAY 5 -#define TM_SATURDAY 6 - -#define TM_JANUARY 0 -#define TM_FEBRUARY 1 -#define TM_MARCH 2 -#define TM_APRIL 3 -#define TM_MAY 4 -#define TM_JUNE 5 -#define TM_JULY 6 -#define TM_AUGUST 7 -#define TM_SEPTEMBER 8 -#define TM_OCTOBER 9 -#define TM_NOVEMBER 10 -#define TM_DECEMBER 11 - -#define TM_YEAR_BASE 1900 - -#define EPOCH_YEAR 1970 -#define EPOCH_WDAY TM_THURSDAY - -#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) - -/* -** Since everything in isleap is modulo 400 (or a factor of 400), we know that -** isleap(y) == isleap(y % 400) -** and so -** isleap(a + b) == isleap((a + b) % 400) -** or -** isleap(a + b) == isleap(a % 400 + b % 400) -** This is true even if % means modulo rather than Fortran remainder -** (which is allowed by C89 but not C99). -** We use this to avoid addition overflow problems. -*/ - -#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) - #endif /* !defined TZFILE_H */ diff --git a/src/zone_info_source.cc b/src/zone_info_source.cc new file mode 100644 index 000000000..2994ee41c --- /dev/null +++ b/src/zone_info_source.cc @@ -0,0 +1,72 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cctz/zone_info_source.h" + +namespace cctz { + +// Defined out-of-line to avoid emitting a weak vtable in all TUs. +ZoneInfoSource::~ZoneInfoSource() {} +std::string ZoneInfoSource::Version() const { return std::string(); } + +} // namespace cctz + +namespace cctz_extension { + +namespace { + +// A default for cctz_extension::zone_info_source_factory, which simply +// defers to the fallback factory. +std::unique_ptr DefaultFactory( + const std::string& name, + const std::function( + const std::string& name)>& fallback_factory) { + return fallback_factory(name); +} + +} // namespace + +// A "weak" definition for cctz_extension::zone_info_source_factory. +// The user may override this with their own "strong" definition (see +// zone_info_source.h). +#if !defined(__has_attribute) +#define __has_attribute(x) 0 +#endif +// MinGW is GCC on Windows, so while it asserts __has_attribute(weak), the +// Windows linker cannot handle that. Nor does the MinGW compiler know how to +// pass "#pragma comment(linker, ...)" to the Windows linker. +#if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__) && !defined(__CYGWIN__) +ZoneInfoSourceFactory zone_info_source_factory + __attribute__((weak)) = DefaultFactory; +#elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION) +extern ZoneInfoSourceFactory zone_info_source_factory; +extern ZoneInfoSourceFactory default_factory; +ZoneInfoSourceFactory default_factory = DefaultFactory; +#if defined(_M_IX86) || defined(_M_ARM) +#pragma comment( \ + linker, \ + "/alternatename:?zone_info_source_factory@cctz_extension@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@3@@ZA=?default_factory@cctz_extension@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@3@@ZA") +#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM64) +#pragma comment( \ + linker, \ + "/alternatename:?zone_info_source_factory@cctz_extension@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@3@@ZEA=?default_factory@cctz_extension@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@3@@ZEA") +#else +#error Unsupported MSVC platform +#endif // _M_ +#else +// Make it a "strong" definition if we have no other choice. +ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory; +#endif + +} // namespace cctz_extension diff --git a/testdata/README.zoneinfo b/testdata/README.zoneinfo new file mode 100644 index 000000000..0fe558585 --- /dev/null +++ b/testdata/README.zoneinfo @@ -0,0 +1,38 @@ +testdata/zoneinfo contains time-zone data files that may be used with CCTZ. +Install them in a location referenced by the ${TZDIR} environment variable. +Symbolic and hard links have been eliminated for portability. + +On Linux systems the distribution's versions of these files can probably +already be found in the default ${TZDIR} location, /usr/share/zoneinfo. + +New versions can be generated using the following shell script. + + #!/bin/sh - + set -e + DESTDIR=$(mktemp -d) + trap "rm -fr ${DESTDIR}" 0 2 15 + ( + cd ${DESTDIR} + git clone https://github.com/eggert/tz.git + make --directory=tz \ + install DESTDIR=${DESTDIR} \ + DATAFORM=vanguard \ + TZDIR=/zoneinfo \ + REDO=posix_only \ + LOCALTIME=Factory \ + TZDATA_TEXT= \ + PACKRATDATA=backzone PACKRATLIST=zone.tab \ + ZONETABLES=zone1970.tab\ zonenow.tab + tar --create --dereference --hard-dereference --file tzfile.tar \ + --directory=tz tzfile.h + tar --create --dereference --hard-dereference --file zoneinfo.tar \ + --exclude=zoneinfo/posixrules zoneinfo \ + --directory=tz version + ) + tar --extract --directory src --file ${DESTDIR}/tzfile.tar + tar --extract --directory testdata --file ${DESTDIR}/zoneinfo.tar + exit 0 + +To run the CCTZ tests using the testdata/zoneinfo files, execute: + + bazel test --test_env=TZDIR=${PWD}/testdata/zoneinfo ... diff --git a/testdata/version b/testdata/version new file mode 100644 index 000000000..5d9126009 --- /dev/null +++ b/testdata/version @@ -0,0 +1 @@ +2026a diff --git a/testdata/zoneinfo/Africa/Abidjan b/testdata/zoneinfo/Africa/Abidjan new file mode 100644 index 0000000000000000000000000000000000000000..8906e88c819d9ad3b794eb6356a240a74a95ffae GIT binary patch literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~>DeR?#{d8SSb#JG0gI1s2!lHia{&nh FE&z`x5Apy2 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Accra b/testdata/zoneinfo/Africa/Accra new file mode 100644 index 0000000000000000000000000000000000000000..c39ae382b5e8cf587c0fa38e729140aed60a222f GIT binary patch literal 700 zcmWHE%1kq2AP5+NDnJ+nLI`WI1uA0&Vv+wqFiUod35Z^JU`qp-{`BMnh+b?meF2!h znhEAF6+Nv0;xFAcw*W*h`}PkkzkK=yu>6V}Mqv4sl`LTSRlBx>`KzNl!TdF|UxC%H zwb=t!zphpeEWcj%16Y1TTp(C}!+&M4{3eHMVE(3uE5Q6MN?c&|TMpd;tKY_K3zpxu zgdZ%w{YfEMen+b_SbpcRZ(#ne^b=tI?iHF~^?N*igVpctj0MZ@)6xga@6Vb5mOsFq z1eQPOD+=ZxeES^CKdk2oR)6@sG+6yn{u;3S(G7lJ`C}h8faQ-*Yy!)lFysNtpDbYq z^G^vmfaOnzT7lJ{ZntRwh2y1%mn%T@?S;3&@^_q8OMv)yoB6={?I#~T<^KMYn1tfHhxd3yb75xAJ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Algiers b/testdata/zoneinfo/Africa/Algiers new file mode 100644 index 0000000000000000000000000000000000000000..56a4dd2a19fac5cc1bb1951dedf3ae93e0b9e321 GIT binary patch literal 470 zcmWHE%1kq2AP5+NDnJ+nLI`V70xDwzVyXW?kbQEt3W%PV5a17@XS-K?0MplX3PALn zJrlw7+yfq9@p+y9!2J0Ow7~oY2}{BB!Ui5Ny+}_8OfRnT0nXvkI2VBE^OH;jK=g$!1_ls)u}BQezvQO^)_2959ZWwxcNr}IIcCELkbjvf z4uWZB=M!L>_xyE`FazIO7cif{A_~kG$cPjGF@(yT3qZ7Rno|Ra7KyI`i;MclGcYnU zp+Hs^AY^6*iGdhQ%&b8B?tpYL88WZ{?GRw(0Pz@j85m>~7zIHh3}QaMAq)XP9PSzn TB0?CPK@4Xgg9}LL8gc;uxvi~T literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Asmara b/testdata/zoneinfo/Africa/Asmara new file mode 100644 index 0000000000000000000000000000000000000000..194e98690fbbbc183de75088ea787c873040b44c GIT binary patch literal 170 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#V!{7F;QT_e2SjJKZRY{e2iAX@!N>$uqEZ4f l4oCu(s$?*5FfeEtF!1{LhA=pSunUlIbqrzP0us8$TmTfd9XbF2 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Asmera b/testdata/zoneinfo/Africa/Asmera new file mode 100644 index 0000000000000000000000000000000000000000..194e98690fbbbc183de75088ea787c873040b44c GIT binary patch literal 170 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#V!{7F;QT_e2SjJKZRY{e2iAX@!N>$uqEZ4f l4oCu(s$?*5FfeEtF!1{LhA=pSunUlIbqrzP0us8$TmTfd9XbF2 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Bamako b/testdata/zoneinfo/Africa/Bamako new file mode 100644 index 0000000000000000000000000000000000000000..3cb875fade2d5152ef734c9cdf2d6653c6e5ebe2 GIT binary patch literal 158 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#p8r5F>De>}5WQ#8js_6@POx2ok%{sD{~rxN eB_P1^|NqAi3>-ebAq?(7tZQJ%zy)L&Z~*{nu^@#2 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Bangui b/testdata/zoneinfo/Africa/Bangui new file mode 100644 index 0000000000000000000000000000000000000000..0021d2d7fd6174288e212222ed0328159881de03 GIT binary patch literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~=~=A^P(UyTq?u2EfyKu+gdyB9gn4^f2O#lCXOkrREk{=jY YK%xvBKE5Fgx(0>}?m(IgNEmPd02-+k!vFvP literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Blantyre b/testdata/zoneinfo/Africa/Blantyre new file mode 100644 index 0000000000000000000000000000000000000000..d7bca1e6032a8fd0f6bf73f9804037a376d51695 GIT binary patch literal 165 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#VxIp%FiA+q07OrpUi=C~ukrj)!pH5r0bS00!_gZ|T%(YMJJ2mCH46+nSoWw9<*%M#eTu88u6kiej;Z)WRWASVq`B z7zHWasI-e&mZ3rh<)v~NCMeVvk;_b%PQ~T2_dNXpe(a3x+3!5h3qw@r9VnEL1rLi^ z&^JBmg&Gk50gKhK<#ZOVF@ou40|>*2QzR`l;) zIpE$4g|PWf3H<()4(>a9FNZ#7OW2R+ZH^dt#J2?=>DOWZW7KJAw3C)hLU z8tj$E!G4inzmZ;eN6688kNKcydmcy6?vV zE_h3Isf93StJYwqx$UUdLNiUKfzx-U!14eW_8DRxoMAZ#XL8)&%%>dev+Q5t?DH+? zw-2&(ggJ`*HuQ?h-RKoJoaj}>8(~#LC3@9htB#oybwmaFf^56ajrD(D%zu-H{wAS_ sIwNAO?v83vUeh=NXaYu)452`D0tw+@&^k4 zy7H8O{Cfd-Jk0c-!sD0z$yI)Cz|I3j$X??EB?JFZDcz%OJ zl9UHF26QqbkBi{UT5yv2OXl!T$dCN1nTF4i+SPlRjju7i?~8(bbn(gHkF^JxmeZmjAN^b%b4ZjF{zQDl)N7fKSBY{hq_j=}r}!M;&0!b7 zn+NBCQ(dv()Mr`Xw5n!sntL{Kn@Nv;n`8#3$Mk^H^Fxt4f(__*#M!`~js_t!UV0OK zW`_lw`H;U~wrwH$?5+g#J2P)E?esUUd>3pq&^IUW9`PK&$M$diDUFi3@?dS_l zx50(=^t7xiMsLZlN55ZO%1or^fl}6x%%J8?r zmFe_6rn-y%SQI^v50_$IHI1GQrw{D7MbBz8-}mbJ%jhL7-*3r6&y(VJ=uhhDS>sEQ z1o@l_D@5wde)hOF|U*8*$}fI+>l4lGr{55KNGhBedAvP$fgi_ zHh08;n;+8i?BNmYpX~}n-;&1fQH!0P=T?lPKWCt4TVM_L+oI^%?$LldH1zCjYQ=u% zEid{Xty`Hb^z71J19z3t^WtLuU%06M8vP~T9Z8VS$k!VgG7=7W!+i{>eG`kThKC?6`KP80#k5!0HzPUF95lVBfF&m zOdrer0HV2H@PH@=o-lrOzTd$1*Y{{PJ?Ovl09JBAZ0C>HjKR~z{rFJGP7WVz<^=_ zIRglQG@k$?2Z&_gWnhp|U=;N64Pgj(1>xWj24^6{8N}cMvUCkWOdVfiJySgc9bZEO J5Up>_1pwDUjA#G= literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Conakry b/testdata/zoneinfo/Africa/Conakry new file mode 100644 index 0000000000000000000000000000000000000000..c22c328b291f43ad3e7a70e16021bc35ed40fdab GIT binary patch literal 158 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#p8r5F>DlZU5WQ#8js_6@)-ebAq=_(h79gNnhQu6Z~*`Tlp7BK literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Dar_es_Salaam b/testdata/zoneinfo/Africa/Dar_es_Salaam new file mode 100644 index 0000000000000000000000000000000000000000..b37c2b4464968a2d972b0cefff54310bfe2665c8 GIT binary patch literal 161 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#zW+e5ZSmzbAo|+e`U@cXy-?Z}Mkb(XDpx?p iX&ErEFfgdCVc_ub4PkI~3}MhVFfuV^-~uvrjky4T2_1a^ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Djibouti b/testdata/zoneinfo/Africa/Djibouti new file mode 100644 index 0000000000000000000000000000000000000000..e9bbc7ad9f3a4bbcea298b2e90dda7ffa96c5f3a GIT binary patch literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@$)4fpnygRNVAp!1B;Ju2!pF*2m=?8 I&^6`)0ApPZ+5i9m literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Douala b/testdata/zoneinfo/Africa/Douala new file mode 100644 index 0000000000000000000000000000000000000000..65001f609d68d6efd398e1b8d54903deb9a49b34 GIT binary patch literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~=~-(AP=Hecq?u2EfyKu+gdyB9gn6W>4=RD6J;C|fOoId?L-?z!9 z=_we}^RizTFC2}sp&KZb1 zqUPMH>HTWX^Q0b8Q@5f4oVe*1aAMCg@Rrw>sK;WR)q zz4_70=nvZXeI4weXQ5#Z`oao&7O%d5{bJ)N`p^Dc20j#JMSkucKyL}6=V8|Y^oKnT z^d;s;;F4x~S~r)Xw-z;{KPp8sQ|S5S1n-y9FnZehHeug3osGRRdn>qXfS%>KJJ6S( zre|gBKRB<p2vTB3H#OaH=wt7buq{3dE(e|@QEv>NXKrsB$RPfOoMA8 z-U8QT(X&?b7=3LFJx`64ZdzopX=dgAacsQP(BaiQ4e^mDj{e!Mz<~TjQwkKfkl>|vMbH;yt1P1)C9)ADt w%BS@ErzS;!^1nu>2^Q*T)hCVeJXa@zladW0a&5GTz_nJ)ep`7J8yP+OU-J-s*8l(j literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Freetown b/testdata/zoneinfo/Africa/Freetown new file mode 100644 index 0000000000000000000000000000000000000000..8431ed65b9a5e92f0516c62f24c5dc664a105114 GIT binary patch literal 324 zcmWHE%1kq2AP5+NDnJ+nLI`US1}b9(VzK`~5LLC}4Tzq)eSZ#!-evb-0+_y+m;j=8 zuaE}w_w1kY0L0(h=`R4H_boU9mfxS%1eQP0>U56E0m36LHc1qMzA1}y_dULW5OhG56w5C&&Q5C$^1fGk}jE&%F=A*BES literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Harare b/testdata/zoneinfo/Africa/Harare new file mode 100644 index 0000000000000000000000000000000000000000..c4a502cfdecb5a3f831f8e375c49563f7a7e651d GIT binary patch literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iW=K=e-R@*mVKAS@Vn9nY+09MbT-~{G#G6aL=xfoQye6EM>V0rEbY+ydm z5gss~cmE48pKqx>SUvwr)&vG15NIm~%L{fq2lIu}mx1MlGfsl}B3{~HzNp7)FkehN z9;{wmqZiDV;F$!Lm*mI?^CjON1ItT&?0&!i1kxA0!F-vExnRER#yYTiiw0K(kbHu; yQ~(nr0m#h6z#zK>q+H8@5g3#*3JjbeHUqDZZwQ04V=#yaVQ>XvE+9kKhzkJma7J1H literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Kampala b/testdata/zoneinfo/Africa/Kampala new file mode 100644 index 0000000000000000000000000000000000000000..3021d844d9004a014759bd7562feab98fb47ba65 GIT binary patch literal 182 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwk^exj@!fqH5WVHltP3Fe+T6AqAo_Wadk7;F xGtgMM6p*=E1|U7k8Vno^3~Fl__B-;Q0 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Khartoum b/testdata/zoneinfo/Africa/Khartoum new file mode 100644 index 0000000000000000000000000000000000000000..3f8e44b8a6e171a0fde96736ed9d4fcde1bcd4a8 GIT binary patch literal 458 zcmWHE%1kq2AP5+NDnJ+nLI`V71}b9#V!{7Fux;@zkTwQ}dEyU16l0Z10ElL){rLby zGe@Ui0MRT7bq_!^tL+;wpUoiw%x9NZ0ITOva02r=8G^y`Tns8;KG(x`usrtzHZY&( z2oIRgyZ;54&$rYbte$@*YXSoh2(%T0c0XVM0_h9hV7|=7TrgjDV;xw%MT4sXNIvq% ylK>`00+5-BfkCbTq+H8@5g3#*3JjbeHUqDZZwQ04V=#yaVQ>XvE+9kKhzkHkp+^4z literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Kigali b/testdata/zoneinfo/Africa/Kigali new file mode 100644 index 0000000000000000000000000000000000000000..b2eff5701e2340e51aac4685596bb37f9966996d GIT binary patch literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iWg?;~FTP(a22q*+FRfyKu+gu&S{gnOyMyBk$eIS TEIz&=4B?I;3|v4$*N_VUx;ql$ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Lubumbashi b/testdata/zoneinfo/Africa/Lubumbashi new file mode 100644 index 0000000000000000000000000000000000000000..14e1ee1602e0fbb5d5199432309273cb141bf3c6 GIT binary patch literal 150 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%P~ofS0HPOlMSoxf%19mn$}sQ=Ft9K% Z$S5#y`1pn}ggb^XI0G>kkkB>a0stOe6h#04 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Lusaka b/testdata/zoneinfo/Africa/Lusaka new file mode 100644 index 0000000000000000000000000000000000000000..18fcb1689fd6c46e70acbb86e74f0c51f9302a40 GIT binary patch literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iW=<>WC{?lFfi~5 XFmU+zhA_ATakyg$0~e6cHRJ*SOiUFG literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Maputo b/testdata/zoneinfo/Africa/Maputo new file mode 100644 index 0000000000000000000000000000000000000000..581bb0e08b616a433d422ccb8f958cbebdae1770 GIT binary patch literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iW=>vXjYC?MAb(k!FEz~bW@!r<%}!oUS2 Hbd9(GSdtBU literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Maseru b/testdata/zoneinfo/Africa/Maseru new file mode 100644 index 0000000000000000000000000000000000000000..820d852155ef46868a0804a862c0f9fac44e33d5 GIT binary patch literal 157 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#&i_Erdf=7}VA<@cHDUAi{nmh^fsqNQgz*mp p!~g#uKY*1oFmNz1@Ch*R`1pn}=o%O@xC7~M#}EcCAfao>1pt!SAOZjY literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Nouakchott b/testdata/zoneinfo/Africa/Nouakchott new file mode 100644 index 0000000000000000000000000000000000000000..faa6f324cbd026309645ff5f1d783f1e248ac99b GIT binary patch literal 158 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#p8r5F>Dk;85WQ#8js_6@?&*mMj7*IG|9|8G c83zO`K=ua)4jK%IO73>-ebAq?(79PSvxzy)L&Z~*|L=^B#& literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Timbuktu b/testdata/zoneinfo/Africa/Timbuktu new file mode 100644 index 0000000000000000000000000000000000000000..3cb875fade2d5152ef734c9cdf2d6653c6e5ebe2 GIT binary patch literal 158 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#p8r5F>De>}5WQ#8js_6@POx2ok%{sD{~rxN eB_P1^|NqAi3>-ebAq?(7tZQJ%zy)L&Z~*{nu^@#2 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Tripoli b/testdata/zoneinfo/Africa/Tripoli new file mode 100644 index 0000000000000000000000000000000000000000..e0c89971aabea2c87842a9276b043d0fd946e34e GIT binary patch literal 431 zcmWHE%1kq2AP5+NDnJ+nLI`V704ievV!{7Fu<+AC6%c)Q_eKE_eNTC90*HQCaS6mo0*F>~*be3!`F#ZQja|&Z>P<|u9)RQn=FS9B41pmx8$fhW=9UH~MlfWC y(hweq1d4zV0|QSCNUe+lBQU)91Q<9$YzAH*-w+08*I*D4!r%(TTtGtChzkG|lxEie literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Tunis b/testdata/zoneinfo/Africa/Tunis new file mode 100644 index 0000000000000000000000000000000000000000..ca324cb4cd26cc29529faaee4c0465ae0cecc8f6 GIT binary patch literal 449 zcmWHE%1kq2AP5+NDnJ+nLI`V70xDwxV!{7F5a}lT1w>Cw2=E8d$E-RYfav29^Af=H zZ6z@O)T0nEeR^%?2ax!g=iUM!`s_;a31Iq=7z3C-vjHrAZjmXNe}0k)n17-3FFmeE0F2KO+;~T;d0L0F&!5|`pfeT3J8gc;ufb)m! literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Africa/Windhoek b/testdata/zoneinfo/Africa/Windhoek new file mode 100644 index 0000000000000000000000000000000000000000..0edc52b9b783827a8ac1090fe350bfe13977f745 GIT binary patch literal 638 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1uA0$V)6e#kX!9t0iv7S&S!w=GwXU9K=j#p`2`^J z)Yz6k0MWWV#}h!bUZ#uyh}N%t38EMbJpO_ChUu&gAij~t12Es%?KzllBKT(lNZeHI zB$#jd@gA6O&bAuNH@|oQ%(r;f3+7vHTm(2x8 z?W39nKn#cc05IRtDizFk@`nVRvy?lS@1idPmUsE33Ff=;eFO8|ZgGS8?mvVYKms0z z)hB>x&+A_rK(yClPB7nl`!z7%r|C7A?>l`5nD3W#7R>iAp9SUzIIRcs0~59bbu%yo zDNO|PgB@mq`61lv1VD^Xg=#QA^z{TVKb#>J%nv_Z1m;IPum|%aSBD5NGBGo;vXBTF z7z8*#CWuNfurM&lC@^p_FlZSt0!cmrMt-n}u#ayDgSLU8u>nJ{V{iyVxMK)|GZ1qD I30)&D0E>-r5C8xG literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Adak b/testdata/zoneinfo/America/Adak new file mode 100644 index 0000000000000000000000000000000000000000..b1497bda631efdcb6635ffb6b0ee6f7da9e2a280 GIT binary patch literal 969 zcmb8sT}V@57zgloA38U!R&8r8EjOz%UGtnxm-gk^nrPAL*iJ>eFc*Db5NSdbO?olJ9< z&oAKe*9H7uQJ9seKTplU^B)x81tZg#w_eV{3p3;JqLbI)#XZBYZO>`gzBvs$T2k;5 zUpMUZ45*B+N^=x;>G#5}dQT1YU0-B)=}ag~uF41D>Ipl%?5+)7eq$D{Io>YuG3FjD zz@A+`xc2aOf%+@LmrF*ScM_}n_@qHs_9%rc^-Clg(P5W=cv4)2# z_1j_@xb5pFNvAg$^(CeM`b_4s|N9ubJ;Ru$CHK*JKxRfw>+jZ;;jBQ%irPjeb86aP yudW((<<_{uwk7!9&9|(uD6gY2g+)4e(ZLG~FGPV?{&*-53<&o~)yl0u(`-5CoUZHL{FCdS_s%U>Hqtf9i&gJ(z=X374+=r7m(tA9> zmJJ=BphJ;Z{*weB6Zol8c{EQizNCEaiV~%q8*a=}&bxjjk-I|@6y>Ey$7IUt zojnr$kKKyMlyq0CVEv#6F6a+usBh?Q$x<%tsDzD*8#ejPu<80y*kYZBE$LaAk2B%x z3wXtc9NrhbnUko$GMk21P37R#cV}ekTgTGyn&C-!?U_-yxOW7$b@s#dy-9doFb=Qx z9)vfP_hlH5jh1@Yq3?hlH8v~t9p6H5$tQP;T$-{(jK(41EofxYkE!qxLhxaP@I*!SvMijT3a zw*uFL;|t+iz28v6Jy=`mF6Y zxbPF+{#?NPj@j4n&WyI-U5}^W-8Z!THjj_Pa-X(e_f0T6k0)xKL_^-!gG5_Dg*t6e^sp`NW?k;9f)uE)$jJt^UyO@1%{2b<|ou4Qn8cwiID%yCVwDC%yJ4p7$>coI3`C@**=ocm7FFwuL-T(jq literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Anguilla b/testdata/zoneinfo/America/Anguilla new file mode 100644 index 0000000000000000000000000000000000000000..d0577350733f631c79ff70f6808f47f4178413cc GIT binary patch literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~+1ylt@&ErL4;UE!|37|!fyKu+guyX5 LgnHq&@0t^iQ|L@$u b!1Dk9@dFGTKE5FguE8M;jzG)>Buuyf8A=^t literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Araguaina b/testdata/zoneinfo/America/Araguaina new file mode 100644 index 0000000000000000000000000000000000000000..f66c9f79d6cd4790c54d01286660f8ea0807f1c6 GIT binary patch literal 592 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1}b9)VxIp%Fl|+d0f^qg@A&{s|8-aZqIZ5Y0gLat zSE2yo-?CT-=HGh#3rydUe7FH5erIPSSpM#BQLy;E+4sQw`*&x7`42*j!Tc}N|AWku>3EsOJMcCR{Q|V|9-;;mjBaTy8!5R2HBH+ z1|V9l;`#y*Ex*8Y1Bg~IKED7&D>i0=<(0TkfceT10$_RNM+FKXc~$dIV7}^=<6yo) zLnT`31TlMRJ<*iTr2g}>!^MU!cM<#;h?fgD~`2o$TV1A&2 f0VB)*|5q0kJUymkp4#Gv)#Sd3?{w literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/Buenos_Aires b/testdata/zoneinfo/America/Argentina/Buenos_Aires new file mode 100644 index 0000000000000000000000000000000000000000..d6f999b8605c9f73653a16e2ddbd5a49b96c0f56 GIT binary patch literal 708 zcma)&O(?@*9LJwA%vxDdBx$mxO=`_%!ZhvRCA+X9CrU~waxf+2;-pquN?BvOI4E=Q z(l$1R;h@z>%3(!rgy!GO%j0>zE^a(ezrN4s|M@- z*%VN=MweFGd3xp@TAo`I9cG@}#iu@=JEacr&cz74zi=|lzxy}6@PX6@d~o3ke)swg zes5d~9|{z~hkG30eU}S-P#-}*G8IGrutb1A>J`HueQDsMO-A@=VjX-k73ro-j?Ke+k8AF%Hd_6<<3p8Qtkw+j4xo-(-^p-EKkdO z6|ruxnmmKmzB;fb5eHW;b}3km7=>fpuMKIC&Gy`%yqSh?NqfMp!9Im3BlDj-OZ;nR z;!NqOo)AhSF(Rfk8YU7-FJmGZrMC%@oS%uT-D)EiHdR_Zn`$;XB5h!&#%k#|fdER> literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/Catamarca b/testdata/zoneinfo/America/Argentina/Catamarca new file mode 100644 index 0000000000000000000000000000000000000000..1dcc8d85434c9d016f170cb2f16811ebef327b77 GIT binary patch literal 708 zcma)&-7AAp9LLYzm|0m-B#CTkL#^3Nm>%t7CA(oou3ShdMJ`MUxpAddT1stsyH%SD zFWJ}_h6}AWNx4{&J3{j`ug5uGe*ow7d%oxM`~1$ub6mZH119q4lCTM0e7XL}P#r@(W&^eo78r`!YHNsYko7EeZbe|K{YK9t>n4=-H7?_J-) z?~kkCBcT%bXs-u+;P-JF!i*jd#X&8+HKnTV=|om%Tv EKU&60&j0`b literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/ComodRivadavia b/testdata/zoneinfo/America/Argentina/ComodRivadavia new file mode 100644 index 0000000000000000000000000000000000000000..1dcc8d85434c9d016f170cb2f16811ebef327b77 GIT binary patch literal 708 zcma)&-7AAp9LLYzm|0m-B#CTkL#^3Nm>%t7CA(oou3ShdMJ`MUxpAddT1stsyH%SD zFWJ}_h6}AWNx4{&J3{j`ug5uGe*ow7d%oxM`~1$ub6mZH119q4lCTM0e7XL}P#r@(W&^eo78r`!YHNsYko7EeZbe|K{YK9t>n4=-H7?_J-) z?~kkCBcT%bXs-u+;P-JF!i*jd#X&8+HKnTV=|om%Tv EKU&60&j0`b literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/Cordoba b/testdata/zoneinfo/America/Argentina/Cordoba new file mode 100644 index 0000000000000000000000000000000000000000..35a52e53d123b5ef5d293b3af19046630f02bb66 GIT binary patch literal 708 zcma)&-7AAp9LLXIFiTlcB#CUTO=`_%^47EqFWC(%+7%_G6uB@ZhCZpmC= zZDV5?F7(tUDHkhpN76ja>v7I^f54p6@A>{d=kq%k&v7`128|@+lCTM0d^s{-X<}p9 ztO_YxW6RrKo*N5p1JC`*E-TN2l1rTX%G_XId=%baG!^FFzqbh=NbSN07jNMY?;hcg zCY11@KrwvS=>{LKtbk7%BAAa%3z$DG72(hN0YPeo(!A4wPdXRH?f zD`JNK4tB%;Y^C4pci9Z4^Cl~MTavTc;pM4NkF4>m^z4DvDi2s=c>`-+$HCf)d;_1; z3cX+*p;pd1Z#`I_h{0Da^_25-i+GOvbs;^n)s>sh`x*GQ&kb;Uu)ka)mHl&P$h(HLwa!R9NqM-CfkmOPNkdUZ&Px3nL4q{_fZ7{K_VPz!BM%FdgDE|PnyG!l> literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/Jujuy b/testdata/zoneinfo/America/Argentina/Jujuy new file mode 100644 index 0000000000000000000000000000000000000000..b275f27c0287415674d2ccc850c3d612f4a45b0f GIT binary patch literal 690 zcma)&-7AAp9LLYtn6--)MUoU6lUjQ*d28B*lHIUUu3ShdMJ`Z6Zd^#Mw3H%mw_+~F z@;aLtF4k%!aj}p)OPZ&7Jg# zqbm60{Q`JjmlJ%lv;_9o2ha~pM9@DilHh~ga`@n{4nEXufe*#Dz~@sg_)GgL`j_!( z_^_SBhutsWXr&qc%GLu;G%Dc}%M$oq(GQjk8Y}&e^t_CIGS>#53`OBT5+m@R(Hi)# zfEoV#pacGABlTXti)JvNHCe^mvh4L%H>I*{V1=^O|Js0OV+q=6g?9ZbT4H`Pmzh9{rwRkaU zT%7({xs-Bg%4McpA8wH-H!@FU%FS#Sc=NIkek*;%NBb?$GQ2ms2ERRh4Zm}955GI4 zhu`yN!28-=;QhHd@Ij3qeg9|>{lhE;{-{F(fAnL54>Z`|1L0Nh$+#Q-%(006+0z94 zg@eOi$dBNV(F%WQ?*vEcbnuaR1^lM%0V@`RMBk%4%%dMowZlgPA^7*mApA$D68_U~ zh5y=ah5ufO{jZ-{E0|AKNaEkJgyklgQkUPmK$++Efb$J*aDnX=T<|;qF3L?YQ?KaU z11>Hsl!%S&1$(1hjlC%x0+-CR<&d{2$1-Kro(U;=V}0o=$w&Lf!9?sEZ^v>}aq53w zttNKk5Na(Y=lf2^IQIvchVy`r={Ua%s**Xs3#$zD%#xcOPG%QVX08xZF2=(2wc@G1 GT>lG4153pK literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/Mendoza b/testdata/zoneinfo/America/Argentina/Mendoza new file mode 100644 index 0000000000000000000000000000000000000000..691c56978a033586e3302db2ef600e4b0ffd6366 GIT binary patch literal 708 zcma))-7AAp9LLYtnB`(cc}Y?TlhS6Um>%tdWH&5oS1v?KkqeZ!+_+LJEv2^RlKEL0^b9x-k-fkoLbE#MdFTNaqk62k- z3ad=Y)}Uuy&2wqiRmpR6v{m4_m3uDo+|GA_x331^ce2JMe!sJ^48I#&gWsFGf#1J< zgg+S3!TWc!;U%XFeCYLpk7{M~%M&5=ALl9XC!K2elY{|2&|rZNL{`CPQ*QX6eG&b^ zmudJ*JB7a#pTXfWGyIjU3mmm-;iEnU{I2N(D@MJ*zejoUp+A;kgO3Hm@E_4(_;|P) z{!=!?f9dUMS3^5*zyK0ejNgr+3 zjbZGtRwF5g6}b_bxB2^cp6@PhJWs#A&*%MopTqlD`-cW~*r9e5Bn7A4zV2&t{$QQOhd&(Z@OX zn1#Z}ybs`n+5mrHwt-V7Ief}3f?s9BU{R+O`2UFaZuHYdX83d@0soe=!@nmQ;XlF# z_|HHO{MUNsy}p+XU^=fC*xQm^Pp6lsyn1AXXO+_ju2wq1HO3ck&C@uzwz5#md$sXC zu$nxB)!t^XCYb=&E%jEg8ZnBexZf1iAO(M>FI?t_xbLv%;d{r;Oob#X`=47T{k5}Y zS&S$RstBPp94AsrBOxNE^fE3fp!7B=QSvh>=(1RenN7V`&!&Nmjwo8$sjWfr1Hu4G Av;Y7A literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/Salta b/testdata/zoneinfo/America/Argentina/Salta new file mode 100644 index 0000000000000000000000000000000000000000..58863e0436d16ef8ff8ba3d96b452086e4ae8ff5 GIT binary patch literal 690 zcma)&-7AAp9LLXN8?#nc6iFh}+N9QOCT~rkyA_WM zta%$V54%{aO;Rpa~iotD7_YW`pdmwe_{kaP&^gn-vfJ_@Q3ML_@l*J_~W}r z_>&0@{OMr{e9+?spRKHb&znN%ho)obUzEx4;XWmNIAemB+U)RBatC}h>w}ND*3pl= z%)v)p6h10GgX2aUe8SlePPM4vQ>!xgT{Q%jEjkDPANgq&{dA!dJ}t%JKT_lHpYeM5 zuaFJ?`=}fKXDj<&nPnT8&RZSqZAso{hsaZ{A70~G<=X@6bv|&l{S93GItDgW7MOX@ z5bFgS33YHbij81XG7ev})KkH~+vQ8#Z#Xp}+sE^>c|TJjG>8R tl!jtNNvRYhYD#Znf|k;Uq@d$xqV06KiIYvO*~+GljfH5M*{QWo^9#6+N67#H literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/San_Juan b/testdata/zoneinfo/America/Argentina/San_Juan new file mode 100644 index 0000000000000000000000000000000000000000..7eba33c1c5b13cbd9b7566f450d524a45cf8b65e GIT binary patch literal 717 zcma)&-z$Sr7{||SW0ta_ND}$ENv$!HU%lFelHIUUu3ShdMJ`Z6Zd|FAmQpl7Zk5-? z(2R{?C|ZrAT&&0)p?RC1$9cZ~0G`v+_k5nu^Ip8i+1cA;VSkoNY*14<|Nf*=tR;)i z0EAkBT=75MGMI=p}O3V!GM4t{q; z4>uPR@P}O*_``1#e7MO5AC9eok0;&mr;a7;pFU2( zpF24Gx%>c*8m;gb_HJ;zK?fiADBxFZA6T&%B>Era-h=%_h8;c;j>5mihvDC&)$ku7 zEBvRw9sX0$gj!3Z$?T#l%vGW*MO&D@Ufdch F^*=7fOT_>H literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/San_Luis b/testdata/zoneinfo/America/Argentina/San_Luis new file mode 100644 index 0000000000000000000000000000000000000000..0a81cbddfa2813041472b716baa91c35a8451379 GIT binary patch literal 717 zcma)&-7AAp9LLXW53_c$qP*tDG?ZGinZkOsi?Qs6UC5OSDW%8-N|YN{YQ=Iz8*-;i z-qtpZ#|)uqBzKD3Q8Z8UdYtq12k<-n`kv4E{LaNW?v9>r6Zx|gY=Sp0_up4+Y%G&? zE@d?^yRy!6Vaj9VxjE7*^4uys4)6??c)-ESe)v${Xq2CaHWuN-=~ej1%r*S>%{~0i zum*lNoDU!E@PPN`=D_=P66U3`1m+KlW%yX93O@E-2_J8?!pCn{z(?a=_!HMW=1-m` z;LlwY{ygvqPF7gpFYR66RD&8m<&(j$LN8c0=|uh>`N4hzSN!Fq>z*DX7^YbkAZh-YVFSyM50xtVn0vif`?-|Y{ zoR>R_qJ))IJ_Oh9RwBia580?RirhPfvcZn&Pd_->3T}EH6gfAqnZeGBc2SX`{O1x> ze6e9cDP#yLeodfs@01Wqr36t?8jlh+rB?}smeRXhg^uruw#DTpcGgu!GwW*BCZefl IJ6pBp2Vy!-;{X5v literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/Tucuman b/testdata/zoneinfo/America/Argentina/Tucuman new file mode 100644 index 0000000000000000000000000000000000000000..10556d5d856a0f33afd8da2b07a2005e7be80fb0 GIT binary patch literal 726 zcmWHE%1kq2AP5+NDnJ+nLI`WI2P$I&Vv+wqP&8-V5)i#;QojL+-c}vt0HU``o!kJT zcgXdF`8%!@faQ0I*B$_g@7lT;EWi85MzH*zY1hH>dv87g%kQh;0?Y5;EdiE45Y-Rn zADlZE%s*s(7_9zq-374vBQoE>@<$U`!171`X@TXBJDP*#k3U!s=AUSs0+v7JyAZ7Y z)VnsY{5jwMVEJSmlVELb4%E9u#E}Mbne;+ml%m3LE43_`91`=NX=9q%{|9eavfMLtPzSwI6 zh~`kqUjU+&r)&lDRRpGh`Ksohz X!5N5k4NQR87>JD+xNLwdJ7X>YQUg#g literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Argentina/Ushuaia b/testdata/zoneinfo/America/Argentina/Ushuaia new file mode 100644 index 0000000000000000000000000000000000000000..e0317502769271ad0c038493df2ad2b90ec402d4 GIT binary patch literal 708 zcma)&Pbh<79LJx{#*DI}ND|r7Cbc#*VS2U0O6I_doE)T-A_tU^iyYKSODP(5Rkj1> z@5V43v>Hh{tjLYfyv@Hop6Bc0HqX#7vE`ks1LgTiV3s~!|1?yr_aK(Ik39Avac!K*i0Uc7(hBNWqb~{lbk*57~%VmFd znq10=(m;X`N<$GMqcj{O3QDgcl59%vViFZUlk8@@gIL*A>Z{lo*%*kjo}C(u${*+O BOAY`4 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Aruba b/testdata/zoneinfo/America/Aruba new file mode 100644 index 0000000000000000000000000000000000000000..6158ca50eb2bac7d57c5b3db88726c36dcb17899 GIT binary patch literal 151 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$V!r=CFj-FD0z`kC@y3IZ>Hq(I9t;fs{~y@F f!1Dk9@dFH8KE5Fgx&|i31`LkDAq-qV!h{O|LyH|x literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Asuncion b/testdata/zoneinfo/America/Asuncion new file mode 100644 index 0000000000000000000000000000000000000000..f056047f058ee5983f113c9129cb7e3e87633de6 GIT binary patch literal 1085 zcmcK0-Aj{E90%~TshM-?)O1cWdtYgr&)k@^nLbO+Rde%YzO5HE-$87GM0GVH5+ZVx zWL=37bYbOEvb-oCyXl2$gIR$=Y)N0I&LubAEiz_xHPa=5%#;>5W&2S%^E~U(D`6k&GJn6odhGCPSpM)Y9Cvn= zWAE|TH9YGHE*)}3f3v`x*j553)eiB@$%kITn@lP=MZJRkRFzF&xiTgfxpLWqJndU6 za@D6v2=cA&3&^*%1d(sAiH3KSHo!X#X3X!h znBmWrKBNu&|d$p8O~5XDzvLU2cl;tPRn e6vg)eB4@WmZmVz-3q2anK#!it3h7;>m;D1;>)C<; literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Atikokan b/testdata/zoneinfo/America/Atikokan new file mode 100644 index 0000000000000000000000000000000000000000..c82871528308b02a45d17b3973c108c20e561c40 GIT binary patch literal 224 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I&Vu}AiQ1q@P1w_x=v9JL|&)@a407Reo5uN~| zPj~zSi(gXy0v5lN$oYYZk%^I+h4ugcRWb|=|NrmYz{v9d|LO${9AGvNm=pk!3?e?h ZAq>tgKpYIj;XoV^!r%&Ia{&ocE&%lkOIiQ` literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Atka b/testdata/zoneinfo/America/Atka new file mode 100644 index 0000000000000000000000000000000000000000..b1497bda631efdcb6635ffb6b0ee6f7da9e2a280 GIT binary patch literal 969 zcmb8sT}V@57zgloA38U!R&8r8EjOz%UGtnxm-gk^nrPAL*iJ>eFc*Db5NSdbO?olJ9< z&oAKe*9H7uQJ9seKTplU^B)x81tZg#w_eV{3p3;JqLbI)#XZBYZO>`gzBvs$T2k;5 zUpMUZ45*B+N^=x;>G#5}dQT1YU0-B)=}ag~uF41D>Ipl%?5+)7eq$D{Io>YuG3FjD zz@A+`xc2aOf%+@LmrF*ScM_}n_@qHs_9%rc^-Clg(P5W=cv4)2# z_1j_@xb5pFNvAg$^(CeM`b_4s|N9ubJ;Ru$CHK*JKxRfw>+jZ;;jBQ%irPjeb86aP yudW((<<_{uwk7!9&9|(uD6gY2g+)4e(ZLG~FGPV?{&*-53<&HqU9HuZUE5=#^)D+XvM}%u)GrY2{2zdLI5nU{HQmUT?v4Fkjzo8JKU- zPzmN6%KC!U8-*)?^&7Kgf#ppsLcsDSKMsQVW(x9PzS;QcC>=!E$=@D z%Ukv9faR@E{0Gb1 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Bahia_Banderas b/testdata/zoneinfo/America/Bahia_Banderas new file mode 100644 index 0000000000000000000000000000000000000000..882400bd33bdc23fc75b092a01ea935b02431715 GIT binary patch literal 700 zcmajXO(?@*90%~{KUg#iMu%3!HO+D{)mdUNoZvV zbnS&+XILJ879&GWi=FvYt%AccB^>@)jj;F2w^=)#C1n#HIZMTSmYZd{&IwnTVsK?a z8?013!c~byaCP<WSDxM}(tR(t$z z_R!oFgf-(XSX;UYw`fP;*3<=9m#>C(F`t}{5xqDM*5A*=?avapBW#8ZSLqSfXWTAi zK{^kkaMxlA+`WDW_c#jN?7=j32KTCyVcy_}%{lL|rNjmIkt?`Ab7zK*k^ZM+cp$n2 zTQ7X@;H?cF+CO4#WcZ{Bwyk;Lk*!?VJ~;}++gI1v6m+rT1G8RT2cz7^cS*pNfsf(S128?M=K_f4pUwd03zX!6`GRGSzuj!5Hf>F5bOW{6VeO}|NmdTz{v9d|M3G19RL5HJHg1~;~T=@=mNySAq=_( N#>NH=TtKD?7XY7HQF#CW literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Belem b/testdata/zoneinfo/America/Belem new file mode 100644 index 0000000000000000000000000000000000000000..e0d7653c64c1e3b3e546d4c5e7644865b237f128 GIT binary patch literal 394 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%Fl|*y35edo@A&{s|8-aZqIZ5YF#yrK z?v*Hj=vx-+!2DaUe}U;ck`Fh4#P95k1k2z3EeaODH~Su#fB)_*F#kb_F_`~l`hT$c zudH!k{HqU9HuZUE5=#^)D+XvM}%u)GrYi3LoIc;Ns4mwFf&{{MgcfRW|@|Em`m XIDC9V7<3JcfY_LU%LYi=8FK*u>AtJ- literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Belize b/testdata/zoneinfo/America/Belize new file mode 100644 index 0000000000000000000000000000000000000000..bfc19f4e587cadf6a2b05781860c21dccdf02961 GIT binary patch literal 1045 zcmb8u|4S2b7zgm(=31^8At91PEQwMo#v&_%EM^c=aMj2w$j${){ZMLDLV^7t1yN8+ zl>X4vlx1rS*z4lW0+dkJ@0=&e2(Yy@H*bl=YBf#iL+%! z#iGT?32G|y;wu(8woL9dl3aBqK_^YCb+<^fasOd~W>fWAxOwY&j{LYpf?ISf+`1j+s1!9cd=z~SLzzvZ8!jThwC}YxmV@E?*6N=C$SQKVLb`=1ao=H^;Q?aFFh;Z zzEgU*|KSuoP@sYbtKP#yo7M@m_loO)hnF+3cV`{!jYVOfzFnl8&*z2x%stp|v%zm7 z7vZ;ehdIiP>|GBBa+2lb!0QT@=4kF5j~Oh&o{&Bc3!cqzFy04`)$8C;U<~(+S0&(2 zu3mV83&7#pN3ghWhNF8UmDl0V`j2q*hz0(_bi$LyLU=NAAC6_0^0XHlyaIonH^K3y z3`v*$qy&vVK|jz zhf{$Cj`n6%ci>sq1pFs@0iLTJfagbU^ORetZ06|y&{#q|rso4oGpn=$&a&@dmCO5yEoedy!egs;9`9F?d2Fw5AdH`1cYb6_4{`VUZu>7Cy?hPP+%ATC# z0HWn8o`U)E3!D#t_zK2%!F|xB>&i|NmDnFtPyI2N*bfd_x#?4UB=Fw7UQR literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Bogota b/testdata/zoneinfo/America/Bogota new file mode 100644 index 0000000000000000000000000000000000000000..85b903333eb6325aa8343f6e9aee38447495303f GIT binary patch literal 179 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwf&V}dH^<}yh@KGI^|Hq*3RTWfAp)7dYpO)VS^J7IZI2&ULgR#bFRoze=g zJmgI!)2$$ksI+d1K~16v`f;&tvcP`a6c!N`C{1^IpYK25P4D5^_xU{MeP9$`q?DRJoyKECFG#4`zOnYJu&N^(B$-1@z zg;F1xl_|69(y+lh2^;Pe!A3C&8*h(cU-)?qUhpxF_oj)*e4DX_$sTyo!#JFKGlu)( zl^%F;-#K{6$pi4xu68(YZv$-JUJvI7obWQ|YS>Z|l4($26kw~?0b75SDKxizHp2E) z4qQ0?4PHJr1sBC%!Ntc5vA^Q%UASbo3YQ*y$>^-C`UJ1qaR)9lKY<-C1$JaUpm7RE zVCUpG?3$9`HIJ^t?l;{s4b~2whduY3;qud+uy>#m_I37(bkBb@AFgQVfGeA4;3`KW zyw3j)t~R*f8rwAAVyxzi2@a$u;M!+D;Pvkl@P<)Ap=M(u3UBKF4sRYj1J@mT4R7fk zlxeVa=P10b{S+K5zXXSZ`{B^{5y^+8l9^4%PdD#Z^bkw w{POQQs<1rtmZq@8B0*leBo=Pr72!oap9#FF=8ZdC;qiOC?y%42@p-($KY$7DK>z>% literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Buenos_Aires b/testdata/zoneinfo/America/Buenos_Aires new file mode 100644 index 0000000000000000000000000000000000000000..d6f999b8605c9f73653a16e2ddbd5a49b96c0f56 GIT binary patch literal 708 zcma)&O(?@*9LJwA%vxDdBx$mxO=`_%!ZhvRCA+X9CrU~waxf+2;-pquN?BvOI4E=Q z(l$1R;h@z>%3(!rgy!GO%j0>zE^a(ezrN4s|M@- z*%VN=MweFGd3xp@TAo`I9cG@}#iu@=JEacr&cz74zi=|lzxy}6@PX6@d~o3ke)swg zes5d~9|{z~hkG30eU}S-P#-}*G8IGrutb1A>J`HueQDsMO-A@=VjX-k73ro-j?Ke+k8AF%Hd_6<<3p8Qtkw+j4xo-(-^p-EKkdO z6|ruxnmmKmzB;fb5eHW;b}3km7=>fpuMKIC&Gy`%yqSh?NqfMp!9Im3BlDj-OZ;nR z;!NqOo)AhSF(Rfk8YU7-FJmGZrMC%@oS%uT-D)EiHdR_Zn`$;XB5h!&#%k#|fdER> literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Cambridge_Bay b/testdata/zoneinfo/America/Cambridge_Bay new file mode 100644 index 0000000000000000000000000000000000000000..1092f4b61a1b203f7feabb586b51085bb72602dc GIT binary patch literal 883 zcmbWwOGs2<6bJBcbezX^s+-U8m7|u^jN|pr`0k;WGil+_U^k*RBKSZzib3F_y1o{! zyyz;#aB3AnPP7ssmB@u=3tOe6(LN7`A<%=GTm!ndyViPKM!gZ^lJx#20<=`N3W|uDcnIZ)<`R9@fB# zw{O8o4neiP0NFT#!|8Mx2t znSitJ>u^r{7e;Zh_!oTX&O10a@e}NHYq0ZZ4UJ3af?cb#uzOR1^FF?YJ>NQ28sxtm zfTa)haKW=ySRN^Yy{-Ks?fD)j!G$#~a8dm}TzI1P|FYI zcc{5y{2fA_`-8o!D^qxWEh1>tT%Q_)D~7h=%F*X=RmWHOM*pZvgPV6FaCOsD*k3RV z2mB3i;O}QK+7K0OJl)R}V>TT-rEfB(>u<*mM*LfJeN1CE^rEg$MhpqmGduMxJztht m@PWdDA)fbm`W049$@>6Lfe%ah&=V|_e3I-5dcBfYl7;`ZnXHrm literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Campo_Grande b/testdata/zoneinfo/America/Campo_Grande new file mode 100644 index 0000000000000000000000000000000000000000..6855e4e9fe021cbbc392c76e1effef86dd53510c GIT binary patch literal 952 zcmcJ~-%C?r7zgloT0@o=K@eiI*$7*?d2|O|%k1dTWx3VrG^gvLA7F`6P*KuFSP}+a z1Sb8477=7uyAV<-c%eWBl2Y2ma6b^dPzE(99b0yKpYK25mCxZl51;q@-QcJlU7giz z-O-5#9U680p9DoMUz|cs%;WdBW!hug+J0fLdBe2F(~S!4iTFKLGA zJ@Q;?2lBszgJJqkW8|emyR>%^-W_srvdJEU%kJJ%$a}W@fX#tYPBt&xk!bIAFpfPt z2bY%_6>|BfH2M~%!It4?$oDUoaLNyKE66MOXXMt-Z^&(-w{T_iC@l32z*WW|`qgbV z&cxXDy~t(91%)hUrr{cs6|R}SiGJjsCp%eL`ND=b7tGnRCUtS@v z_x^*A3>CtPEeSUa=;6klYZ4RV^3A}m)dbw+InU|7DVamxy?q$D`@$^PpK6XP?vk)OJF20qO!u7@^Wxs!~nN1#NdtxDL5Fv!kL(}m%mDRx($0YZEA`!O`Dt1ZPK(!&I(#RDzi#< Nab#ww6YqN2@E`026-EF6 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Cancun b/testdata/zoneinfo/America/Cancun new file mode 100644 index 0000000000000000000000000000000000000000..3110cdfd6e6f4ccd889447657dff43560d5aaee0 GIT binary patch literal 538 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1}b9(Vv+wquyot41R$G1tm_$wVvs05a{)vfrk8;z z2BTt*0uXKN9s!~lOoCp4`KIdHA3%K5BMb>3+RW$-Slpal2E=8skbVJ{w|Mps%(wh~ z3e30q%F+N5u-Y?PnK&`40I9zfHng0J@w}OG;|Nqqs7+C)Q-?@Q-14J_N{QrOa0Hc79ZwP~Pa0r7d5Ieg7X&~kT Ha!k1Z4u)y) literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Caracas b/testdata/zoneinfo/America/Caracas new file mode 100644 index 0000000000000000000000000000000000000000..8dbe6ff74127e02577fdccd694af5a61580369e5 GIT binary patch literal 190 zcmWHE%1kq2AP5+NDnJ+nLI`VN1uA0!Vxj*)kl8Nf0HP<$>DYkiZ!_L_fXs1^o>Ty$ z!&O%nFfuVSG5`O6(1C#gNV+hv{QrMo2Ls3d|Hlt7@cH%t7CA(oou3ShdMJ`MUxpAddT1stsyH%SD zFWJ}_h6}AWNx4{&J3{j`ug5uGe*ow7d%oxM`~1$ub6mZH119q4lCTM0e7XL}P#r@(W&^eo78r`!YHNsYko7EeZbe|K{YK9t>n4=-H7?_J-) z?~kkCBcT%bXs-u+;P-JF!i*jd#X&8+HKnTV=|om%Tv EKU&60&j0`b literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Cayenne b/testdata/zoneinfo/America/Cayenne new file mode 100644 index 0000000000000000000000000000000000000000..cd49f0534438cc3bfa0e09bb5701552ce9a177cc GIT binary patch literal 151 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%F!77_1Q7lEu;~FtrvLxXePCet|Nr;_ e2A2Q-uU=r_@bL{{&^0gtVq*p_8z5Hq)DTNoJr|KGvH b!1Dk9&J7G4KE5Fg-azac9Kyf_Buu#g6^|V* literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Chicago b/testdata/zoneinfo/America/Chicago new file mode 100644 index 0000000000000000000000000000000000000000..b016880653929aa40dd5ac0e82e4094a9d787cdf GIT binary patch literal 1754 zcmb``YfzL`7{Kwv{UQjZBm$vHxgogR;v%kz!4Ba>SgseW(IHKuX<|#1ai+m_B26cw zG{@}1#anoxMK?ksVMQVaYbHU74c!*9l`v%$Qv}*=&;OI(^h4*J^FHVIT+aLH)vPF3 z8!zs=T$~+p%cZ&hh~C-e>D<8%=UVAzuavR;P_$0Qitp}fWvtvX5m$ZIi}#%^5;DL4 z-8(iJ52!n-A6#w1hZdWte-*Tc{_2EATx~Z{KQie{e8jvPA06I=k2MwJnyx(jb$Kq< z8`5!Y$y|K=i&Z-L-4prCwK5vsS%AOEOvQCCN8oQ2VYpu9flqqcaYN`8++elfMh|x( z?`dpn!QWrD;!}FFP3D_g+i`Q55gS)@~%Uh-)mflFPit@ONT$w%DlO0BmRBc+t^b667DO|;Qo?%_>Zh4 ze0k+G{O2;2P0m|0RYJxq$>DfF5sv?wBJiM>z=OB@@l|U-{=2&sUu$c{*PHva@}42R zMJJ=J;tak~)`D+tI*5l058zv?w&H(sw&2_I3-Fzo*YL=b@7d%%cLNsUQSW>_I+8DB zerzBMkN0HZf7_$5{bUq&RQucH|0F*3C%9}K!mhJ2I~3R_@C5d$*)Q9Luk8~&!Lp0GpQ+X+^Zv&5cw)m&9B_E2OpCz1Mfjm@Mfl;3 zOYx+FrFe2~3J%Ij!H>)d!BZkbaPW*|tvpQi9>*cBQ*p@6V4X~a_Ko4NbEEjt)0c4g z@r!s`RWqKxAwaf^$2M2t8B1>9h}TcqVA zC!FjRhEqZZZ1Rv|wc|Ns9XPekg6H-g!z%r_PA29xeu$qgGvoQ6YjIkk5icm+p_P5l z z>)xjU%H6kkq_?}SoxE?%g?(BB?E9H~rSB*A3{x=uVBi2{ip5UBQmdcgwAd0I*`U91 zQlnesqQ<4Ym8yAV%vgiBfsFf1Q%S-Zee@qhLbMrcgJwU`!w8mvI;j{ z_QB1YM>?8o*(--zr&i#$`6Rf#*9muw$u!0sRtMbKn#d%T;JEclT&M{wm zDRU!I;k>waBFlTw!ug+9aKT%QpN7KF8C(?9z?OpmTs-#-mn==erNbw%b$ZE57iA4W zxV&!?wxut?6}B$8GI|WQCtG3r$GlEFW7X;;xcYJwuDJ_`YnRutUw7e#(!OB-O?8rWb9rt=26Xi^}rC`pZD7fwC2zIT#!0k61 zuzUI(?l_!PP!o={eqmnpZ z)-%R=z|Yj2Z?3XP`bt{P_k)tIPF9%QqOfw&vQ4CDjkw4a(94-dvoS+2n@mQNF+=kU D(_5Nj literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Coral_Harbour b/testdata/zoneinfo/America/Coral_Harbour new file mode 100644 index 0000000000000000000000000000000000000000..c82871528308b02a45d17b3973c108c20e561c40 GIT binary patch literal 224 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I&Vu}AiQ1q@P1w_x=v9JL|&)@a407Reo5uN~| zPj~zSi(gXy0v5lN$oYYZk%^I+h4ugcRWb|=|NrmYz{v9d|LO${9AGvNm=pk!3?e?h ZAq>tgKpYIj;XoV^!r%&Ia{&ocE&%lkOIiQ` literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Cordoba b/testdata/zoneinfo/America/Cordoba new file mode 100644 index 0000000000000000000000000000000000000000..35a52e53d123b5ef5d293b3af19046630f02bb66 GIT binary patch literal 708 zcma)&-7AAp9LLXIFiTlcB#CUTO=`_%^47EqFWC(%+7%_G6uB@ZhCZpmC= zZDV5?F7(tUDHkhpN76ja>v7I^f54p6@A>{d=kq%k&v7`128|@+lCTM0d^s{-X<}p9 ztO_YxW6RrKo*N5p1JC`*E-TN2l1rTX%G_XId=%baG!^FFzqbh=NbSN07jNMY?;hcg zCY11@KrwvS=>{LKtbk7%BAAa%3z$DG72(hN0YPeo(!A4wPdXRH?f zD`JNK4tB%;Y^C4pci9Z4^Cl~MTavTc;pM4NkF4>m^z4DvDi2s=c>`-+$HCf)d;_1; z3cX+*p;pd1Z#`I_h{0Da^_25-i+GOvbs;^n)s>sh`x*GQ&kb;Uu)ka)mHl&P$h(HLwa!R9NqM-CfkmOPNkdUZ&Px3nL4q{_fZ7{K_VPz!BM%FdgDE|PnyG!l> literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Costa_Rica b/testdata/zoneinfo/America/Costa_Rica new file mode 100644 index 0000000000000000000000000000000000000000..08f0128ee681d8f7e1df186d93514f3f4cff2830 GIT binary patch literal 232 zcmWHE%1kq2AP5+NDnJ+nLI`W&0xDwxV!{7FklC)~3!)dl5c37;7c}!s0Mpy^0zkB| zm^PR%JUsx+SD*d>%-6`S$+u2*F1Fd0wXgM6#oCe(U^e&OtSp{zjFg4=l}n! a7clVp_=Ye9djSb&7a$G}Vc-H1W?TTV6)k)K literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Coyhaique b/testdata/zoneinfo/America/Coyhaique new file mode 100644 index 0000000000000000000000000000000000000000..26354e89460e7c9e585d62ab477cd69a5559b554 GIT binary patch literal 1362 zcmciASx8h-7zgk(i%TxK=9cDYX_i@|qdA(()igENa?GXCOvQ~z6Vr!;N?NRkEHNT1 z#E38ny=tYB;w36urgEUcq$DUaib!m;O>gJ?rDxyzF6Vsw?*BV?7&w}ovf==;Xi4Y< zTdXvTA2~|LOz5%~X_Xy!w`RRj85hfXi}r0A>#cRK@3P)T_6e->d9`qNZ8*o=6GcW@ z@6D=2e%&(==Wc{tMt)OPg1paV40+#V3-bOsEj%!yfOW2WF|XV64)f0(-@pb{2IdSk zP4JvP41K=o7telI)IApHe;}mlCC{25gfF&~6Y zUQNTM^LFr(VLfa%@eMX_|D>eHh{eztY}qghFTFSbTb1^}*2fG29V0gJ&9H58A8hAS z1KV#o4==N6;@O;o_W{^prW$rK&V`-yJ7DLjNZ6%Y4KIJHZQ6YsrLw>_6Qzqe6&J(bgnh1oJ*Uw?t`|}TY^>`cXGkXVKb9;zqb8E-0 zz`mDS;dOltuwVUQc>TF@ctb%UtUPp_BeeXZW8r}OGFTNpreyB}xkNa~JOO4jNK_X*1w0NVXm&6XYpr z^#Y-ldZ80}TJ$))t?o3u-S<1k@^oz#tTBHMX9iEL{_kTfii4Geh~m&KA{WI0o|uZ_h(IjZE}^?&RAS9` aVx5$%A?bAaDTC+=q)SE2!ss5MGW!eRxNk`S literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Creston b/testdata/zoneinfo/America/Creston new file mode 100644 index 0000000000000000000000000000000000000000..9d69a0ab819e936a1f4f8029e111a7b960db8b8f GIT binary patch literal 158 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#p8r4)XIrobM9;qFT>zrz{j_FaWMcgPf6@^K hhX4QPPGDg9|G&S1fy2i)guypBgdqTkxqu9FE&!V~BHsW2 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Cuiaba b/testdata/zoneinfo/America/Cuiaba new file mode 100644 index 0000000000000000000000000000000000000000..c09a87558d53b031fca84a4c92165b01b37da360 GIT binary patch literal 934 zcmcJ~-Ahwp90%}cW?_HzCj zr}xX#UC1LDBi=_x6L2i@9*!$@@ShiX=>Of_1F!RbVUzzQ@{(VNIOWH?W#py&Gjen1cjRS(cW`;*1S|~>!xj2=^ebD+ zI1^*h4j{MMuF7O`#04{qVU!!r*%Hezst>k95S#53qS_xq7MC*LAJoem;zdj1eT6Mh1p9ejg+ z^UN*Sb$JMOzw*N8ngZybAG#?sF&={x`Gsqj;ET)zD~@Vd`PqoR*O(7`L&soWRtENs z>)_Uv2;BB40k=ncITO=y{hO4f*`Y^OzxFVus*CfQY*n4*ET`F}FtcP4$I5gy;Hq)zu?!6V{~y@F f!1Dk9@dFH8KE5Fgx&|i31`LkDAq-qV!h{O|LRTG6 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Danmarkshavn b/testdata/zoneinfo/America/Danmarkshavn new file mode 100644 index 0000000000000000000000000000000000000000..8718efcce25cd28ff9fa0f48bba0a2a7e6be4ed0 GIT binary patch literal 447 zcmWHE%1kq2AP5+NDnJ+nLI`V70xDwxVuAlaFuTDMq>Vw?wg0Mk;3CxU6|J$nT}`eoLv1Jkl|=7VXuo(W)DzNQgO zE94Y`X~mdiFsJhA`+F7z42pgFBGT1tbi(02vZWm;e9( literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Dawson b/testdata/zoneinfo/America/Dawson new file mode 100644 index 0000000000000000000000000000000000000000..07e4c5f4ac3852571b17cb33fe565a5ea2c49f0a GIT binary patch literal 1029 zcmb``-AmJ96bJBUOI;3yLB7nj*-xj6OCq?dJ5GC_ih zawO$NwSG!B(T%cje2On~;L)*UgnRmY1)S9X?Bh-z zun2tqGKHgjE>?`G`0p!fzeM?5)pK0nGcVYIeZI>N7u4I}LSr4QF7+W_l&yv}ax1J^ zu!xLm^@l=On=F8JkAK6(6N~Vg(HU3>R|ynnB?FJ((m*b(?|rM{`!efSxV-ftyf*(8 zY^aREhV;BhF=kXoVB_oyxbpKsxGFILuS@kud9FG(4A;c>!>0aIaP4q2y#DYNfnv;j zq72^PJPBKTS+La*fa}bkV4K1Y+qIc0ddBQ?8o2)N9Nh4132vNu4mXXfMT)VFQ+MG_ zLx14S*Dt|aj=h7o4&I6KTyuK@-qw8)c9=xC#c>pF`H>PR#+=m`@ZOo4gk8BuU{`zu zZk=y~x8I116ld-?y?F0Aa}{p8?}pn$r(y548hA%j5Z)P9!9Hyx?C)5B{YyGHV0{e- zJ~jx9YIpH>73Nbd989O+&f95t&+H@|8hj6TB}U-A-A~|svCucUjJ_2a@=SS_;(vcD z=`ZAFOp=BovJ6QY=wq~@dk#*OB;Ab4^7x$<;jZH+D{*`LEa;&2QSYMma?`>~3olI% JO(h*R36>8b2{hOQ;)gcYRO<>hrn-8(J+U9lE<$_ z@k)^SXeemUr5s;gu~SYsbQ0y3EfIDmzqgW|O(|N+z3LZ{a$oep2id#uA=`#sx+U1< znS+l)JLq$~Cc!7}Mfh}PR-!)c)e-p2HVAvhJK%F`D}2#a2Va&{!dDIX@O5eyd}FK? zsn2a(g_hE*&x5_MnXoT93HCX4@ZC)azF+u)A2vMjU|5p4#E&XrAiJ7uKsEGYyITiC{kFCT$_~lcinouj~eRN)v*ol1BtKpZeGUPrs^%XP$WA z^j$YBUo)`JBjl1^U`cT<%@R=_oq;nB>O^K$us~utvvyi!IjcGatLEg)8Y;y8vQxL= zqFpjvy#EY&1)-G5r>Wi8}n}UAzZg-}wcu>OKiqA9w+82zQIDv2jNX-qd&;_S!DMKJPx*_v4YE zRQ!1|RR7Aqt^bl`xu=WJ-}y#Fp`x`!G^lyJh3)z%dAeT N-QssRtPZQ4`wbnj4)_27 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Detroit b/testdata/zoneinfo/America/Detroit new file mode 100644 index 0000000000000000000000000000000000000000..6eb3ac46ec56985b52488ae6a8d80247c2adcd4a GIT binary patch literal 899 zcmb`_%TE(g6bA6qf`HSa6+sJ#k0Lfx>d=SfEud|~LmP<>G3sVCKvOnOG$C<=8o@`R zQ3D%dLPXGDTp+k23c*Lv#6(3F;3GP+FvN&X#FbUYdq4gFHlE43XMXp7cUB`Gj5Ygc z$uhA7Z(j1!SL#_TiM8Ee)iLTg#AkPT7xDT0ysq;3I``+|RN@-0`0H?K3*xw{^bh;CEG|a-eErS}d+8lTS=ha<>w`AOc zov!1s^Y3Go=R~0a7C+pCU0;ge{IPSedrDSVjJEc~VCh~VT+p@)_H^1|Z#1g&obT8# z*k4@>Z`=DG4mk7SLf;r%l$;6|XTQ~mRq^NVa7p|DTskocm%ZzO%Ll)yJh%P+DY)YD zE4cF75xDB;FubGvq{3pfb59o>Y&;By3R>ZCC8=oJZ_0zH^-t z4P)dkr5MK3ag!CR4Qu-Dh)ltKGKG2XXI;-aB$L240_?>d@k>6*Ih&Jn`j6jWEiiOmqpqmdH1$No29t?|!3JMIT@BE+kP3RlWobx;1IWP|+A82au zu{n={Pf*a2=U%DhW2rncbbihz#wRIv-5pdZUyGR(%G#9+uoiEFyU%@wdm?F!?t7b` zz13<-HQ2m!LJsYi`QkL|FY&2=3d#~(&sZ{UA9U& zweqh*IjwvKHhB`T+5Qf;h$FDThGF4*H#~nb3R@?J`8Hzdvo33$V!Z}7%9F?iFEpi;3p)(LMp{}tZaaSAR!JPvP*bSTu= zzHbQLQGWss7F~ox!Gmz<=R+~Yko3$mCL#IaKWbgStTFzZ-qH+4UGG$x8MPH}ac@{= g;UJG{9{YJz%1q!W;Z1kgFZm>oJM8sJUdbc;1G${^$p8QV literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Eirunepe b/testdata/zoneinfo/America/Eirunepe new file mode 100644 index 0000000000000000000000000000000000000000..7da4b98fe3c70a1aecae8e0f4264324eaf9e1fb6 GIT binary patch literal 436 zcmWHE%1kq2AP5+NDnJ+nLI`V71S(?zVxIp%Fl|*w1Bl+ipT+>D|Hd2u(K|l|1c2yW z_a-=i=vx-2!2DZp#K80&$-fss;&*nIg5~f2HUx{`oBa#SzkhcdnExQeAI$$ULmI69 zD{B>)|Ls5nSpGYo)d7$>KLS0#{2#|3g5`g4y#uTNwNeBu|ND&+SpHA<%mYBTGsvD? z6#$~;Dn1_o(eeudFMwzToA$r~B=3<>59SBevm9Vz w#0#03{{P?Cz`*eT|M3HiEWn`Iz`y}wGqCvhhA`+Fm;kXU1D6euv@_)b0F&sY)e9Ine0)O~oLzu8ID~- zy9J&qeGgBcYe#=&K0;>>-9>*VTt)wcT|{U7a?v@jI~;q@yv=@i!K?^gn7bfi=ZnMX z@KWb7`0vZz@N%;nHr)5-*zZWLOGGTZOO`PItOab8?WJYs#z(|DR+A(lY#MG33*@7) zpd=DD=ib8R4_}DrI1x_P!xnvYxNq6@hGXYeZDp|a(>mCux>m%_xf^Bhnqn<%o0kLI zWt@WTQ}@CS(Hht>Bp7y*1i{Yk$y!3!T61UEg&zpJOb6)Lxof`@?51~w*R{{X>l^0a z4Y#{tQLc}Oj+2dr&tdlzE7;@2XO5kF22Q}6VxGa99X`Nf?#L?SGJCB5%p z?~$XhPiq4#{g|(1bG}s-u&nVg?3aHAmRCf;isR)XI!2T^p0L0AG#rp@3I~c);2`BN z94t`5DmN33K1NhSE^x@=5WJ;h3EtZM3f@-ltfONjw50~#Ub+B>-7JB3WcI+}Mb%n1 z7m?5kN2Xndqx^L6&Zv{{E}QeP+A{%G&)pIcx}uF0aCB!O95Y}C$A;Dv@c2Bw5#QK^ zUjEmIZ!na{5n?b@YKgJIP+CCD*ms^KuJoTnzuU*fYe;;uh9t5bMfX0s6E#Fg4^;F( T8t*St%H+~`g+iu~$%X#_Z)Mmm literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Fort_Nelson b/testdata/zoneinfo/America/Fort_Nelson new file mode 100644 index 0000000000000000000000000000000000000000..2a49c6c50f4c21765232712d18a6cbbeedafc441 GIT binary patch literal 1448 zcmd7R`%jH=90&04Io(giBb_>q@K8FPQqle5E;~y1PLWw;WHnYqu~{-1x%I@{MtS5H zjdj^smZes|G)AnNbSgh^DGxv*NQCPuaOHZzsgs_EsohrPd5mxK9*h&kMDU1|B5Pse{VPkPk83RlP)EgpPHWnPn+k#)01a; zw&zcO3Ov((0RH=88$4UBfenvbIrcrtZ8gu5{^KzKJ6=tm_NmdC$t>`K4t%t8;e>;RX2uY;!Ub zUYL3mwoQzO<)K>GF3=ygSNp+=6>$QgvB*LJE2X}$a@0p;^~JsRutSR-yrf|YURpT` zFMH4l^I2{@Z70jm)WRzgtYOEr4vy8Ge1E_z!=A&=@@81&S`4dZheg^()UsSy-TfAJ z9oPrE)m6f)T5|-}=U#jr_R#HxJ#&u3tFLc{*BrdY(>CIj=>&Ugj=?^0rm(Ln0rvCi zhyBe0-~a~`j*gLlJ|!IZrwuMgu>kFpg4R^1=8`HbsO?jmP z>)RYv2XEPb2@dfT;jJNu;jLq>JZ&Qy_luaIQpgs9J4kNj?LoWIEP?Z8$SwbXO@UkiPXrLUjN5qVlZ5uBE(=Q r5+ue3LqRSv$Ga77`coDO#5O!aOQJ*QiKAx+J<(bcLEmNc@|XPs-b?Lq literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Fort_Wayne b/testdata/zoneinfo/America/Fort_Wayne new file mode 100644 index 0000000000000000000000000000000000000000..6b08d15bdaba6cf94dcb2681887154f4d265d8ba GIT binary patch literal 531 zcmWHE%1kq2AP5+NDnJ+nLI`V711e(&VwwLy5Xby)0f?TrOs4@v&)@a407Nfn;{)>- z&bkfep9)t3^H1Gy2lG#N`~&kZDSrX;FC}t*0O`A2`k4VlUvYR1=3foH3g%x^I1A=q zH{A~A-(Xk|=HC>Z3FhB?FcHkZ^>1qfNdN5v#bExOd(*-EyDKLYfW+_Zs|54!cNT&9 z59URK`42Ng!2CybwqX8aPctz8Nt`^G|KgL_2ax_(K%ax?e>-Hr{Qt}UKLCaW1H<%x zA3zji`@;ty+C{&t07SdGI46MV&nrGKF@hm83zPxjLP%C7RyGLy|9`y|$c~*G7+L=R zU%h~V1I*?DlL8=;LFE7c;|CZee0)O~oLzu87>L7xI3R?<707l4ig5uMra*>{ud$wy Po`H_9p`o6ko&gsCE#d-; literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Fortaleza b/testdata/zoneinfo/America/Fortaleza new file mode 100644 index 0000000000000000000000000000000000000000..092e40d70122f764fd2630957be1d3e32858f6f5 GIT binary patch literal 484 zcmWHE%1kq2AP5+NDnJ+nLI`V72P$I*VxIp%Fl|+~1c=_j@A&{s|8-aZqIZ5YF#yrK z?v*Hj=vx-+!2DaUe}U;ck`Fh4#P95k1k2z3EeaODH~Su#fB)_*F#kb_F_`~l`hT$c zudH!k{HqU9HuZUE5=#^)D+XvM}%u)GrY2{2zdLI5nU{HQ4AyV?$qUT4KJgzcZK`~3rKJd<= zpagGT^5#$KC>Bedq*L8q8F2F%8f#Pdd_J)t@%jG#S2&XO_ZoLZ`JwWuh03sx2E7vh zpHca#@EI#b;JETRINtFRHl>fkTg^SNz#hWFubc2T?FO9i<$=nm62k#_`}lQu$BPz? z@6Aun!aF+};9af7@a|v{oD@iflWQ#S9`8E5H)jprmuZn0)qc|woMKpmQ&v_LzPCh| z;MBQAIBj|wJ}?r75BB!K=`FuCinEM6ZE)t9PjJ?iUX|~&J+I+Ir|!aslOMy@+>5Yv z{gpy7W)rGm+u|cQ_nQqqGSv#(KUPURcQkY!7Dsd7yj!KPqg#NTmjW8an5+3aoL^l6 zyH9_BJ=Qe1z%>jP#_6!vGON-v=3S1$MgIoj;C^RhvyAEbXVqY&dzhJU lPrzxe^~C1_vec)(P8&HouX582pb*}&*=aF literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Godthab b/testdata/zoneinfo/America/Godthab new file mode 100644 index 0000000000000000000000000000000000000000..310774ea4fdd1798782a41f905d16e3548cd191e GIT binary patch literal 965 zcmcJ{-Ahw(9LMpq=17JYEAyc?GhJ&woXxWxpWCLk+^BYZJlT9$^I=NC@IoZIFf@`b zV#oRx1{66~wyy|!O{a)t{zu%W{y4l52 zhc20PgKV<+!=E%t*W#p|AWCaw;0Ad{C31Z=#1rgaftaNI1(Op$!xZ^q%$+wdHTn{s zTpfp}-amxu=@}JyubB+Nw9zqmIv~LGzPs>@zXxWtbihm(54Dy`c$O}NI*lHlOGt%! zgzfW{N0MRAhodkz{0GucH=!Z8291OBFt2wSGQJnk5C-~I78x^XWH z-Slb~-5gP(TgHz;Pk0Mn@85ym;1X>0Mqt~Wp8}cJUiKQ@;aNcY(udKV){r1O@?So= zTojiFC`uF~D^#2)M!(A9$w|e#IG!>vthCLP(juKUvvitlG{+hXj7*-vL~|wvzl`z# D+K#Hs literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Goose_Bay b/testdata/zoneinfo/America/Goose_Bay new file mode 100644 index 0000000000000000000000000000000000000000..e2cc3eefc273c206ab9d88f94660f587932991fc GIT binary patch literal 1580 zcmb8veN4=890%~EDvFo zG4xl+<}jz|;h5QVDVI`LktFIQ!qxeH-hZ|E!}|XAz4zz!`F_5?ziz+u4Ou%Qxc@Gm zP0*&5{{Jf%*_e=RUkh8CqnFL4EK%p3p)7satfJJED6%Q5)M5!`b?(3|%BL6I;Afc) za81rITpLvh*KKuC(_FpBIanJz1V6XB8%X^ZK27k8t|Is)cOTZz`F?=T^~xSCWn;d~ zK>0e!I+3zzw?Et*^Z|a8D1Z(2^>9l-AKdb(9By^7%b!!F8m%W@Tr9DozKHU?i?%}JPJ=X=D-duMLLcx z$Er+t%7Y`YQ~6;d^_`0|V3&gRuxsuT*expxo|@?mPm_DW(jtKa5l|_mc+oKN(VSB&le6q z`xO@NiZ;_+#6carAYnGVaP?g{GJuB{MHIn{ZM$KK*X@3~C+Vq$qyC(Qm(<;am$n{) zmsQlLXfFEEI(T{E4LIhq1diRG4@*z2&8E4y)IIQu9gAUESTY+^Z^c{NjC*V+jl=kZe`|r=1Rnbd z%(C~|v9I4oj&D~%X6IyHuscgQAbGKN!jl6fVBArWF p!?uj=G`82Lb5d4ISx+isg^*PXStmrXKolVg4^fE4BC#l3_!o8Gf8788 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Grand_Turk b/testdata/zoneinfo/America/Grand_Turk new file mode 100644 index 0000000000000000000000000000000000000000..9d90e745b04fae51493817b5ba1db5015a39bfda GIT binary patch literal 853 zcmb`;+e?#S90%}cbD~V8ELWZ~orm$x`R-uzP*zSi=G9@e-7_*!K$d|gO_ z)3t)1)k#KT6wXv8!I}TmLHl$2GKLQtN#$lbl3)Y>k26<0V`(WYVGpzqr4i_&C!iKQyXEjnX7J$XsGT8XW z4Vyygu(_in#(S2R|KU=n3%=F74_kG`aG7NZE>B2-E3$SYgiXcKU%2w*8+?0x8@{tQ z23Jk~3G&|EuYK^nw_EW2_w8`?iy7E9(CcS4QsW(kYac&??ZzJ1VXuW9#}hGDBhHex z2r@hjyHaehYxX%@AI*o|ABJ%6*{SyPzVx~iZkX4?-iH$0_)Y~kRT<&t?jyJ*I~A6F z-(mUW7;gO(jwzIJ7xby(C|ztMgwh2iQBnG3iX>9Hv8+huFS+cIWa4J)XklxYiH)V2 U!OCEeN=1ukGDv2#XckTCGwa!~+yDRo literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Grenada b/testdata/zoneinfo/America/Grenada new file mode 100644 index 0000000000000000000000000000000000000000..a58e63a44f37936348cd9f49990b6d39dad32fab GIT binary patch literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@ry|c0;s5`uRTvol|KGWRkp;+Jz`)_-8^Yl1 O0>r@~3|v6Mj0*q+L?#pf literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Guayaquil b/testdata/zoneinfo/America/Guayaquil new file mode 100644 index 0000000000000000000000000000000000000000..381ae6c463260d85ce92d6585b6420fed0c096dd GIT binary patch literal 179 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwf&V~|*{&7=qPHz^k^t$~7W;DnOcy?LU}R=u x{{Mfg1_J|7K7)bf|Nr9$7&-p`-?@Q-$HzB>ArOdl4NQR8l!40zNZOfl0RUr$BfbCt literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Guyana b/testdata/zoneinfo/America/Guyana new file mode 100644 index 0000000000000000000000000000000000000000..bcc66881c17cebf8767b7a147b1fcf7ab29bbd9f GIT binary patch literal 181 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwq5nWINtVAIM9;Wc?En;G;Hqcc1EMvrIvikR zVrKmR|70Zt!~g%s4=}L&|9{$rf#d)Gs}~sfe0)O~bPY^^*x1ArL^5#M0Qq(%TmZ0G BBpd($ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Halifax b/testdata/zoneinfo/America/Halifax new file mode 100644 index 0000000000000000000000000000000000000000..9fa850a7d4c36dea84149bc0ea2fcd3581d61a8c GIT binary patch literal 1672 zcmb8uYfw~W9LMpqinMJecma&XKqUdgWf#E^G0-5!3wlNtjT-Ar(+!)Hn8>UKb;^>N zQX4A^6R+W|a5vB(0vE50c3D6P3YUX6KxDm~DXg)sn+zKjO<-6}TzP ziGPYO!p+il+!F96Zc+1btLF_x>|Z(jiY(Govl6!zF2`zdGH%aFz*h?<<7*3oaYuTn zD)u_ZO>~RwiZI|VZ$Iw#y@tE%Tk-E5XYqAs4fbv=QN&*F`a)UcjWwI`&8J?(e=l8y z|4Gik|HdrFw<2@c@AI?Ze&ZtCe`}#Co^!iv1|DdR#)EZ!c&K6w)((2z;{PD+=ut%& z-fhGq);8dgxjnL|`zU`YB1g#$*f*sf-(@Yw#;`JcxBti3Bz=TUJ+I+=)U|kY%ZF}B zKli$_@tDe2vESi*Rn+}IeGHE+T!F`}OT^=IX5$IjAvj=x83!f|;h@MtJaLLymh^L< zu?+_s263==KoNCwdm9d^_uxsjwfKIg3y1FAkHhkNRefBVym1qrl647BUA5OO>f!Mx z@B<6q!qWmi!4cD+#Suft6@5&KGNt1v&kj7jI|@Hovkpf$J}Qg38O2XvOIak2DVU3` z+fCT^e735ONwIm?@yzr&IBwYwI6h($o)zoB5BX|1!TgIlOy zUn6~nxiH)>_}_U=JEQ+}O}p$i_-NXBmt^GgXx{x7XV|5Asrt>-?+X3OcFCk8PA^7h S%(TQ>tkD@Zo5g0an*IaqsOC)o literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Havana b/testdata/zoneinfo/America/Havana new file mode 100644 index 0000000000000000000000000000000000000000..e06629d36841463326ff3350bc2f94d0417c3cdd GIT binary patch literal 1117 zcmciB?@Lor9LMpqO--himAY(MD@|AFbhCvue_Zg_N;j`;5NU!$Ej6TwU{M$m*yb{^ zRfmF~ph?5I`YrAJSR9`zG9PUo{TTJ(@mE)d5(KfjZsf3ZTITc*bIdXP$RR zwC>M7iSz#cdidQ$5@G;7Ch6?vKcw0^J`it%Rdt2loGjEbx-I3;Ta3 z2jOK;E4(tsVA&g%_-|mWcOgJgcqS#P(mesI&MpY#xRx&>HQt;mQ4@sM@S1e1Ku**R zz=@Gd5?ReWu=+>4Ku(%(gOfjYN#wOsExc~L6<$AbA5Q7)6KH=!!?yr+qsu2zHyQnK zYV}<>t?4S9o)deX#&QDQoY0K@3~e=>u~-goS<=JWx5os=$JUS<&KxR(w_S9Iw7$JZ z2kRQm@QyP|cxOce&S%-b!r56x@Gip?oRfAP&ebePjE~$EFYebzX0g8eb2q$aZWP}8 z;xwG+y94Lnv%!Ym3vj{Z0=UrK2pdn;qNXDyXi-f*x=%PN((}xjAJF}#;aHb_Xt6f- z-ijB40XlbJ=@EKx>M3do-9$@lua1`<$@gYC@|jWACNv=MA_fTZ3~o zp9axGs%WfFMC>09hv3@&4z$i6!Mg2QH)?-rN9*15sCfIgs8A{Y(}({*ry1i{iN(qC u8%dEU%j3f=xz6TfRz52#`E)p$nqSNudA1^h$xv8Om}fH@4MzUWsQw4Ss79v% literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Hermosillo b/testdata/zoneinfo/America/Hermosillo new file mode 100644 index 0000000000000000000000000000000000000000..ba7b14760d47d1e10241e78e976f0093ada6551b GIT binary patch literal 258 zcmWHE%1kq2AP5+NDnJ+nLI`W&1uA0!VuAlauyost0ua6aqc)h{mKK%(;%|4f1@m|C zn1T5_{- z&bkfep9)t3^H1Gy2lG#N`~&kZDSrX;FC}t*0O`A2`k4VlUvYR1=3foH3g%x^I1A=q zH{A~A-(Xk|=HC>Z3FhB?FcHkZ^>1qfNdN5v#bExOd(*-EyDKLYfW+_Zs|54!cNT&9 z59URK`42Ng!2CybwqX8aPctz8Nt`^G|KgL_2ax_(K%ax?e>-Hr{Qt}UKLCaW1H<%x zA3zji`@;ty+C{&t07SdGI46MV&nrGKF@hm83zPxjLP%C7RyGLy|9`y|$c~*G7+L=R zU%h~V1I*?DlL8=;LFE7c;|CZee0)O~oLzu87>L7xI3R?<707l4ig5uMra*>{ud$wy Po`H_9p`o6ko&gsCE#d-; literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Indiana/Knox b/testdata/zoneinfo/America/Indiana/Knox new file mode 100644 index 0000000000000000000000000000000000000000..b187d5f8c75685af67913e9360b50ecad19fe6ad GIT binary patch literal 1016 zcmajdUr5tY6bJCTf6mQKS2>%jrfD_Iu{Og$fkDtD77dK1QjsA+v7UaF8NS4P$$W^) zg0cs<5kwND1!4xJl|&RlGc=cf+N^9?x}WBQscqf!?bY!9IQN{-`JH=Ten0mi&+!7b z;*#(Q3R>=!j~wA+NjwY*zN%$$Kjqdt7B6Mrlivbm|AkaIaBCQTdod38=gz_XH7b$j z1}X*^<-zQC@W;X~c!;&bA$k=U^W^ z^{Nk^?uiI=Ppm!cr7Zeh!ZVj&z;j0%;f47Vm|u)KaeisY3IBPW562(p!->0Ek-iVR zsYQ}B#$f5W7%V%b5vY*YqiSA}ji(Y$KUf0moh5L_4kNra&j=fGiUle% zlb2wlG!r(?8obn47g>bY2N&QC&qra?!x12 z58lu()!iYHCldGkEE%;1yN-62zR%@myB$0Z@TlTZ?q+4YR`W&?e_?TLw-#7!7MI;_ IwOeiKzt^*oeE- z&bkfepYHev=3i3&0_I;zTJRM$DU?j{*yR)F#oBh1epKK z-G%|A@41i(SpN%kIWYglCowSp70_iM`BxWzfcdYVJp%LJY`g{Lzdd#Y%zrm=519Xc z{euRO`hPoQ!2JKq|33iwje%kMzYidavHjr#5Y1Hn0L*7D_?H0Uvn2d20MV=g4-!B$ zo5OuDpWWaPn9trT3FdPOY=Y2hr+fgZ- z&bkfepYHev=3i3&0_I;zI8DFGIL=5E6P;y)KM0n5Komjm-(d=dlm zU$HZQ`L8bi0P|lzdj#gc*?0@ge|zi*nE!6#9x(s?`Uedl^FGW!TmYg!_8$WCKh-Y< z^FQY=0rS7aw}bg#{oBC&Z}ypB{&)QhF#i`v`UjByUq8|rK=khyo?!l;8=heP-xJzk z{=XgCVE+FVydOZ}$uNT#Ofj~<2lJWA--G$gg**iy21_D$1Bhk~cn9XQIlKk)*$pm$ z`Ru*wU_Ph7CNQ6K?P8E}2CffNz- z&bkfepYHev=3i3&0_I;zI8DFGIL=5E6P;y)KM0n5Komjm-(d=dlm zUjc0f$-lbz1I&N@>=Bs%X5%d||Lw6OVE(&_d%*nn>mM|L)PI^}tNf2v;! z=6}v#0_J~-ZwK?g`nQ4kzh8KQ_5Zoy$pF&#_k=c>|8IvjnE!wI{|CS@U|^X3?*oWp zY=8IwM7!vh6@X}0mp};pc{>9WBM>sPfGH3Y0a<};HdZ!PpveFK>sEriwsQj`%m4qY z7cg*u**suU07No~{QrOa0HcJDZwQ043lIkbaX1hMgfO@Q*{(n_E})- z&bkfepYHev=3i3&0_I;z- z&bkfepYHev=3i3&0_I;z z_Sg|H|K0wF1t4|r*FR_g(H{!uf#pB;9|H3~)h`9hf6iY5=6{KA2lK!Bw}JWpcF2I$ z|6l(90WfSB7^eUG0HPS%A3gxlF8XB!AllU>5JG?64&pMn>*ju7Vgy2F7BB^3qC-|T zAOs4s{{O%BBgi{DH!!mN|G#- z&bkfepYHev=3i3&0_I;z- z&bkfep9)t3^H1Gy2lG#N`~&kZDSrX;FC}t*0O`A2`k4VlUvYR1=3foH3g%x^I1A=q zH{A~A-(Xk|=HC>Z3FhB?FcHkZ^>1qfNdN5v#bExOd(*-EyDKLYfW+_Zs|54!cNT&9 z59URK`42Ng!2CybwqX8aPctz8Nt`^G|KgL_2ax_(K%ax?e>-Hr{Qt}UKLCaW1H<%x zA3zji`@;ty+C{&t07SdGI46MV&nrGKF@hm83zPxjLP%C7RyGLy|9`y|$c~*G7+L=R zU%h~V1I*?DlL8=;LFE7c;|CZee0)O~oLzu87>L7xI3R?<707l4ig5uMra*>{ud$wy Po`H_9p`o6ko&gsCE#d-; literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Inuvik b/testdata/zoneinfo/America/Inuvik new file mode 100644 index 0000000000000000000000000000000000000000..86639f6ecb4c424911e5bdbca81a9e39c86e850c GIT binary patch literal 817 zcmWHE%1kq2AP5+NDnJ+nLI`W|04iezVv+wq@PN&)0mx=xNmO3|qFDpECV*%*N6rNx zn%&?Hn9rf`8qDVuI0xo)F`NbSxjt+F^SK|a2lIJuo)rLUW8gh75zOb?xgN~tU%5^J zBrY&>BA74OIRVTUs!Rn5GYDsNNp7VhDmcMU;`Bul?f%(?AcZ2yh8zAv&yL&E}Z`TirSNqxZV7@~> zBwig`W;cKYoctm2>YP#w=DX-mng9}ab%_V_T|XZcU}8jpEX-s=khu&D|NqaOz{v9d ze}4l52Z+tU^Z)Bk;*(-Qd5Txk+N7PC8y{8-#iKZhi9Jm_ssJ$N>il8#}15% zHhA$U2VbeCH49a`L0P#o+QIwB>^~a1x~tPSW>)`dyvNq-D(`V+Utx><61HY8!SRkU zSYS_KA=(4m^lsR`{zPY#gvBs?c)klh@~kt;=Z>KkIPuXf_-I=td@ND{CtY{L$yFkJ zyu=Ql5N)tCOH>&p#kvWn#@OK0Z9(Jnv~Qbm`sy$E8xBYLp6}icoL^A|7hK(d{jMCi(6;~=SrXvlv`;#t6#v-cjg{;! zV}Ab4D*A=bBRZd7oZixSzx1L*=lycu2e@?jCR}!R4leI{pz`lm>IUIJ^9?wd*9wP% z0XXz~GHN!(9QwZ}Hg5kt`XR+I-Y%NVhA}_GtT@~8b{NLgW0u6{CTFfJvrxUlLJd?w es%r`h&^bV7frfq>dTR3}pCo%~y7fthJwzF=o6m@ic60p<&5 zx`X*5ky>EBsHY~FFJ{RD=8J1`gZUClnh6X*Aj$C-%$H)~PGDqW#sdHU-@(Md047=f i|KGWRf#d)G;|Cade0)O~yn)y?7>Hd$7`T88Q!W64fkAEn literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Jujuy b/testdata/zoneinfo/America/Jujuy new file mode 100644 index 0000000000000000000000000000000000000000..b275f27c0287415674d2ccc850c3d612f4a45b0f GIT binary patch literal 690 zcma)&-7AAp9LLYtn6--)MUoU6lUjQ*d28B*lHIUUu3ShdMJ`Z6Zd^#Mw3H%mw_+~F z@;aLtF4k%!aj}p)OPZ&7Jg# zqbm60{Q`JjmlJ%lv;_9o2ha~pM9@DilHh~ga`@n{4nEXufe*#Dz~@sg_)GgL`j_!( z_^_SBhutsWXr&qc%GLu;G%Dc}%M$oq(GQjk8Y}&e^t_CIGS>#53`OBT5+m@R(Hi)# zfEoV#pacGABlTXti)JvNHCe^mvh4L%H>I*{V1=^OXftATy^}~++4@AV^i0cO=nUzT5J?{CrM!!wGyI`LMtet z@<=y{6vw-Q(oq*BL52{5R*+sqM4va6bP;{s3_ZQizuQ2156}C5f6x0I&do{h?>wlo zMVE+{z{6E3A}s;UkwxUFDOr6P@hmv_jz>6nX;c5WV=tKTzJqTQ5rXcB7KKl z3rG~Ei%!^lvH;FIR;f|n((czO^Y;j_HRgbA%2(KSxe0cN&tb=%afy#J;ae6ict47J z=c{KT^_M&zfR~Pq!pm-rNYobx2jJy>8oc6E7hKqR9Co!GKo;#tBUeW2aK9>03%g5G z8slrV!wq}P5!h4Z!kp)OW0vlVKUV0J-kEZE&4dkJd)ErD8~y@IC!z|?mGn--rF)Cv zvcsPx>X%36;fkG8u&?MH><`|C{R_D)%>{%jaNzA5I5?Mqs~(NRq1j71A7krp48!uh zBXISZbFgwX35O5q3eBlqDqPcY7T%C@!4ZE4T&wulTMdT*h`_^SU@2}g6k;Ej_4 zyy^8zcyrd5rMWE+$Kb7+9c~yJg0~%=gJb9K>wJtg?tTh4bqvDs>Jhj(-VHbZ_@J1~ zc@}g2KOgJguFYZpzlX8eZpI9wH%EJa53?A?b(rPY|Oxy`($W$9Q}meeFFkQt?{FAYV*FJ@$#AEH7* zGFTdFNyM@Uvcjyy!k|*2Oij;LS(%qZMbX8b-uG{b-=z2Op6B^J@BgqHGwd}LXvv~W zL=$YYWmx=?5*icJ9VXC~=j>=?)zYf0VD-Z7A7)k?t9;<5hGDq5_&Z_qmOwwa*Lyq8 zdk6LKlamg(Kk6&opYOr5{6NV|yv{(g2j)YLo5&4!72|wlv>txlb_VC8on`P?O%cpl z_Q5uj0k)T?!Edq>;J0}Z@H>SR9@nQ5_PXyAWjw1NJ?Cuj4CZ+7_8xE-E+ z(G5@abi>p4Y-X05v2qox^0K-2_j@n}x!K3z9Gg3Cg~7rlfur9kA@vTP6;ZW~W7X*h z2RoY`MrIe|teI8U9L~t9TlyF*RzHBnr-ES*-|KVrY8}sV621!Op4tEgYF^hocTzIYQUU_-=UBmb38c zfL2%@T@1?|56vv6kmSOO(H1y*A`y=1tcH~X1|yA;H5L=Bx{(0KmT!gCwNhA9Sje-S zw&*7ur_X}d?i_*RFI;l4O`$;>$I8W((Y8i z>rX$2H=N%OryrjCT{l)9HPRT_w4)B^83*#=%-B*`mze?UzFg*=M1L=5m-+VJXui6- zEx1Gr`i1lV=mo*r!2T*7*F-LYaHWyBqxZtym)(iKAUx_4Nw;MiNJb{zyXf9ccaDMR bXs@F)32owOqs)#|X;o@vwnn4UsML}_4kxPc1&!$JkF@bNJr9S<$8N2XrkuLwNmA~=|0_;8eX1DFTp5R7o>Ab@s-N&^ z%qUae%$sIL`OkAVtlV?M>YzoY?_rlLNW$qUSkpZPYY&^_ROn(wNy-H+U*W>0FRKz1#)QIok!#J=O}( z>uiNf+k^K2F1q+;4c{llSnV+wb7T znaA*wLqBg>fl3}ie-T@c=_gjxVr2v?5yd5ok}iA8!ppc*!5uuu9=iz z_oIujXRISmeJfJkus9TkYmc|X-o9$scOXG+%zwlH*KOJfuiQ2X2b_)YD*r3EUhjZ| z6`y4)f}a$)VfqE!_%w&SdOS5j2WxKS?{)2iB)sl?{$AH#?SPvO(pXfFH1wH5PCjbBd literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Knox_IN b/testdata/zoneinfo/America/Knox_IN new file mode 100644 index 0000000000000000000000000000000000000000..b187d5f8c75685af67913e9360b50ecad19fe6ad GIT binary patch literal 1016 zcmajdUr5tY6bJCTf6mQKS2>%jrfD_Iu{Og$fkDtD77dK1QjsA+v7UaF8NS4P$$W^) zg0cs<5kwND1!4xJl|&RlGc=cf+N^9?x}WBQscqf!?bY!9IQN{-`JH=Ten0mi&+!7b z;*#(Q3R>=!j~wA+NjwY*zN%$$Kjqdt7B6Mrlivbm|AkaIaBCQTdod38=gz_XH7b$j z1}X*^<-zQC@W;X~c!;&bA$k=U^W^ z^{Nk^?uiI=Ppm!cr7Zeh!ZVj&z;j0%;f47Vm|u)KaeisY3IBPW562(p!->0Ek-iVR zsYQ}B#$f5W7%V%b5vY*YqiSA}ji(Y$KUf0moh5L_4kNra&j=fGiUle% zlb2wlG!r(?8obn47g>bY2N&QC&qra?!x12 z58lu()!iYHCldGkEE%;1yN-62zR%@myB$0Z@TlTZ?q+4YR`W&?e_?TLw-#7!7MI;_ IwOeiKzt^*oeEHq)zu?!6V{~y@F f!1Dk9@dFH8KE5Fgx&|i31`LkDAq-qV!h{O|LRTG6 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/La_Paz b/testdata/zoneinfo/America/La_Paz new file mode 100644 index 0000000000000000000000000000000000000000..68ddaae768e665a8170ea1485aae51c686f5cfed GIT binary patch literal 170 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#VuAlakl8Ms0-|@wO?v{S-(9`J$i)2r{{a~W q1~AF;|Nl81Mvnjgj~`&*@$n5|a0X(h;1C8~0}}==8z5eoL>jbKmMQp0MHBuIf)|yV7fon0YuCH{C)vMD-=vP0HRgrJqGjD zL~Fo&T~%hVdfnM`92l9IP~iXn+mA3X0Le8V^7sKpmjC~EZeZZ>@eN_nH825UQwA;@ JAZcgH1pxMtQp*4U literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Los_Angeles b/testdata/zoneinfo/America/Los_Angeles new file mode 100644 index 0000000000000000000000000000000000000000..aaf07787ad92b65eadae63b64bba290f9f961507 GIT binary patch literal 1294 zcmci9*H2Sn9LDieD5GT^k!3}#fRvU}+Ol293PTAX6-Nw;QA|w?AV~B=#E63!iUt?{e^uDUh_zbTc#Chy5ydf$}g%hG-_ z7wo2OE3Uy@hxsMi*~H;~SN9$GbM*tXyYU?QrSu}&Q>jP4>T}WFqRr^H#I5M}%mDO< zJQ(eZPh#os^*g7b12W}8$Ai#88^?v3T+yF>W9U%*6gu2uLPrek=xFT-N8dM=*8u-2 z{{WAlY(^(?9-)(aZlk|bE~9@U&!AI*h3K^3EtbA##%TvUYg+=(PM?<2^SOa+c)slb z{P$G?Yr>C<-P8(r^yXo(L4jMte=KgRdvGB zLVqb4XI7tj4tr%dz}|;CSbFXgG77IrdItNteuQO;N?2wdHj*($E-r@U-S1(=;6B*D zu^v{o7IAbgpt1s1J>Clk79EAv716Nf;3X*;W3>4`a8P^!9Gq?qhsZMEQ0)L5W)lvF zds?yNF($lU0!PgC!)sgS;dPy_;q`SMMl!~1Xt)n=ET4rVub07_a=PHCl4_35MW-~v zG5asTv4KW7F7_}SH_{J~iCI}~o%H$xGR;5-ZYcwj2N-h2ezA3}w literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Louisville b/testdata/zoneinfo/America/Louisville new file mode 100644 index 0000000000000000000000000000000000000000..f2136d6ed41bb7dc0646b91bab366efb46bacb78 GIT binary patch literal 1242 zcmb8uYe-XJ7zglo-lp@CmX~>(rPY|Oxy`($W$9Q}meeFFkQt?{FAYV*FJ@$#AEH7* zGFTdFNyM@Uvcjyy!k|*2Oij;LS(%qZMbX8b-uG{b-=z2Op6B^J@BgqHGwd}LXvv~W zL=$YYWmx=?5*icJ9VXC~=j>=?)zYf0VD-Z7A7)k?t9;<5hGDq5_&Z_qmOwwa*Lyq8 zdk6LKlamg(Kk6&opYOr5{6NV|yv{(g2j)YLo5&4!72|wlv>txlb_VC8on`P?O%cpl z_Q5uj0k)T?!Edq>;J0}Z@H>SR9@nQ5_PXyAWjw1NJ?Cuj4CZ+7_8xE-E+ z(G5@abi>p4Y-X05v2qox^0K-2_j@n}x!K3z9Gg3Cg~7rlfur9kA@vTP6;ZW~W7X*h z2RoY`MrIe|teI8U9L~t9TlyF*RzHBnr-ES*-|KVrY8}sV621!Op4tEgYF^hocTzIYQUU_-=UBmb38c zfL2%@T@1?|56vv6kmSOO(H1y*A`y=1tcH~X1|yA;H5L=Bx{(0KmT!gCwNhA9Sje-S zw&*7ur_X}d?i_*RFI;l4O`$;>$I8W((Y8i z>rX$2H=N%OryrjCT{l)9HPRT_w4)B^83*#=%-B*`mze?UzFg*=M1L=5m-+VJXui6- zEx1Gr`i1lV=mo*r!2T*7*F-LYaHWyBqxZtym)(iKAUx_4Nw;MiNJb{zyXf9ccaDMR bXs@F)32owOqs)#|X;o@vwnn4UsML}_4Hq)zu?!6V{~y@F f!1Dk9@dFH8KE5Fgx&|i31`LkDAq-qV!h{O|LRTG6 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Maceio b/testdata/zoneinfo/America/Maceio new file mode 100644 index 0000000000000000000000000000000000000000..dbb8d57d91d6640c1282fab3a063567d1f663f88 GIT binary patch literal 502 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1S(?&VxIp%Fl|*v4T#>s@A&{s|8-aZqIZ5YF#yrK z?v*Hj=vx-+!2DaUe}U;ck`Fh4#P95k1k2z3EeaODH~Su#fB)_*F#kb_F_`~l`hT$c zudH!k{HqU9HuZUE5=#^)D+XvM}%u)GrY2{2zdLI5nU{HQB<+m30J!?WRR910 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Managua b/testdata/zoneinfo/America/Managua new file mode 100644 index 0000000000000000000000000000000000000000..86ef76bf2241b6abde0f4790d23b180db4b4b1cc GIT binary patch literal 295 zcmWHE%1kq2AP5+NDnJ+nLI`US04iezVv+wqklC)20;2codb|MXXLBw|0MVRF>;gcv zVBn7jVERfvm@jO23(ObZ5(wsNCQeiU$!i_-2J^L@?}FuxPQC~8ogxl^`Ofy4V7^O8 zUIS1$gR6XG0wWVM6AKVBL+Stj*UK<407(f3mjC}(FJR#K|9|HO1|AT}DB$B8!r%+U U&cPuJu0ZVU62ia*J=vx+h!2DZpIKcEB$@d39;&*nYgXQo3RtAgToBamNzkhcHnExQe5zPNGgBPs+ zD{Bsz|Ls5#SpGYo&IXVf literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Martinique b/testdata/zoneinfo/America/Martinique new file mode 100644 index 0000000000000000000000000000000000000000..25c0232d95492333e8c1aef7321a24a331e2e24a GIT binary patch literal 178 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gw!T&&z*)DPfL{D6N!Ud#X*f-AsM2nb+ZD3?# vX8QmC*d7K3Fv;@&|M3G1od5q{y}-!p;~T=@<_07jgMrv3gn%Rx)+s`fl^BwXJfccIsy#+vR3{L)wzl9II zo~J&ZJ8yBA9%rqcy>BwYUTqre{TYAd{poYRUA(2Ft}z`?{XmF|XR^f!r&N8ysWHWH zn*Ihh_{YNO;U65Q^hYh6@qG%tdWH&5oS1v?KkqeZ!+_+LJEv2^RlKEL0^b9x-k-fkoLbE#MdFTNaqk62k- z3ad=Y)}Uuy&2wqiRmpR6v{m4_m3uDo+|GA_x331^ce2JMe!sJ^48I#&gWsFGf#1J< zgg+S3!TWc!;U%XFeCYLpk7{M~%M&5=ALl9XC!K2elY{|2&|rZNL{`CPQ*QX6eG&b^ zmudJ*JB7a#pTXfWGyIjU3mmm-;iEnU{I2N(D@MJ*zejoUp+A;kgO3Hm@E_4(_;|P) z{!=!?f9dUMS3^5*zyK0ejNgrDGIhnv=y5 zIM+J@=cT@a&G|jBIU1Je!lG@4Eo(Dy{-y^m_%H}tBiBWmJ2l(|3o~xG@J=Ia8_0w0 zEuA#R9JkeQ(S@tc9vncZOJl}snIZx*~=W{wo>YMPZ>CX_@22UQ+-zPe@CbGrZgwZV)yEqOdW%8f0hG(Cwz?t&kV3%a^C5;J=V%vrA-hNz}~JWR@s{ HL6h+d(?xwy literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Metlakatla b/testdata/zoneinfo/America/Metlakatla new file mode 100644 index 0000000000000000000000000000000000000000..71b0eab085dbbb48050d7b6a271ebb1a29fb1926 GIT binary patch literal 586 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1}ftKV!8i7V1MZEMG#%vZXgAsPj^Z!0MVC}zZ8J! zL^S~r{cnf60*L;I*<_lF8gZaXlMPR;2WGI*~>KOv&i&>h3`Qn;pV7`P>@B{`RkmQsA z^QD+f!Td1OM+-pWVNX2_Ky-xMe+4joR13_H{Pz&dk6OwD=11Q<4CcqUxGi90VrF4t z#S7WkL6C`!f#I4O1H=FSEz3Y;e**){|NnC*FmixN9xw?E{>B0Z5s)mSq>pb1LqISP qhXZi{5W9phIC=vG9KC@oE)dfa#MJRM)-%#G(D5}i)HBpG-~s@c41tya literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Mexico_City b/testdata/zoneinfo/America/Mexico_City new file mode 100644 index 0000000000000000000000000000000000000000..18112346129a885b5d5fa27109682b63784f72c0 GIT binary patch literal 773 zcmWHE%1kq2AP5+NDnJ+nLI`Vd0V-nyVu}Aiuyost0ua6aqc)h{mKK%(;%|4f1@m|C zn1T5_{ z!}Kx`#b8v-Q2?Ti-6KF0gGtaUFyB<&3d}b%Is@jLv&(?_7Sb<1fEX6f{(;HiHw!8ble7pX8V7~qA0x;hp{{Wcp*wR}7)W+cCzX;5CPRR%J zUG!VPd{>u1FyD5|IfG3M6nD2Qb70mZ~{2k2q-r)}B`m zKSFd?0Z@WCfET7OC+6|HV8E4FCVnoxs5I|NrU*3>+Ym nk>~&aof{Yhz@&(eZwP~La0r7l5c|3SX%G$%Vc-G^m~jCBO_)21uW9Uh)ADtx)>p0*F>@EO!9W zN}wVD`I`4S!F;V((qO*! zzHBgG=dy(ZP#J^nJYO(hZ?hDbuV1GR<{M1<1Lhm1dtU&lGb*|V<{P`~g83#v2f%z& zb$&44%xDpqZ_f4+%(sxV7`lf6qxVoq7LS}e(t%z$iz%6{Qv)S z1OvnW|Hlt7u>Ajj^#TLO|NoC4F!K2LhA=n=hcM_G7z42p1D6euWoHZ|jqG%MjrEN5 O40L=A4fPE547dR2=xD(J literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Moncton b/testdata/zoneinfo/America/Moncton new file mode 100644 index 0000000000000000000000000000000000000000..020e33d976179e8f61a6040caaef3c8eb7f348bc GIT binary patch literal 1493 zcmb`_YcNz{7zgmPxr{cq+;Yn$l}oI9mI%d2*=Z*$X@<^+E<7Z+HQJ%tr*5oKv@TdJd0tHF>hv5X@N3k=sz+1|>8cSZHUb_r!NQs3=e z1MfL{8{TVN2-`cIgYDN}(Oetl$Pa@Z z*e!1scE1pyB7Gj0WUyzLHSBfbIqYrEgZF#n!#&9%Xv3c9i%rNg0DZePWK#G*|G8amuP%cE~ z#!OPnrMMKikWvyiQx@grIOqEhD9`CR&+|Dw&k-GcE+zRh1UA8whxqr3mW_q6jHfKN zy|?YWdR{XmUcD|Ge5BLBKDiq9ea{5=|0xZxypYuXQ#iYK1Xd15NW4)Q?Ql;0Gn}g^ zgw@ImI4?X2&QE;8e*WVRT=01g7Y1dM{GrHu1{Zt2V9m(_tX;f=OV%W~bkGm$rspNL zM#^foV14%>Y{;61%MEpKMT`qJrm0}##}wgVk|n^Vn;y9G;T^8>8DaBfT!1&0m2|jz zF9_F+M#Hsp*Kl2jVv;}94;;f*T_h};*WiZa7uc3L4mXlZ*q*Q|u{C19_rOiTG1%c> zf}5|LaLdj4Yw_)!0mlQaL0r;z?)8!2zNP?144)pDul@Xc_`g{BZSg* kH<3}gyFnuOEyyW7J`iHf7Li!2BGI$77+7T)#h{M*1uxs6P5=M^ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Montevideo b/testdata/zoneinfo/America/Montevideo new file mode 100644 index 0000000000000000000000000000000000000000..4b2fb3e560f6ad26b30b2215d26b3d6176d076b2 GIT binary patch literal 969 zcma*jTS(JU90&0KYIB!da}FY!Z8NiJLzHNNX4eT7w`JT`D{m!2;pTD!+A}l*Z zyn_}E-||oP@-{hNn;0LxRUfRB!xutP$`Lker@Z<_6`{QL_CPh|^=A!c${X?CG0L0K z6R6+*J__F%ABFEeAAs+L2jKBr-Eb_}4d3r;gC7Li;P|PoYWm*8+U@Y8Lw-1+*TWNQ zy>L=yGgDt`y$()gb@1bJVR%xPfG01umr>vRsvf+b|GE`kXmr2}J<|rNFKLd#OFy*m zuRk?-|9eqgM*pMGf830m@fs+_`_4v?iETra(ta&0ee>!PS(XUno!sAwck#8w>hSFLiXl zr5PLQ#$pxvjp_ZUmn%%Dmq&8Hd-L2B>ZbEWsMom`;rg9hVgerx%~#TtJ2Zna%0|7@ zgZy?HZjyDN-ZXU>ZqByAEzx?|ku<^1!GK-h!!@FW-6!kd*3f5o*TE9lb0ptGeYCWU;) zUZh2Zvh9PnGr5lu6x;8#LijK~mh#jk-L?dRDa;5gI!=CiMReD?L(`{~xc zCNn)!y63p*4Y9=7?|o#yUK_8kDP#JqAIcdJSyEG^h}`kRWm)7m`Q|o}rC(LWi`-f4 zsfpZ`T8YcHyn=U!fJ!V)-mwF<`}egMLxO{@znI`upze!~2~U{B75# z_`A>jv7;I)Z%KeUadNt8M8Gjz1N^QlbgB$Ug=n8yRD#hmlKf#?* zTV-*s(^amB>Q}=Eh+P@IbZ^*}C z9d=o-N#P}#*nDsSw&XsItwqytL`H@tdXei#a8yz}Pdf|odk6w!OU?mhfO;c*6{=d6pW6okp(%)B2ZXWtu@_^*UcOR~P&)DozVuHS2 f(ASIlT4|RII->Q>Fk6&4(rgX0MMRh*%vQs{dz=-7 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Montserrat b/testdata/zoneinfo/America/Montserrat new file mode 100644 index 0000000000000000000000000000000000000000..41bf898bd7965d787e3eb1b55fb6347e10710f14 GIT binary patch literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@r$VdXJHe`A*`tzCnVk6c!{xa zBT|VVSz_3@nsLEGmJUH8VVxUq;mn1In4K_8XFZej0w<@oD{Mafxf=fastTTYS_r4^7QkwsD${==+YQ(Bf0NkW+IvUg zb!SH4+Dp6Py8XA{^_@pVx<=}o&cO|PcELVJ6!!ZXVE>QnidLi5q-k~k=Tp@?Q9@Mp wNnE2-)xn!YkGm14X>(8@{%y3k(hkw~3528Y(2G4-%DZ`|J?L`rF5b!g14LjPpa1{> literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/New_York b/testdata/zoneinfo/America/New_York new file mode 100644 index 0000000000000000000000000000000000000000..2b6c2eea14df07392729ae9f5712a44ec4f02bae GIT binary patch literal 1744 zcmb8vc~FdD90%~HLuD)FSXb_AZECl}O63S8VJF8nxh5}Dn&pq)VT2iS6v+%R8pbh8 zbU9ZSR%{`w$+%iaIr5f-h*vpM?0TNB|CxR}&wlswdw;)Y|Jv0o(ys6$|1BFj!450U z|5x;MtP4H8th8e6#JwzaIfHnX$F6+fSRUU&;LO8!;S+K7@X6%&0(+jd@;sca%Ej}X z`IRE;=StJyJpZ$Bo+TUer+e;!PuHfxXIgpqtWgV}GtYz1>t@0F!m;p$ByTwX=vNYrz$W!Zp51fXEeNjgj)5!MqB+*D zbPa(ks{`RXJ4Lu^_}9P5bzslDwn1d`k3wF;kE2ZRlOd(>Q&k>ZO)}vc=`OfNNQR$T za(TA@yetlWQJV(8JhhEu{aWKH_*GggEa=p5opw50pQMCeM~sFWV!Fd`q7?$$Zw&Vq zS-uT$hu_KE;P<^-;3kJJaMSlk@P|e-{PD>}xY<+;e=0R|?4Hm1DxRfytQh{1UIe#n zJ_xra9Du(r-2i`!Tn~SrycqtWTm-j`UMH}7e!5M7+npA|?QIK0*6(;14F9SQf`3;G zge{i`z}8%=Kz}2I9JGimY*On4mbU8z*p9bw%=X-Go@JLg0>{!JY zr4e$tcc2U0NA3*w9VX`pt$t3;aDQ88xPOa;XMK;lW_ZBEkMO|j_u)bL_u#>q`S6fL zg8iXe_rt@Y>fzxl^#Y+aLRAiroVgDkCC!0lo@-#4r5lu6x;8#LijK~mh#jk-L?dRDa;5gI!=CiMReD?L(`{~xc zCNn)!y63p*4Y9=7?|o#yUK_8kDP#JqAIcdJSyEG^h}`kRWm)7m`Q|o}rC(LWi`-f4 zsfpZ`T8YcHyn=U!fJ!V)-mwF<`}egMLxO{@znI`upze!~2~U{B75# z_`A>jv7;I)Z%KeUadNt8M8Gjz1N^QlbgB$Ug=n8yRD#hmlKf#?* zTV-*s(^amB>Q}=Eh+P@IbZ^*}C z9d=o-N#P}#*nDsSw&XsItwqytL`H@tdXei#a8yz}Pdf|odk6w!OU?mhfO;c*6{=d6pW6okp(%)B2ZXWtu@_^*UcOR~P&)DozVuHS2 f(ASIlT4|RII->Q>Fk6&4(rgX0MMRh*%vQs{dz=-7 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Nome b/testdata/zoneinfo/America/Nome new file mode 100644 index 0000000000000000000000000000000000000000..23ead1c004ffd82c03b69b44e147daef4c07c961 GIT binary patch literal 975 zcmb8n-ET`_90%~HUDuamDC=grqI+v~tM0U2XZ5zWI>OY>^dNI%O^Qrnx-1bQ8$-ep zZ;2brknWBIX-F_lXm%qp7gHCMc)ek}5b++%c09lDA7JsEJkR&{dCvD7c}K@?51VnR zc!M@AdFD@KUK9AXDSS1KOg*LSIoXn>9PJN}QD!T?Cy+5IK=~)THAOjnuS=p-uF3)a z55_J=B?{H4`T(W+pbyUL+L9q_Vy$D8`K@&sN^Q^!>)ge#?#w>eVEhdmZj4LR6TZBJ zXT8heeL?P5fbM5!((s(&96a~h3-pZxX?R}$eR%$%%Wz@GCD_z<1TNap3m5xi@B&9W zTvFbXVSFt#gkZCJCv2`U8R_2qHI$+({ZN&pv}7ycMI$Auo81y^l+4BLv{!uIOxuzh+mMLmab7IwUO4OdSj;F<>yVdt~cNnT^i zt_;Dh+nsQ2?{QeXAi?fENs)S(r;GNvf;&vfpRm_|{$+f{m;1-LO{HYrM9f|V%BxuYrz x=CVx@nQe~py`67KW+6U@!ZK^)8Eoc5u$fN+oqn=2;&pjkqBG)lyWB2O_zN7H-5me` literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Noronha b/testdata/zoneinfo/America/Noronha new file mode 100644 index 0000000000000000000000000000000000000000..9e74745ca79137918281337fa270c5fec4bd7da1 GIT binary patch literal 484 zcmWHE%1kq2AP5+NDnJ+nLI`V72P$I*VxIp%Fl|+83W(mpZ+!tw|23KbqIZ5&QvlJs z?xhKU=vx*G!2DaU-+<{ml9v~N#P96%2Fu_5%?=j7H~RvZfB$X|nExO|70mxK{UccY zSJnV9|J#8uu>5yEfe9dUegw*a`9F?t2h0EBIs#VzYsD+D{O{L4!18~(^Cy7(DSNU( z0YuAHoCNdb7pN})@fC~@g87P#(F!2G68A1JUpazl0f?{sC`kZBtC~Mq0H&|(1oO?m z?Ev#Fc9etpmiMnJfaEP-GJ^G6pZExtx5;Oiz{E%t{Qv*q90rE}|37|UWcmO9@dE}9 VAKwrLT?0cPHe%qi0g`q`TmX|XySo4Y literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/North_Dakota/Beulah b/testdata/zoneinfo/America/North_Dakota/Beulah new file mode 100644 index 0000000000000000000000000000000000000000..becf4383301e2d90db0c0c06659b588d25042ee5 GIT binary patch literal 1043 zcmb``?MqWp90%~TIi0&*>sD%Wn>}c`w&vWXGq;{r+gdY6VmGV^OEAUWWJN{L!!51Y zi|A4WmT6nj6H-llQw&OpBIx18gvbJWcvIN}Q9;sl>zwaD;G2GzbHC?v?(fHab;QlB z%?>hYDQE{)3iAAg6Jyotk0W1P%3%i`Ve^3z}862f!AKViuszCTO_4| zJ{c+m+y3V#lis3pgx-SQh(eW4cgrLjdme9kD|#a&wERIGi_>@Dd6Q|Jn?F3~uNj*^+66BdPQwfDr*PkLy$fE{ za~@uN<_Nr`traegH^3!3cfd=7Zg`n{Eo?21Dzs5*5@DO(1>1f&leBODVuBqRBV0E2 z9bP_^g;%8C!Yez<@P5^~0l55t3RfH-XVg{)KErEvJ%XJjFJMz-XzXyJKxI6=9-uT!Cv9!KD+vvJsa#R>b4bMpEAPL4bAX|eOWl*3c)r0 zad@Mk)wR|>HBAS#U$wdhbFbmh%Sqhd^zi|_c|fb{mXS;F*2`L5x7|#@b?sVR>$`gs z^l{`~;Xz$7t(kRqOlGkNAN%=e;-gV!VeT-u$fp_(Ppn$k;sZ*}P z3+X^Ny`XIcVMI0QqGV7?5J7dbZnD5$ZYp~rDoC1c{hsgs05AIec+T^Dp7VR)z&R(p zx4YBLW?dS7f`V3f_K`MzOyFV3^0iMVB`6Qx@TruqCIy9Z?5qWjU;Yd~>yzMA#qS8+ zPqiBv<-b!$43yKK_Q2DxTH%?eJ~;Eh3ulKc^mvS2G#e;s&SfYu?Xej+@1RK`>)K0I z%K6RH3gv=^G%PqLV4>dw>kXr@{`N5D#UIz;Iq%}QFO5Iq(~Qj>?SoZP z)C(`@I}I;9z8_xH-2oT1HNnMOH^U`f8@$-I3O1Gp6>5~~McAaZ!ls{kt!5-@t zxYqp|UMtw)I`bbs#aP`(3HGMPVc(PQ@VYliczr@tso0PlfH$813fEsb2{-iQ-fLsD zKSGU7J96*U-_ZjHs-g<@gMpoJ@Yj8&)$pCCL!$D(cR_w`^WWebBC45jdnn980Uo<}wDM>UGe5VVTjZBo4o9e3cFRsj$mNnRx1{66~wyy|!O{a)t{zu%W{y4l52 zhc20PgKV<+!=E%t*W#p|AWCaw;0Ad{C31Z=#1rgaftaNI1(Op$!xZ^q%$+wdHTn{s zTpfp}-amxu=@}JyubB+Nw9zqmIv~LGzPs>@zXxWtbihm(54Dy`c$O}NI*lHlOGt%! zgzfW{N0MRAhodkz{0GucH=!Z8291OBFt2wSGQJnk5C-~I78x^XWH z-Slb~-5gP(TgHz;Pk0Mn@85ym;1X>0Mqt~Wp8}cJUiKQ@;aNcY(udKV){r1O@?So= zTojiFC`uF~D^#2)M!(A9$w|e#IG!>vthCLP(juKUvvitlG{+hXj7*-vL~|wvzl`z# D+K#Hs literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Ojinaga b/testdata/zoneinfo/America/Ojinaga new file mode 100644 index 0000000000000000000000000000000000000000..1dd08b1cafd4b36ce963bdc42a075665fa723b54 GIT binary patch literal 718 zcmb8n%PT}t90%}ouMtfXlk7-}QjB2+<2e|H@w%SZG#HFWBnyhH$Sh>CGAwL7vLFi! zlQc-#u@n}}4i^Q>YG zc2Awd?T0gPNAC{YxiScQlv6(qT|S?evO9Gf?&(M)vYzQzk0eVWlB^LYL=68rvdsBP zEMuH6`Bk;*(-Qd5Txk+N7PC8y{8-#iKZhi9Jm_ssJ$N>il8#}15% zHhA$U2VbeCH49a`L0P#o+QIwB>^~a1x~tPSW>)`dyvNq-D(`V+Utx><61HY8!SRkU zSYS_KA=(4m^lsR`{zPY#gvBs?c)klh@~kt;=Z>KkIPuXf_-I=td@ND{CtY{L$yFkJ zyu=Ql5N)tCOH>&p#kvWn#@OK0Z9(Jnv~Qbm`sy$E8xBYLp6}icoL^A|7hK(d{jMCi(6;~=SrXvlv`;#t6#v-cjg{;! zV}Ab4D*A=bBRZd7oZixSzx1L*=lycu2e@?jCR}!R4leI{pz`lm>IUIJ^9?wd*9wP% z0XXz~GHN!(9QwZ}Hg5kt`XR+I-Y%NVhA}_GtT@~8b{NLgW0u6{CTFfJvrxUlLJd?w es%r`h&^bV7frfq>dTR3}pCo%~ypWzNh zCT5oZ|Ic_ZFaSv#1`yi^M4mgr!14e8)e8)KKE5Fg0YI#4U~FsvA{n@BfTW!<7XUfW BELZ>l literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Phoenix b/testdata/zoneinfo/America/Phoenix new file mode 100644 index 0000000000000000000000000000000000000000..c2bd2f949b248b835c98216b4dc66f9f6eb0265e GIT binary patch literal 240 zcmWHE%1kq2AP5+NDnJ+nLI`W&1}b9#VuAla5XZu^0YuMRW;Fps&)?170HPPP$$r^U93H~J1!S0W0RTV0SUUg! literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Port-au-Prince b/testdata/zoneinfo/America/Port-au-Prince new file mode 100644 index 0000000000000000000000000000000000000000..3e75731baa7c47f2a60ad07733d6f8467ccfbebf GIT binary patch literal 565 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1uA0!V!{7Fkl8LD0HWvQ75)L~my~w90HUQB-#dWm zkM9CNwDiM^V7|=73t+zN!OdX4+{R5{zWl0V>y_w6nf{dgKEJATTQW1?C&OTZ8!~L3hA>C;tktd!18U9T*R749pLf5d`x?LQjDCA-_L^`C+E3!2F0KA3rcM zGZ7E}|KDT4zyKs&7+C)QKYoCb^Z);y8yI+fd_x!l0)T|83lIl~FmM40Qy@pj*I3U; P&p^l5&`{4%&wvX6G;?mv literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Port_of_Spain b/testdata/zoneinfo/America/Port_of_Spain new file mode 100644 index 0000000000000000000000000000000000000000..f4fe59034242c4416bc84f06f38530d625149329 GIT binary patch literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~+1z*yf literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Porto_Acre b/testdata/zoneinfo/America/Porto_Acre new file mode 100644 index 0000000000000000000000000000000000000000..fb5185ca60283bd56f795e9a956274c0b6e63325 GIT binary patch literal 418 zcmWHE%1kq2AP5+NDnJ+nLI`V-2P$I$VxIp%Fl|-a1Q5N0KaBxQ|BX2SqIZ4_2msN$ z?oDt2(YGv4f%&)Ih=J)ll7BCN#P94Z1H~SZufB)__F#kb_KbZezhBR3H zSJo;p|J#8Eu>5yEs{7CynFoMwXOKO) zDgZ>wReU}GqU9F^UI5Vw#;*^6XvM}>u)GrY6ENQ+p&rZ+s%JUC#E1tnGyVU6pn!ql l|Nr9$7+HV;v4MdD#Aaae@eN_nH825UQwA;@AZcgH1pwW1w6g#J literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Porto_Velho b/testdata/zoneinfo/America/Porto_Velho new file mode 100644 index 0000000000000000000000000000000000000000..7f8047d9396f92476873c9dbedb4598d9d238046 GIT binary patch literal 394 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%Fl|-S3lP17Kl}rj{_D2^MDP6Q5yEoedy!egs;9`9F?d2Fw5AdH`1cYb6_4{`VUZu>7Cy?hPP+%ATC# z0HWn8o`U)E3!D#t_zK2%!F0wm`-?mfsvVs t@&Err>EOaI6Q=b3&=6y0ss#_Fq;4X literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Punta_Arenas b/testdata/zoneinfo/America/Punta_Arenas new file mode 100644 index 0000000000000000000000000000000000000000..aa839ea7d42eb9822002e66322c4ae195f1644b5 GIT binary patch literal 1218 zcmcJ~ZAep57zglkx4D^fscELBwJgnA)^wWFbY5SUnr|y-O00+iQ;9T5{g6;esPrLA zln4tkA|yhuT1`pu5|vbo95j}Y1Z74MiAC?~?VLaK*-t%}^E~|S^FLg!bzenUELpNR znqY^Ob?Ga$G^U~_K%!OA95&Bpt3J!jW~c3)h0U&pHxJqDCdWlKg#-0)e|-wiJdj2v z*c>da#{PDA9PZsoypH`{`4Q~xA#UvL)1BB4E!g1UaV_i!J%+sF=zHW}ta=N(48_Q~ z>e}E1XENqu+i!t=S8_ZP=|2!s^GaZYtF?%1%J>{uUK|T6v^v(` z-bj34<5N%U6F=xgLM!R!M|j6$4V-+=0jKoL!luezIJLzI^F>btdX1!&55nn&TX05p z2b}4D9yZ4e@H9ruU#sCPzjiolR;Fj~v*+sIoRKPcm$MYk9U{o*^(Vpkk5t$fSQqK_?B64o$rUoW z$Nznlk~Dgj5Zdn%g(M9N#8Z;SMdHmmN4sl+^JSg*=H**S5k1lRczWXKF%Yk0+D!(p EzhvT4*#H0l literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Rainy_River b/testdata/zoneinfo/America/Rainy_River new file mode 100644 index 0000000000000000000000000000000000000000..7e646d18e18851bfde743b379e52df4ec5b5a20f GIT binary patch literal 1294 zcmciBZ!FYt0LSs~`O}?4B&X{LQQZ!myYnZ1OJT+`;uO_dnv$NlRLleVwQTVyQY*W4 z(LBi7!mRn%q?p;t8W*|fx+IxDC2aZEUBB<=*K^PM-oC%r_x=6-dGg(rRSorZZ6vxUrEG!rn{qRH z$afj{hqCRkuP?ty=>7NUXVJqM!{`z30rZEER`e)oL>ojkXoIN=Jx2KGvHsKOapQf4 ze(zI5rG{$kDn@^5NvPk#h7xA{ZM6AyZPggkHryjx~yRrC{DUzRX*VUukSZBsYkmY8|SR~Vtd`yI4% z?uJ6r%(?Iw+MBAOgW)Bi!?F7sdTV^#BFR5cN@5z1}`BnQb= Oaz#M0QYlx;6~e!?Qp8jM literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Rankin_Inlet b/testdata/zoneinfo/America/Rankin_Inlet new file mode 100644 index 0000000000000000000000000000000000000000..6d1d90dede9888571eb09299dbd0b3e7dcfb1cc9 GIT binary patch literal 807 zcmbWwODtSr6bJBc7-n3`R8hvGgEAQ%*PZbi>e-ozMSB&Pw9kd^zWL@;|wr*KI9!c4ujLf*zIU z?vrvJ)ADCfc^!Ufr!%H~6Rc1VczG&Q4=g!RsOzLnSZ~^ZgA6mUz`U^F`vwQ^55ggT zrhWX3Jy`hwhb|1jVLu0G%?v}G@Wb9tIQ&yR{HU!Sj%akikrfU&D$fW%wiw~)q+FSX z82vSD^oxOw=g|r+Vh^t1xUEY#esvd4@b17*#+PAJR~W@vV)rNlLfwhur5I|&y|T`ROG zTzRHw)QT+pUHg~|Tj2_tSs)5}X^UP0k-_QTnCI1~SRb80Y sXjOG$jOl4+A?cFDoGuS@zVa|Pe*zzJ_`+J1DcVKJT4l3|Hc=A(14>JgdH?_b literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Recife b/testdata/zoneinfo/America/Recife new file mode 100644 index 0000000000000000000000000000000000000000..305abcb8a2217834e8333a2c486ccd389199a334 GIT binary patch literal 484 zcmWHE%1kq2AP5+NDnJ+nLI`V72P$I*VxIp%Fl|-(4iLSA-}3>O{_C&+MDP4)VgRCd z-78T5(YGwtf%&&y{{qu@Bp+@7iQm~736{V6TNEsQZ}vSf|Nh-sVE%&;V=({A^#5S> zUs>b8{BH+R!1CYuk?S~uN6PQ^1t7(f#v^n*De6Mok8|w zp8<%LtGK=ZM9VKQ-2kE$jL$Cs(Ta_kV0k6(6JWk_gaBAx`B8xaNM6R=a|KImuVEF(4@dHMd|NpOE YVBqla4PnqVFaly@1}+;QX=ls@031EO_y7O^ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Regina b/testdata/zoneinfo/America/Regina new file mode 100644 index 0000000000000000000000000000000000000000..a3f8217a544ebb0993473bbffaae8e2d723c4ec3 GIT binary patch literal 638 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1uA0$Vu}Ai(Drw-42Yh$WBmjWJ%2ZQ1Bl+5>i+>m zZ!_?C0HU|M8iM&d1hl~XovOlM{>~3PVE%4Cg94Dc-RIwd`Fq|8f%$uPawmYq4;68M z)gMlL4VFI=_zKKFYB3osf6VX&T9aP-`m#?=HKsZ0P`Qr%LMZuW+s98kLtX^{KuXy zVE&UhT`>QtrW%<4%-u@>WX^LTX9f`cLR|;UfAL8b%zypt1DOBj+GQ~R?XgP&OpI6| zGYeK>h+@|N|K~no02;A+0V4~LJ%ND(%;o`;Kr2=+U=Z=~4Po$g0pegF4hQ0Z5C&%; Kn+r&oaRC5Dz-C|o literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Resolute b/testdata/zoneinfo/America/Resolute new file mode 100644 index 0000000000000000000000000000000000000000..97eb8a9c1fbbf56b8e32a1bea34f68e263e2a9d7 GIT binary patch literal 807 zcmbW#Pb`~Z90%~H+G+PHim|GWV$;;>_4f6z$~Lr(k;u$Sa5F;e;!T*vMcTy0!Iso^ zSR^*PEtae%B8_aT%MKzz#6kQC7g;1*-f>g$dY*3_c5CAI=E?K@{PKNnudlPeS0ph< zMH}p}@x^}fnASA(7!*2N(SV<3qUlP&eWUrW#2jDq2i6Mfu+Fju-!y!KIWh-x@>@9J zU=r4Ehh#!0G4c{l3J2lj&q1~(hWA5o%J>kRI?@KG^|!&dI-GENgA>lEG{LuRCfJx) zA+eCDJBLkinXu`^=x2+p!zgUtID_vj@4?w~yKv6TPuMb?%<3dJFazhc{)6*he3x0c zTeb<`Yy1Egq%XkM!T@Z&*zmK3jq8SO`}1(&u@}Do;~i|@d@iwG(ex{rpZCDUqaCm? zSpYlwhFOh>gF3jRz8x-YIfl!uF1TD=g)6jX*qQZPX2E%M0ar#>VArn$xN7GMT>bUj z&lV4sUc(RH?8A?yB)DcE0@sdBNUT@)-W3bor6!xAjk~r0MKlOhv)mOi+ vqJ%>#jiStcBs!LfzDN*=+v6kdXFlSkhohmKF6>PuyvPgoCWnJ}@B()U;8v1r literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Rio_Branco b/testdata/zoneinfo/America/Rio_Branco new file mode 100644 index 0000000000000000000000000000000000000000..fb5185ca60283bd56f795e9a956274c0b6e63325 GIT binary patch literal 418 zcmWHE%1kq2AP5+NDnJ+nLI`V-2P$I$VxIp%Fl|-a1Q5N0KaBxQ|BX2SqIZ4_2msN$ z?oDt2(YGv4f%&)Ih=J)ll7BCN#P94Z1H~SZufB)__F#kb_KbZezhBR3H zSJo;p|J#8Eu>5yEs{7CynFoMwXOKO) zDgZ>wReU}GqU9F^UI5Vw#;*^6XvM}>u)GrY6ENQ+p&rZ+s%JUC#E1tnGyVU6pn!ql l|Nr9$7+HV;v4MdD#Aaae@eN_nH825UQwA;@AZcgH1pwW1w6g#J literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Rosario b/testdata/zoneinfo/America/Rosario new file mode 100644 index 0000000000000000000000000000000000000000..35a52e53d123b5ef5d293b3af19046630f02bb66 GIT binary patch literal 708 zcma)&-7AAp9LLXIFiTlcB#CUTO=`_%^47EqFWC(%+7%_G6uB@ZhCZpmC= zZDV5?F7(tUDHkhpN76ja>v7I^f54p6@A>{d=kq%k&v7`128|@+lCTM0d^s{-X<}p9 ztO_YxW6RrKo*N5p1JC`*E-TN2l1rTX%G_XId=%baG!^FFzqbh=NbSN07jNMY?;hcg zCY11@KrwvS=>{LKtbk7%BAAa%3z$DG72(hN0YPeo(!A4wPdXRH?f zD`JNK4tB%;Y^C4pci9Z4^Cl~MTavTc;pM4NkF4>m^z4DvDi2s=c>`-+$HCf)d;_1; z3cX+*p;pd1Z#`I_h{0Da^_25-i+GOvbs;^n)s>sh`x*GQ&kb;Uu)ka)mHl&P$h(HLwa!R9NqM-CfkmOPNkdUZ&Px3nL4q{_fZ7{K_VPz!BM%FdgDE|PnyG!l> literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Santa_Isabel b/testdata/zoneinfo/America/Santa_Isabel new file mode 100644 index 0000000000000000000000000000000000000000..0d8c993bd1cf2fa2cbf002421ec9c0fb2b29645b GIT binary patch literal 1367 zcmc)J$xo9(9LDi!Sqf!)WfxE@pruesTehMivS?)sAQi=fTM&bZ0Yr&h5EK)MK?-Q1 zF<{l0NKh6rh(Qr9L}T3QK@dbl1cL0MtWswl{s4|nGw-*bd4KPFX{tGpk**}GE*_m= zn=Q@ij}*}{Q@WiEblqzj&SI_3OF-+ULJF9h($nB4t{h=*7EVvHz8)#TeZ9vF?&~XS zasJ6Q6?2_skKt}2fV zy9J&qeGgBcYe#=&K0;>>-9>*VTt)wcT|{U7a?v@jI~;q@yv=@i!K?^gn7bfi=ZnMX z@KWb7`0vZz@N%;nHr)5-*zZWLOGGTZOO`PItOab8?WJYs#z(|DR+A(lY#MG33*@7) zpd=DD=ib8R4_}DrI1x_P!xnvYxNq6@hGXYeZDp|a(>mCux>m%_xf^Bhnqn<%o0kLI zWt@WTQ}@CS(Hht>Bp7y*1i{Yk$y!3!T61UEg&zpJOb6)Lxof`@?51~w*R{{X>l^0a z4Y#{tQLc}Oj+2dr&tdlzE7;@2XO5kF22Q}6VxGa99X`Nf?#L?SGJCB5%p z?~$XhPiq4#{g|(1bG}s-u&nVg?3aHAmRCf;isR)XI!2T^p0L0AG#rp@3I~c);2`BN z94t`5DmN33K1NhSE^x@=5WJ;h3EtZM3f@-ltfONjw50~#Ub+B>-7JB3WcI+}Mb%n1 z7m?5kN2Xndqx^L6&Zv{{E}QeP+A{%G&)pIcx}uF0aCB!O95Y}C$A;Dv@c2Bw5#QK^ zUjEmIZ!na{5n?b@YKgJIP+CCD*ms^KuJoTnzuU*fYe;;uh9t5bMfX0s6E#Fg4^;F( T8t*St%H+~`g+iu~$%X#_Z)Mmm literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Santarem b/testdata/zoneinfo/America/Santarem new file mode 100644 index 0000000000000000000000000000000000000000..f81d144206ac5bd2029d59beac0bb82801ebe67a GIT binary patch literal 409 zcmWHE%1kq2AP5+NDnJ+nLI`V-11e(yVxIp%Fl|+p2Z-LmAN~PM|MlAdqIZ6Dasbi0 z?ll>J=vx+h!2DZpIKcEB$@d39;&*nYgXQo3RtAgToBamNzkhcHnExQe5zPNGgBPs+ zD{Bsz|Ls5#SpGYo&IXV{w_u1wUu^oxv)nZLRG`0wkg7?ZHPPX8fpsyL2um`9VX52~Hq)eWG^T%m z47RWyge_jr!j_8;@QPsrY&G>2wr>BVpvQ>K&^Rn>7=u?{9)N92dtkd0MuCnI`-EnA zRdFBe;8O!TZodexwr}FuoRjwv*lDgBb}`R`T@1Tn*O_S8ty>MRd9LROE%$S7ut%2$ zUR(JaUe_px9C>;aj%uHUHRYXfbb|rrG9L5v7>OzE zg=3XB;B5)#;W&pgur{cNqhmz-r4o*}Z-(P%#R~R3VXg*F9ISwM7_#A{euDYr?g%*L zfd%r^^m>8NO1spFJUw;--dT4R-sSs^V|j+Y3f5V_g0sSAa6YT+qrmbU=ZA1k<1;vS zz60Jhj@&vZe2TpNfME6PLdKB9Af=e?;dcN z6qp9)TmIhj0Hn`K^I-xbGZQll9I`UA{{O$Pf`I`@CNQx4|9|`dBj^ABJ2x=!{{Meq m2csZJghAZLH-sVB1xUEM0C8{#gRX&zu>pf4ki`WgOt=8q(o)<2 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Sao_Paulo b/testdata/zoneinfo/America/Sao_Paulo new file mode 100644 index 0000000000000000000000000000000000000000..a16da2c4d5a980cd944d86c34ea8a2f597e39b71 GIT binary patch literal 952 zcmcJ}-%C?r9LMozR#LOHE+Q(_$A-vi+G%I$EHi7^Ty56!U~@(Y)zG>qqNpwcqmn=< z?3Z9S4_$vgW7q3dYIPf`F{QZuX@JWm)GV zJT?TE6y;&R%PaZ(ta7>bTCra-`xg7&z8mP3lWFuFw_WHvhb{D~Gr91t!7lXb z`XBJ_uD@_i*(kiH!-V&)`_7p>zVK_J#-c2c1k=9Plx;p2X|fo+5}pA*(TdpY$+ zM-JRLvH^}{O~aAi1-NM{0Y`5daI?{(%h%Y^);Q0y{kM;0jRhIAtaQq@)UrOjW6Ogf Rjg=~H`KZiZCBLgx`#+zs5jOw; literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Scoresbysund b/testdata/zoneinfo/America/Scoresbysund new file mode 100644 index 0000000000000000000000000000000000000000..fc1b11cbe876cabb53fc1d42db25b0aabd967fc0 GIT binary patch literal 984 zcmcJ}|4S2b9LMoH=V%OnxH5IMnblm=yv@69n%XwC8 zKg5U&Mi3S)ihc-NzpVN}?F$hkn!m(|$|x8WeIW{yijeC*ul)i3)aUrzi8+RHa-N`^$o!Ff&|U(4p_}LLW{`? zH*1WgC+FUu@_+%NZ%l?M!^-s{2dIjwx)3E-?1mvQ(ARm6okhzYb zEOdItp{wTtY^b~p8y&|AE)K&cV@f9Xn%?xIoBtj~w@mubn_maf?i&&48E=8!GwrZ- z)CAjNX4pQ`%#e9o{93dxYD90fd_;Hn7SVp~6gpsjiw=DI0Jmu#6`Xwvx96|H9hsX@ zn0X+R`Qo`Gx^wI*dS@bm?n<6Uckek1d*Xv|*QPj>gaGWV=!Co3+Je707%cNMWPb3) z3iRHE8g%IHPxQW=9^IE-4#U~6aR2Z;jHG7afk+PapZF}3c?VnXp$Eb<=xEhN^q?n$ zj_K~mbP-*w`5#Y_qI@|-QHqj(M-?l|kMFdOyeS>|GrB|&CCbJ*)Xh_M97pNhYIz;% VoATNtL@*F-n{XgVtt$P3f literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Shiprock b/testdata/zoneinfo/America/Shiprock new file mode 100644 index 0000000000000000000000000000000000000000..09e54e5c7c5bb2384e37626d4b985cfad29ed29b GIT binary patch literal 1042 zcmb`_OH30{6b9hiQfNDlGAban#Rn**we|%SS|6acqQ*voHJ}Sk6CS~hsIkU{I!e{B zFiez%O28Hf(HOPFji!l0jK;*rqHaVJL^moLW7LF7q2s-O)GZtDITiC{kFCT$_~lcinouj~eRN)v*ol1BtKpZeGUPrs^%XP$WA z^j$YBUo)`JBjl1^U`cT<%@R=_oq;nB>O^K$us~utvvyi!IjcGatLEg)8Y;y8vQxL= zqFpjvy#EY&1)-G5r>Wi8}n}UAzZg-}wcu>OKiqA9w+82zQIDv2jNX-qd&;_S!DMKJPx*_v4YE zRQ!1|RR7Aqt^bl`xu=WJ-}y#Fp`x`!G^lyJh3)z%dAeT N-QssRtPZQ4`wbnj4)_27 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Sitka b/testdata/zoneinfo/America/Sitka new file mode 100644 index 0000000000000000000000000000000000000000..36681ed78eaf0b46f8d142884cf7ae8903a18907 GIT binary patch literal 956 zcmb8t%TE(g6bA6yQaYWXYL%k3fQ|)PT56fL7N{>Q6p3PEO{)fXBt(M?t&$jx(O5N6 z5+6g{*bvRILKB6FE|i#vVPhg{VqF+xd~Q_Y!uZ+{81MQ10EuUE?zz8vzsYPSyQgn& zgw0zfo}i}6&i_h=$3)&9gIDY1>kC5P%&I=A%rG@7M5B-ok|VL|x@3m4mA(eWG>Z%@cP&ZO@;T=roM z_x9J%9CW_m(IC8Vd<sSp2psJ^4X?>K;h3)%Zi@VYn}yAAOI5kdc(r`4hvPH9;kAz? zc-@;<@Os^=Q*Oh9ad@L@gIkA&;7tdo;l$Z{8jrEI?N8zM-U6I#9ECfQ$Kj5j9~G0i z#9}V}*JHH_|MxIf9AV5b@;+KGpJEonxTczHSnXK(Z=TOFC*7J{*jH~$Wm!7IdpGYi i?_`#Bb0@m^Ceg)r60LD^Fcl3&LP{_d4u`@aMfwXhr^v7X literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/St_Barthelemy b/testdata/zoneinfo/America/St_Barthelemy new file mode 100644 index 0000000000000000000000000000000000000000..f4fe59034242c4416bc84f06f38530d625149329 GIT binary patch literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~+1z*yf literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/St_Johns b/testdata/zoneinfo/America/St_Johns new file mode 100644 index 0000000000000000000000000000000000000000..94d790baaccb72298bb577041cf3c8400339a7da GIT binary patch literal 1878 zcmbW%e^AqP7zgl;A7duvm!mrvpsq3BxPM+Q2^!F4fX{}t+DbGN?phBZp!+T zdu^15WS(rw!v`a`QGQds05@pn;cwMr@R9Ay(0^3k1ve(&gY~h8;qO+A!c9KaaMOJg zd~CcJZoaI8zrV1jm%d{#Rlz?rtKpU-+HF)nUXu>De)s|WW2pc>QCtL{RPx}qbUAEH zn1tK;e7Iw&e>UCI8JKEAx^KciO~t~dp$o8Ct9+Zz&3&9k%2Ou{5tLmVN1#ke9r5*fa*QbLvYWv18^^^4IYSbmDBk^ zq1{3`xL0nayqM*!pd5OW4-dy*hc79(u+{%8JQC-GM<(>}Xt1A(=0*q3SSW2{8u+rl z6z5~+t?=*ra^Wjl8GN-w3}35^g8#@2g~wlAfUgVOustKfO84Ff3ARu=_;avhdIolK zY_PL`2)=1I!;>v-@SolF@L#9Q3YwoXm{gRvboKCbtq#8Z{vLRytO|C$riR_QJK)(( z>F}MzH2AKd$U^tr3yg#3xN>;z?q)01=N)`_!MX~*Z{flZjDE1^sMA8fGuG!5Rtok< zy|7osdDy#rLP2$(LWhddH}5>mN$G+8M9nZa`WWmVR15Q1pTfLb@4}Bfq>|eJ<*MvZ_c;x$>nJIOeVLi{#jK zpTVoL3dhO(@SSkn>Qp%H!F~gi61Wuc&a8X~z8X@L0 z1`FWKB|&gz>qa=ZvX%Q literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/St_Kitts b/testdata/zoneinfo/America/St_Kitts new file mode 100644 index 0000000000000000000000000000000000000000..6170b6c09d7a4412e94c146246fbba418b3331a0 GIT binary patch literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~+1%s|0Yp!Fc6;1C8bAYsA<07Y;fvH$=8 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/St_Thomas b/testdata/zoneinfo/America/St_Thomas new file mode 100644 index 0000000000000000000000000000000000000000..0e62d30bb5d9e1a6c13b3a45323605828c8d9deb GIT binary patch literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@r!u^N;TlOL2ZM|MjyEVE&tHm%;qE$1Z{S?N={&6WMXCk z5~z^%|NmJp7=W5qFJNT(|9|cT1`aTr2TTGDUA=%o#K$*;!Pf6Bn2m!SMh8bv6tP|NrmYz{v9d|LO${96r7w49+e<92~;H1tiS4 E0FH_xivR!s literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Thule b/testdata/zoneinfo/America/Thule new file mode 100644 index 0000000000000000000000000000000000000000..f38dc56bf20d9db68515ea7602c9edb39fabae8d GIT binary patch literal 455 zcmWHE%1kq2AP5+NDnJ+nLI`V70xDw$VxIp%FuS4r4@jT-*Qy5~TH|T#1rV)yHRb_` z);ekr=4r5lu6x;8#LijK~mh#jk-L?dRDa;5gI!=CiMReD?L(`{~xc zCNn)!y63p*4Y9=7?|o#yUK_8kDP#JqAIcdJSyEG^h}`kRWm)7m`Q|o}rC(LWi`-f4 zsfpZ`T8YcHyn=U!fJ!V)-mwF<`}egMLxO{@znI`upze!~2~U{B75# z_`A>jv7;I)Z%KeUadNt8M8Gjz1N^QlbgB$Ug=n8yRD#hmlKf#?* zTV-*s(^amB>Q}=Eh+P@IbZ^*}C z9d=o-N#P}#*nDsSw&XsItwqytL`H@tdXei#a8yz}Pdf|odk6w!OU?mhfO;c*6{=d6pW6okp(%)B2ZXWtu@_^*UcOR~P&)DozVuHS2 f(ASIlT4|RII->Q>Fk6&4(rgX0MMRh*%vQs{dz=-7 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Tijuana b/testdata/zoneinfo/America/Tijuana new file mode 100644 index 0000000000000000000000000000000000000000..0d8c993bd1cf2fa2cbf002421ec9c0fb2b29645b GIT binary patch literal 1367 zcmc)J$xo9(9LDi!Sqf!)WfxE@pruesTehMivS?)sAQi=fTM&bZ0Yr&h5EK)MK?-Q1 zF<{l0NKh6rh(Qr9L}T3QK@dbl1cL0MtWswl{s4|nGw-*bd4KPFX{tGpk**}GE*_m= zn=Q@ij}*}{Q@WiEblqzj&SI_3OF-+ULJF9h($nB4t{h=*7EVvHz8)#TeZ9vF?&~XS zasJ6Q6?2_skKt}2fV zy9J&qeGgBcYe#=&K0;>>-9>*VTt)wcT|{U7a?v@jI~;q@yv=@i!K?^gn7bfi=ZnMX z@KWb7`0vZz@N%;nHr)5-*zZWLOGGTZOO`PItOab8?WJYs#z(|DR+A(lY#MG33*@7) zpd=DD=ib8R4_}DrI1x_P!xnvYxNq6@hGXYeZDp|a(>mCux>m%_xf^Bhnqn<%o0kLI zWt@WTQ}@CS(Hht>Bp7y*1i{Yk$y!3!T61UEg&zpJOb6)Lxof`@?51~w*R{{X>l^0a z4Y#{tQLc}Oj+2dr&tdlzE7;@2XO5kF22Q}6VxGa99X`Nf?#L?SGJCB5%p z?~$XhPiq4#{g|(1bG}s-u&nVg?3aHAmRCf;isR)XI!2T^p0L0AG#rp@3I~c);2`BN z94t`5DmN33K1NhSE^x@=5WJ;h3EtZM3f@-ltfONjw50~#Ub+B>-7JB3WcI+}Mb%n1 z7m?5kN2Xndqx^L6&Zv{{E}QeP+A{%G&)pIcx}uF0aCB!O95Y}C$A;Dv@c2Bw5#QK^ zUjEmIZ!na{5n?b@YKgJIP+CCD*ms^KuJoTnzuU*fYe;;uh9t5bMfX0s6E#Fg4^;F( T8t*St%H+~`g+iu~$%X#_Z)Mmm literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Toronto b/testdata/zoneinfo/America/Toronto new file mode 100644 index 0000000000000000000000000000000000000000..668e70d765dc3fb0eda16fb0f1932af607b53412 GIT binary patch literal 1717 zcmb`{|5Fro9LMnm5$Qky5i`X?O^-vkJ0Sc57Nj6yU05BHTItph4D|y$R){l(eIbcv z8YZEfvcXUkQ0oLegCM>r5lu6x;8#LijK~mh#jk-L?dRDa;5gI!=CiMReD?L(`{~xc zCNn)!y63p*4Y9=7?|o#yUK_8kDP#JqAIcdJSyEG^h}`kRWm)7m`Q|o}rC(LWi`-f4 zsfpZ`T8YcHyn=U!fJ!V)-mwF<`}egMLxO{@znI`upze!~2~U{B75# z_`A>jv7;I)Z%KeUadNt8M8Gjz1N^QlbgB$Ug=n8yRD#hmlKf#?* zTV-*s(^amB>Q}=Eh+P@IbZ^*}C z9d=o-N#P}#*nDsSw&XsItwqytL`H@tdXei#a8yz}Pdf|odk6w!OU?mhfO;c*6{=d6pW6okp(%)B2ZXWtu@_^*UcOR~P&)DozVuHS2 f(ASIlT4|RII->Q>Fk6&4(rgX0MMRh*%vQs{dz=-7 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Tortola b/testdata/zoneinfo/America/Tortola new file mode 100644 index 0000000000000000000000000000000000000000..a0a5d6021a529acb30c17e90aa58f31e519386a0 GIT binary patch literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@r$_#oZhw7zgm<&LSsSB-II7i`K6DC5aemGRRVTp){q@OoNo_jhHl(>EcMu)HH1; zy~)(LjA=$AhBv0B)Y$D}(Iyo;i(Jb!r{C}U4|v&g<~h&#JoEki-W>Jeg8X1+%`zhi z+O*VbAE_WQE7C3^sodDoaXK}v?E;+-+oU|5Z>l_Ct@m6JwKmU}rBhex#L@X7-WL9t zH4T5_Oz`J09o)yfh4s?suzsik?qBT{==p(89v(Ebz+dX0@pNzKxC4K!x(N?y&cojd zis0e09Qb?60r*F54E$3b3Xdco;^;l2&KWG7Mp-m$oC$$VHlDCaD}~2KR^jpHd3d6G z2>w;0hbJ3X1bWX@aT`2cZGdMkb@6mRTi6ND9eE7@POF3e#9e{sgDT+#zdD>>bjpX9 zY%AfVh07ehXW5t!uk@XO|GwG_ueK(`;uC+C{$J*f)r8|64`%Z^oS(^uUs-CfI(c5q8k`unZ~3&Kh{#i$>U~zJa5A_FfIV zzKVyPFP6X?3eLbTIa#nYMGd<~MZj+IaM;}|lV?b6v~!0&%)?-hnNWf5Hx0YNo?2IU zbJrrgrFj9~`e*>=N&`3&XSP+e!(Q2ru=lBcmhOGRCgJV-Uc$c8URdU@fn}=`0*Ntl zNjWSxyodcw$KZgDW;jq+#?#ymO)acwISL1ror9IN39#zqEsn&P;1VA=B>5~HnrRJ( z$+F?_U?Uu16A4FpTCwC96FKSuM=g)S(cLR>%)o1SXOp`?VoYq?Q+QYP5*&B`2E4m) z5RR{`=V>k>tpnb3{2H7XB*00Dr{Sbo9cON4ZedAY|LqaQ>$e$36d&+rmZDf)&e-DH o0dIDHs+vhpB%Mk6An9~9BO!<+%fQqSMX*8{n5t4KR0^f!AM7IBd;kCd literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Virgin b/testdata/zoneinfo/America/Virgin new file mode 100644 index 0000000000000000000000000000000000000000..0e62d30bb5d9e1a6c13b3a45323605828c8d9deb GIT binary patch literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@r!u^%@K_2GX?Df=~rmMBNdFW)5G23*t*VSxxViZb|bXYef6Go5` zj-D^(Lp;cM)!Uz6v+Zzkr)3RT9t~)p2-Dls!d&2i4yw}nZhxZ1q!#0Bix7yCYtv`|i)tJ3@5by2DY1ol>8g|4+ z;I^f9c;9GDqB?WF?Ztc7mB?8Q>`Nu#u6rr?@WM3g4}XBW<0J5qz%%%0)c;K`qiGVK=v2=PUB+H<4AEO&O=VGV7#8^a@&(EwFXD#1ZsnaDgpN+;tbCAZ(O&4yua8tS{ J6|`9t{{Yyp^R)l~ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Winnipeg b/testdata/zoneinfo/America/Winnipeg new file mode 100644 index 0000000000000000000000000000000000000000..7e646d18e18851bfde743b379e52df4ec5b5a20f GIT binary patch literal 1294 zcmciBZ!FYt0LSs~`O}?4B&X{LQQZ!myYnZ1OJT+`;uO_dnv$NlRLleVwQTVyQY*W4 z(LBi7!mRn%q?p;t8W*|fx+IxDC2aZEUBB<=*K^PM-oC%r_x=6-dGg(rRSorZZ6vxUrEG!rn{qRH z$afj{hqCRkuP?ty=>7NUXVJqM!{`z30rZEER`e)oL>ojkXoIN=Jx2KGvHsKOapQf4 ze(zI5rG{$kDn@^5NvPk#h7xA{ZM6AyZPggkHryjx~yRrC{DUzRX*VUukSZBsYkmY8|SR~Vtd`yI4% z?uJ6r%(?Iw+MBAOgW)Bi!?F7sdTV^#BFR5cN@5z1}`BnQb= Oaz#M0QYlx;6~e!?Qp8jM literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Yakutat b/testdata/zoneinfo/America/Yakutat new file mode 100644 index 0000000000000000000000000000000000000000..773feba89d36ffab4baf105b8f0ae69584a74014 GIT binary patch literal 946 zcmb8u%TE(g6bA6yQabI3TBQgrh$D}dLLH_9rL8Y4v>L@mNJkCsszieetuZkgqoHb| zB)$?i5)v48n5dcPLWu%~jftp%2VeflxmQ-^SoYA4YLs z@OoNeycRzigqMtr!b@*F#JsC-5MI_h053n0gA2QRV0Y&}xM=HMcttD;7Y7n>Nkv9y zygW`H?6tPS-a5C7&b{AT49e0^)jDO_R295(LV(Nf*x^+}Ut#H3Org2exkmlt(D#?}lB!SdZh zaQ*4CuyU;(4js@Hnp2OeaKn}}aAVpHhy7h}llmKu2%F((S)s&uML*ZTvDshn+Q%Zi zZu%9x-tZYTx8cDEyz#07Ztm}gHyxgVEd3s93Cd zHf#Prmtg;>3e*xk7GY)@&dGtGN9?{?k^jm6ur a@l!G0meykAV5&h@WhIyjh2)T|h<^cFp~tQO literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/America/Yellowknife b/testdata/zoneinfo/America/Yellowknife new file mode 100644 index 0000000000000000000000000000000000000000..645ee9453073acf4cff9f9420b358a8ebbe40f93 GIT binary patch literal 970 zcmbW#TSydP6bJBcZFP62EvItLOV+04w%a!D#ZB#MwVM?!iH?N5gkXxkBn3ea)s!n_ zFHJ>Ih&Jn`j6jWEiiOmqpqmdH1$No29t?|!3JMIT@BE+kP3RlWobx;1IWP|+A82au zu{n={Pf*a2=U%DhW2rncbbihz#wRIv-5pdZUyGR(%G#9+uoiEFyU%@wdm?F!?t7b` zz13<-HQ2m!LJsYi`QkL|FY&2=3d#~(&sZ{UA9U& zweqh*IjwvKHhB`T+5Qf;h$FDThGF4*H#~nb3R@?J`8Hzdvo33$V!Z}7%9F?iFEpi;3p)(LMp{}tZaaSAR!JPvP*bSTu= zzHbQLQGWss7F~ox!Gmz<=R+~Yko3$mCL#IaKWbgStTFzZ-qH+4UGG$x8MPH}ac@{= g;UJG{9{YJz%1q!W;Z1kgFZm>oJM8sJUdbc;1G${^$p8QV literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Antarctica/Casey b/testdata/zoneinfo/Antarctica/Casey new file mode 100644 index 0000000000000000000000000000000000000000..84f1c61e5c7c35090fd2e628e307cff72389fb02 GIT binary patch literal 287 zcmWHE%1kq2AP5+NDnJ+nLI`US1S(?&VxIp%@K5ec1CY(&b&E{_M0@w2`T(N+R?blX z(f-b7CxGY(F6#ym9kqmC07OUc6mbC2F}<=4AUbxMs{x3POFjys7~(4y*nsE+pX~u4 zIx(UN%umvp3FaqTq=5M;92*%Jnb06e0|*o}Ft9K%%-X=fp=)5kplx8mplxW#z-0qu J+38wv0RS#AC%FIs literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Antarctica/Davis b/testdata/zoneinfo/Antarctica/Davis new file mode 100644 index 0000000000000000000000000000000000000000..3ec32224f2982db46a19d1a159f9017286fd1413 GIT binary patch literal 197 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I*VxIp%@O+K~1Bm|SeqR7Y|8rjrGKRtHmWTm} z_MZOB0Yv+)Tm|O)JAXgG$iT=1gdkxMNGf1pVPJ3zVBpX-FksL&Fb85&1}+;Q%TCvv F3jndjA(sFE literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Antarctica/DumontDUrville b/testdata/zoneinfo/Antarctica/DumontDUrville new file mode 100644 index 0000000000000000000000000000000000000000..c0cfc85a29e833d02896066e54126317826ed90f GIT binary patch literal 152 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9$VvhenaAi+f1Bkw7l8^wRpW84sFv3k^=vlzP VqHAElplxWtz-0p@?Q{(dxBwv_8BzcM literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Antarctica/Macquarie b/testdata/zoneinfo/Antarctica/Macquarie new file mode 100644 index 0000000000000000000000000000000000000000..99a8e60edffca85f5caf8eda9d05d85a4978e665 GIT binary patch literal 976 zcmcK1-Ahw(9LMqR*&O1W+7r{%t+aA#dpJjJ&eWOa%m+q6L(=jADsvY>7by}o4p^QW zy(uBdKr6W(_M4Q66TKlI7$<7pRqT$$?RUNLo}H|K}oRx||Ti!E@w zcT(naJCSmJJW=y~nGqBVL%OQxP=BLL=1oFMHrjA53vF2Uz(iME^J6AVO8chyatj*& z%)#WbgT!O{^cALrHeu@PS(w)T1@0Mn3ious zT#h!+5Wyl=l_byyeW7;f-YQIKp&sFg|<(G(T?FuXy=fEcHQ)%#p^+| z)Yb}%ng?*dxUvFW;_gPDuvpPbbv}bW>oBY{G~xR*i7zxawD(&7{Q}(1A=F}UH||9 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Antarctica/Mawson b/testdata/zoneinfo/Antarctica/Mawson new file mode 100644 index 0000000000000000000000000000000000000000..05e4c6c5867330a5af95cd6816ade311a0cac82d GIT binary patch literal 152 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%@JPX^0mx?Xx~1g62$BJVkOT%61_rkP Y1`b^V0|spaGaxo);IaXdcDklq0BGzFF8}}l literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Antarctica/McMurdo b/testdata/zoneinfo/Antarctica/McMurdo new file mode 100644 index 0000000000000000000000000000000000000000..ea1f8f8a7797921488d015ecc6dbf72a81b7d3c1 GIT binary patch literal 768 zcmbu$ODF_!0LStFc-1a;S&}@~YrWR)?CfH_*K5674mN3%=EAn*t-+%vcx;&j0^5-~ugS~9dzkjjQYyR|AebZep z-Ll_^BKlK;EAvqKI4`mep8i0GobABS{&T3>nuF?gFASR+hT*nZsOfXV2<;GzY^{_1 z>V#4GS+X~SBB6^;s+HaEfH9n2cA*BwUWCB7kxUrxeSlhbFie>7!Nlr&m^82klLduD z=u$jKP^Z3wsXQmrW0K}qfld#-5^0k3OP$2bxZe|*nY%#}Q-8Q1GP9ObpkZ|s8pi@5 zKi&;ZT{lqZaX@qZ0kpJuBtn<1UqDRakMqch_=2g!Mry$%s&}}1*gxjaJ>f> zZL35=S3J>#E}4Ep+j`CD(*9#~Sz9A4Z{L6w#R9CfO+tH|23BeNWZz$5^_NTZ8IIAlB3}y!kpCI+ zBmdj)g!NvBBL7WsgS9G8b8hG^&+Q@%r^dEu?9|8!I4xQMr%$-xjCain=R0ns!#l^_ z@UD(EIP+Q-oOLlq@ZRo_5za1Ig>&k^z`1E3;XD^yE<8Ij6br~+W-3}i-bs83zt|}y}(Bp$`t!=Qqd{*$iL#czE36*eB z;v`%gJA-`}CBd#YX5=MbEgH!x9sUL%dX)&5^}L14AI!t<_A$7kI|3_#*Q$I*htEEO zJ@ygUTYU?zOzDGtg%1_EM!ugNaMiY(aMip~@O|}p9aNQ(f|HwoseDq}; z^7@7@jbt6`A4A^YnS+mCxDNX*OA6vx-&CjK*#u1{%X()F452D7ez{$$w7XEIxbAggf5w#&9re3?AC?eYHrq*~Sw literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Antarctica/Rothera b/testdata/zoneinfo/Antarctica/Rothera new file mode 100644 index 0000000000000000000000000000000000000000..ea49c00b2240fbd608425793b225d6e10a58ddef GIT binary patch literal 132 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;4v>0YCS91`|NpOEU|`WTFksL%FlOMg0g`sc FTmZ^O3BCXT literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Antarctica/South_Pole b/testdata/zoneinfo/Antarctica/South_Pole new file mode 100644 index 0000000000000000000000000000000000000000..ea1f8f8a7797921488d015ecc6dbf72a81b7d3c1 GIT binary patch literal 768 zcmbu$ODF_!0LStFc-1a;S&}@~YrWR)?CfH_*K5674mN3%=EAn*t-+%vcx;&j0^5-~ugS~9dzkjjQYyR|AebZep z-Ll_^BKlK;EAvqKI4`mep8i0GobABS{&T3>nuF?gFASR+hT*nZsOfXV2<;GzY^{_1 z>V#4GS+X~SBB6^;s+HaEfH9n2cA*BwUWCB7kxUrxeSlhbFie>7!Nlr&m^82klLduD z=u$jKP^Z3wsXQmrW0K}qfld#-5^0k3OP$2bxZe|*nY%#}Q-8Q1GP9ObpkZ|s8pi@5 zKi&;ZT{lqZaX@qZ0kpJuBtn<1UqDRakMqch_=2g!Mry$%s&}}1*gxjaJ>f> zZL35=S3J>#E}4Ep+j`CD(*9#~Sz9A4Z{L6w#R9CfO+tH|23BeNWZz$5^_NTZ8IIAlx3y{iEu m10xfd10<3P7=ZfR0vI@S4Gb8x4a|Yql!40zNZRR|asdFaJQ3vp literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Arctic/Longyearbyen b/testdata/zoneinfo/Arctic/Longyearbyen new file mode 100644 index 0000000000000000000000000000000000000000..dfc509570a5be7ea90f64610ad5ca5a58fa3d172 GIT binary patch literal 676 zcmbWy&nv@W90%}chGn5|ZMI=-Z1eSFKW!*+n&n{MlkY*IghcJM926IFaB%pNgQ7?d z6n0TAMk!L!FMhUW0LTA-e9xREawUGQ?o1h4!m7#Wnoct9`E z`R6S!^2>5NOw3u~>x2#_M;Z9mBY~;T6im0o;5!?I8FdJLFiC;#{j}vHegtbvG(lACkd_{V!NB=F8Bl+(kM6SfI^^#mdiWySi<#^)ubkoKYx!5cY8qJ*3+GMqxIftEU HbIN}KI)2g> literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Aden b/testdata/zoneinfo/Asia/Aden new file mode 100644 index 0000000000000000000000000000000000000000..ac571479d181c64527f34272b901498e885408f7 GIT binary patch literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iV#E72khD4?YU(yV2`z~bW@!k}$n%)n&> JB<*yKxd31}4BG$z literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Almaty b/testdata/zoneinfo/Asia/Almaty new file mode 100644 index 0000000000000000000000000000000000000000..02f047d70fc811f8cc17f2c08ddc1f328576fb94 GIT binary patch literal 618 zcmWHE%1kq2AP5+NDnJ+nLI`Uy0V-n!VuAlauu8J}4v5~m_`Ly0zo>fc0uU`Gu}J_# zi*syL0MkF8P5{voFP|&`(UP|%!SYgPGQoW5J!J<#;xcQ}!L;n02rwaOUl5sK}tH9HjJHgfB^`MigLlU zv26*MHVN_v)26avVA{;c5JLa80Mi!Iehv&kU~yLp%(wh)0Onim`2*%#-xdP%ZI(%b zY1>_2z_eZKZ!m2?>l&DLNWBZD9h*NLU;u*D2gei`nVGOa7VN?hrNCt1p#swH7Qn#5 oz>rkH$N@|f2@E_Sl99*9H-tgkz!Zqhf!K_J%Ld4^(>3J+0Kt`S8UO$Q literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Amman b/testdata/zoneinfo/Asia/Amman new file mode 100644 index 0000000000000000000000000000000000000000..a3f9dff57148554c4207d71df64851aee2b28b19 GIT binary patch literal 928 zcmcK3-%C?r9LMozm6>O=HWBnf&E>4+)XmMD<+7H}pIaN-Y3kH@bW_L+gSEhZ5oPoT z%!oil^2dctLA1K*_wJS#g;p13_8@^EN#I4GAnSQP`vbi4JI;CSz3+KAR}+0#`;27I zk+CQE#Yf!xNDF)H5W7?fHZLc>edgy5hi+1Csv_#*9?_U3xVehGkkU_i3!gHum#_at zE56^rK0RI_u{Ajw`G`I?oq|?|X3#maU(vZ^Y3RJjF8cTb>SD)8e&`ok-4jEfaDPA- zG$-G$3BE=b>fYo0N%J-IDfu{BE5A+&8|_*X&Y%AM7W<;bKJ0a`da*B#HlRyJ>d~cx zFVOmjK|F70ox<;B!8)|j8iS@&Sf^R3~e8{?F)sa(4Q&n~}{c%O^; z(Nzo2(3Xh^JU=`HtB1ny!c!-_81O>tz&}dZT(XB?jU@nUi$!R&>S3Lt0@kZlN&jTS zMxj(9Y#JAL&`ldkbaQkCZI5rE9gnx+<>@cb8U6v?3w{@2<0&6Qi|*%?_m#~1Xs_`J z+PganTQdfe{=5g{|SzyO#4eXrHgZ{gPuxq4BB5b72RLbqXohxyBvJ#XV x@Fk=JviNxI!35}VD#Zz9ndOhmA-dv%FP_z%)`uonOT literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Anadyr b/testdata/zoneinfo/Asia/Anadyr new file mode 100644 index 0000000000000000000000000000000000000000..551884d322bcd2201b4b9898ec765141277e6eee GIT binary patch literal 743 zcmWHE%1kq2AP5+NDnJ+nLI`Vd04ie#Vv+wquu4*P4v5~mxaR;+j6qag+5kk0N%$`S z(c&C_8^H9>iC}SwmlGU7e92o!z~WM8M8SONJxU26ahWy3U|Mz#3z(Mc{tBk$tDk{s zh3xBKS~2jRk{aEt8v$YX?2zr4;X+z{mV=+t?^{W2M}Mg z!T~~GsRoN{9mxUH+FN45w9XPgFs(bq9!%@C7=UU05=Ag=kRk-84P)&R7=Xa2ND@pN z+bV!*lfd6#+EkVaOq&_rh0uSVfN2Yz{tVCux)-U=Z-}4PnqWGy-B1AT|bK PLk2DzpopEWp%E7VnShFz literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Aqtau b/testdata/zoneinfo/Asia/Aqtau new file mode 100644 index 0000000000000000000000000000000000000000..3a40d1175a7d81d8a307d0e546a1fe9a40888b29 GIT binary patch literal 606 zcmWHE%1kq2AP5+NDnJ+nLI`UCnaBpj0{?+vmE@EMAbRWKzYah#1~G|q1|V9TW1|9? z{`q+Uh?aQyX#;4yNU6JixRFW`X}y-oU|PRq5?G%>N;8-?j9vGD0SJtWI>EHD?F2Aw z5|j<5O=XL~w3(4Fg#H@>rY)qi5*UEM;;tE(Z~5B?%(vPr0p?rZ)&uixmYITS+uZ_S z+OAC;Oxw@;1g0HQe}ZYp7QP3JOw24y=#Z5WBE-mw37Hre^c5I@z`}ung@M5>fPn*; l0umT_KqMoObPHhQ@bL{{&^9muVpAYCW8ks@vg~wCxd8kpZUg`T literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Aqtobe b/testdata/zoneinfo/Asia/Aqtobe new file mode 100644 index 0000000000000000000000000000000000000000..62c5840a83e29b4fcedba95e438581cec96b3cf6 GIT binary patch literal 615 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1}b9%VuAlauu8Ho14M6K{MP{}#vrQRy#YjvNgPlB z(c&B%A@tAB3qX8{m!H7$lDE~t;!;4yNU6JixR< zjwP5@jL`zqNFW`X}y-oU|PSV1xy>Hl!9r)*aa6r<{1@LgK1;i zCNOOh6bq(JWmCYknUOt&{_6&&Eu>=tK>951YJmBczwN+$tG!%czV&SdFyCgGI+(WI z%><_H+Bm_q{j4Wo+9CBdn09PoxWLH7%)-os4q1W1I3WXr=?t(l92i&_7~BFFIDknZ kfsqG9G5|@p07ecU-w+0E0}~)N1!6M>E*l`rPS=zR0Ohl6^Z)<= literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Ashgabat b/testdata/zoneinfo/Asia/Ashgabat new file mode 100644 index 0000000000000000000000000000000000000000..8482167269080ead3a6046ae5e64b56d48dac1dd GIT binary patch literal 375 zcmWHE%1kq2AP5+NDnJ+nLI`V-1S(?%VuAlauu8Jm1w?OM{MP{}#vrQRy#YjvNgPlB z(c&EY4Z!rz&kI1b#LG`$dCA-A3Lw7JnQ|~+dQZy*5MO3ZDVUa>lLn^cdcwi9e2oW~ zR>-jg(~2=#U|PvX8cZwO@PKI*?Z04JRr(#6R^z@8rqx-w13>1hfB6HZHJlLn^cdcwi9e2oW~ zR>-jg(~2=#U|PvX8cZwO@PKI*?Z04JRr(#6R^z@8rqx-w13>1hfB6HZHJrBL9J4mE`0A5WRH?cK}Ggn8Y~)5G~HJQ2|W< z{Ja1}OT7HF0YppQR#yPgQfJD+eCa(c7eIWOHKkx$c1{|Ymg@-z)ABVQU|J!^5=<+` zXn|=ZA89bHY{LVlRkZ(tX;tZWU|Nm)KA2W#g}6)o%bx&{JsMAbCxB?pip3E6$~~~S z){*mIT6@a@Fs-v>Bbe5mvItD;wM+)n`Xw!3+90JAOdG~7xBxQGsHhrD8{0O4X_KH> zFl{QE0;bK3>>>1DH!y7>odvev;;z{PkbcYGK48ApUI{SY`nDdJZ?nu4Oxx}j0MmAD z;$Yf-)+aFSkopr$JGSsWU}R!uVM2$jY-mEPY;efLz+kX}0SL4V7+4q>+yWRlfGHq> qfd@n~0!g<3Mxcm=1A~B%ZwQ07fiV!902``6pQ1;;9XoZ+Wc_%(pt052mfRZvu}W9GF=if^@8r`Drk!msg2i2Q4}ob{c~-Ev8{aoD?apA)z{tc*1_XxL r5|9y^3qY~1Wx&9}z+mCP$m8Q1!r%nN+6KlzY{I~017z9h8gl^v?09_azn&(byN03#DniGB`< pYiI#dYT>}Z#lWCtz`*C@8^WM%U~FsvBuzjp1}+;QX{T$<1pqkL7mWY_ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Baku b/testdata/zoneinfo/Asia/Baku new file mode 100644 index 0000000000000000000000000000000000000000..96203d7a4266cd8646032165950374761090e318 GIT binary patch literal 744 zcmajbPbh<_~*^Jkf1m?@zh5L!aqmRA1cAc`Es*+Gan z8Rg(OE9Kx%N=b@vlJX~hzmMz6_v!b%p7-zhJ(tJbG0>+c{|-k_u*Jsx|0gzjOh8xs z51kF!ay9eeO6+3aC#Y7AnTgV{jwy*gwZac>hbes|$4uF^3Gb6a(`fnO;w{@x-kgMr zwK147*9%kq9+>8{!}Lxw%y6oq(vk!-wIY}$|AN_~XQ&d$yo8SGO$c-DV}@C)&p%-9 z$rCK-x{PQ0`q6!8DBEI5j4iX!q*#E3`oTZHN1$0g6JQVKn^tu3XFs~+$b>GvcAzcm z&9E$}h2=8_Sg{%ht$hiwa!Nzk*lOOa0t2P1P&9RuDwnm1k)C%LT0C?fn@( zfR4LmSiijnouS9Jizgy zB3yiqA7MAr$tWHn`G;F@{+f?L0kr@Gtpqa^q!0jAim6+NH8rs#|uo$^;m;x`5GNC zt&k%NrWIrOz_gP0e=x0V{Q*p?Xg>tgs?wLhv>NweFs;t=-T-92`j-b_TI0!m2M}Mg zq8&nCIRqBhI?eA55FdhJk4_BSQ%N*8)siNc%Z30D;9_DKOviw*i=MwdW6*Z+%+` z%(q!438rm#eF4*Ut-ryv{j6(X+9CBWn09RbbbtW}oLu*V`Oe8#z19jT{J7&RoYEW^VX=*WQJTkE9sG%I8GKs%0X}{8qaQb{gX5oOa6*2E z{X~pI|23I}PX>MPsmL_=ZMOuRzB)qxebE&a-bN(H0~}4MaRHp&Cgv&UKxb)M)Q(yM92Uf<0;8p%8 z_RE9Y@D)BWeC19EzG}V!zWTrfukO7EYsLrRwT)@?YnpDrx>7Z~UKK}Q|J4I;AX8vN zI1g+LgwZ!0UZZdJU4boYTj07mFPIsb2V46uv2Sy4V&C4p0j@XCf*q7P$0fM|)APZoe^$=i}(d8sp*V7~O8vI8J-nKkKPT6RtZn3n7D1k>_0R$y8o zM;lBl#>jwaB_Ccet!(`dOsi^GRN*OCe5>$lwn^9@qG!FkH;vNQZiWLEFF-h|Pi6jDgDrNZRR|aRC5N?`;DB literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Brunei b/testdata/zoneinfo/Asia/Brunei new file mode 100644 index 0000000000000000000000000000000000000000..e67b411b9f5af9cf6b85aa51051f76b57d972afa GIT binary patch literal 154 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$V!r=Cu(pfI1w`*kckf^X%4F{WnUYz-z{0># c(7?du;~T=DZD4L}03(S^=Ujl?csXWMXCkLI#GQ8z3u#E-C-|Z~>XRrdGxVTmbC&IB@^~ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Chita b/testdata/zoneinfo/Asia/Chita new file mode 100644 index 0000000000000000000000000000000000000000..9d49cd35cd5e52c5ff0f2c0cc6bd3f4f6e856915 GIT binary patch literal 750 zcmajXNhpM29LMqJHG>K1y;#RGmN6L17)vu4+h8&?A|^sgS+XUGP?EA9Ce4AA97eX1 zTr3CNP)N#h!ai<|e%S zx3K1KKJ4Vy!XaH}K8o^A($|0dj`Wj^y}*y%I@14f2mb@EpYEswPqWd|J+qBEXiW!$ z=MrFuH57&p@KDyy!LXWF7;bXFh>R;3sXT;o={Ah=T!9MlB~SAeZwD~?eqTl%)7R$o zY8l^S4`!fpa{|UK_QUw8R+unS0~5Q=P}QJ=Nwv*3ny2p4!(^Qirj*HHYH%D(Q@cC; z@`f5|Bv1D=w=ZbzryDwb?*g51{eaF~dWO246PPu64zp+1U{2!(%pE?m(Y(BZX|%q6 z6`e2dMHlF;=t9>jv>~DcZFuT|MWRxtXO+c$!~4DMedM$CRw%{Y=J* zT>f~(e}Ddc)Rhx4)>=o?I)|8;F{_=EFg9poUbJ(PPu>d literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Choibalsan b/testdata/zoneinfo/Asia/Choibalsan new file mode 100644 index 0000000000000000000000000000000000000000..6f5d3a15abbe48b8a4dc72aadc88c416160a56a6 GIT binary patch literal 594 zcmWHE%1kq2AP5+NDnJ+nLI`UCnaBdf0{?-a?eaSxkUoCyI}<>(#LE*6AX@U)pAR5f z>Wps#h?d@CPynK3*625YXxTYJV7^?BAeb*-{RPZd$o>rGD@I=f^Od}>g89nUJHUJu z?d@Q`s`M-{UyXYvn6J*V?E?c4sDIf8q8K!u%mDK>ugn1RwT@JQ`Py5mz0jC zFyB=+P=EmlLPckR`C+Vy1t5Od*BUTC{Hb#RBQq0;kbxn^1Y}B50Vqc6CNOd^FcdT} a@c8(KFlZZ?1F38EKFU(^7i7gn--0MRERr?p`IRaYgj{57BbVE%QR{b2qL zwzL9}IX7iLfz{u1toZ$;V7>;sJD9I=$w7dL5f5ZwD7+3bpl$*q3j;$z0|SSTZwQ04 P3lIl~FmM40T?;M%d{}{0 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Chungking b/testdata/zoneinfo/Asia/Chungking new file mode 100644 index 0000000000000000000000000000000000000000..d6b66984a2f36ae36b35e174756707aa7286c292 GIT binary patch literal 393 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%P-o_>38EKFU(^7i7gn--0MRERr?p`IRaYgj{57BbVE%QR{b2qL zwzL9}IX7iLfz{u1toZ$;V7>;sJD9I=$w7dL5f5ZwD7+3bpl$*q3j;$z0|SSTZwQ04 P3lIl~FmM40T?;M%d{}{0 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Colombo b/testdata/zoneinfo/Asia/Colombo new file mode 100644 index 0000000000000000000000000000000000000000..3eeb1b72b68993e26a2452afe98a6420ac66bafb GIT binary patch literal 247 zcmWHE%1kq2AP5+NDnJ+nLI`W&04ie#Vu}Ai5Vmcm3W#o>yH^H8pN^8z0MTcrYA*oM zmr5HfK;{}QW6%K6MuiLtAlk+Ll?EddGYbNQNXZ@cHAR)FZc zD=y6dnd@bJL;ys4+uWGI$i&RV!pZ`)>a|SLOps1a$85aQihB7n& literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Damascus b/testdata/zoneinfo/Asia/Damascus new file mode 100644 index 0000000000000000000000000000000000000000..bd1624de5148d5670e4585dfcb445d8b270c02df GIT binary patch literal 1234 zcmc)K>q}E%90%}cQ`6?Wjik(&D_xpvI_H{|b6UEVHfwE1@$Qz8nFyA?$kd!~yipX` zi^w#}bXr7YM39Ui%CHC}sGt!{NxINw&KtALp6B}y__E(P=XXBm`#o%fF|MfUxRR_n zJlbFf8*c4K8feXz9$~9=Zg}pTVf$ulqK)nTvff&@Z&}0O0c{IBm@x<2#a4Jo@)jQU zZ+5f(>_rn{+f#fE`CMHb^7+(r@Iu~Qcrl7Ye@Q)s{?e)%_6C1|y;Gy`viBhT`{^${ z|Ht_nUKyx||2l|`z29n^-Oau?=~H3xDxJ0Lg5OeUW7{V?7`dyw__Z?e($G@fo_H-f7R(GR&@hdk790r{r+=Wv9x z2HyNW2aa@jU~yhF9Mv@gOY~>qt(_5WcCk%U4@Xz`!7<7wHg-cQ)uF#VJPVHXi-lts zi(ND(ai1?4+1@c7X<*H{1XdbV zaI$t9RwbQ4f0y_ftQPekPvKv65jrVz6UcYZM8SLBaq!+TvxViUkJ{1K*xQh&T^U8L z?Rbnlz2PVFjOuiFUr8Oj-*6iJ%rratS@J>TI?)PzK&VEpkJrNb1vB#Oz*CciPWG#1 zB?$PYc-h}@Q&ksiR$YfV)8HhbleeK2&R2H8 z`STTUf#@V$@Ug{3=oESkaFN3b7r#k>OL{Zm(veWOtXT?|_sEU(F=8q8hpmkv@G;F- zxT0v*$mji^mk<4!2GGw&;uSplhq6UN*0XC8WXR=+PG@E(j>r_rM4+K(tvp%q4=F%M A`Tzg` literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Dhaka b/testdata/zoneinfo/Asia/Dhaka new file mode 100644 index 0000000000000000000000000000000000000000..28136808b6d1029676448d8711265d8c55cb4bae GIT binary patch literal 231 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I&VwwLyklEI@2SlH`-L?TlpJ6SO0Mk>AR)FZc zD=y6dnd@bJL;ys4+uWGI$i&RV!pZ`)>a|SLOps1a$85aQihB7n& literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Dili b/testdata/zoneinfo/Asia/Dili new file mode 100644 index 0000000000000000000000000000000000000000..22e705ca1ab1218e9f36b9f4f607258389853c8b GIT binary patch literal 170 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V-n#VxIp%FzJ~b1BgC7)93?8Kldwx0uXI^cqRiQ o6C)D?L+Kt6zo3BusIP7U1BZ`q2!pnP1rS>@aM=J!J6%gI07p<6j{pDw literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Dubai b/testdata/zoneinfo/Asia/Dubai new file mode 100644 index 0000000000000000000000000000000000000000..58d75bc26eec90272e97696f40483eb56c2b8b45 GIT binary patch literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iWg@YBo{Kmp?$Ak7vI3@kprAq?6ECJbCQ KK+;avgbM(ceGa|= literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Dushanbe b/testdata/zoneinfo/Asia/Dushanbe new file mode 100644 index 0000000000000000000000000000000000000000..d83fb076a256817ca0a3ec4e43c7768e6680dc84 GIT binary patch literal 366 zcmWHE%1kq2AP5+NDnJ+nLI`V-04iezVuAlauu8JI0Yq)mroXeXvy1>V0o!CnP9&3p0WcVahWygU|M!g1eliV@dVTIHCA9+ zAx9fbE5^uxX(bFfb$)FmeFHC4qqlL^AUD_=YfO8<+yIIS`vMaM=KPcDklq00pK! AfdBvi literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Famagusta b/testdata/zoneinfo/Asia/Famagusta new file mode 100644 index 0000000000000000000000000000000000000000..cc44179564afe36db0f1f7aab0a19cbc3e4fa4d0 GIT binary patch literal 940 zcmb``OHUI~7>DswY8SL1MbwH@E?N;@hjbY+a`V$uJW0>St`>?dzp(9{rBz z1qlJR4s^nW7qjq|h>rb5O0mwjv#s(Qc$;Gu&$kz)VViLhw*4M~cPtLW#a}MNJKtV{ zg%=5p@v%=2>C}?@F}O6@2bbMG0++{w@UF8icz4JNJ6iJKJ)#A!5SHP+mJD2JvV<9* z$`x}jwdzL(cFr%su6Li|>SuGXn0^YoC!WBb#9g@N`Zz2_2jJRsGdknrRqkk1xizIz z>)hAi`jV?~gZGw|?l)uy(MDk+MQ&WU0Q>&kfSX?W;pVTW;FgEy(bnfp=>Cy5^uRqk zdNAfd+Y&x2op-3+1pA``e7NEl9Pnr1cGE{V==cT)mw%#1jkD{W`+y!>oJ5b$JVHaC zUZ?1MWh@DIOh14-`}^T=atJ=rGm4&!_o0z}aa0Wj(JosD+ATWQ`$s~1v_Xx|KfO|A z%`yD{k1>a_vU&Oimt^4o3VS)rr8UbBDJlyDBJ`!QYDs2hzHoc#mZ->{dXH2ii%PA8 HRh@YavF)T6 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Gaza b/testdata/zoneinfo/Asia/Gaza new file mode 100644 index 0000000000000000000000000000000000000000..0d79662716b445f61e5577bdb09e7c91e4a40d28 GIT binary patch literal 2950 zcmdtjdpy-=90%~nbQwx(U1t)hq}+0ehENotBzhrnDwiqc7%L_9ODLC-+#_s6Dn%$= zNT*y99l4}v>)56ebxul++3fdxe*1g=-{Wd`>Zaa)Wb?(pasIG=K2n%)4B1kYk9-sn zhHQ=LWax8k-X+L(e>t4LTCtNy&tHAebfEcK?mGOsgV#dcKQJPpIZ&|&^KXPl;J0am zu(+g*PkYIMMGVb%i7(I(y1Al%AEbc(gK-@CA?FJq(?LfbepC5`9A^$3Ap(*q6HIJrjfgU`gZxo)XvK6T?QiuFHelJq7`VSFd z*S!6QFt5}!hV%Kn4BW3AUJ9$&RG?qrku74!iK_B8^b6f|&@Uop@M5_)=odeJfqAul zA-tqU8ohe^0Opq#%}2lNrZ;+xXen4Ta~-VZS%i7*P<2?xx)#08%gOL^ueChFE?o-& zQqOV;QePz>X|PZhxk4%mX*hd3(rA(;?ll?<6A^Z;6!UQJH_ts`W8rGpTzBXxeSBLT{fu3~w+H;J%H)-8|YmY)ur=+~icnqv>dwi+;0y z4(w#(4?E9l714f+x;xId3<)IEE;AZomyUec_5DTIts)BE+7=JHpIIX!?Alhg1NV6x z-j8$7Bu6CA!xgzbbRKetS)7QlYp1&h?(wqopd{WV=CF_IM26Z|aRKZ*Tue#69i0IC z)hocex?jM%3r1o8T4_Gr?1}mX-kaYG2l&*${D^uuaN{$E9(?Cj1P5tX!@-uZ@b}Yl z;eDEg5<0g}91e#}jfO*nUhsi8yWxYE*TSLA_VA(forJEiydgf#!y#5Q$dQ9t=ouF^ z_^7oE9Bw27A5$vDe8il7IATBvj?}1wBMk=OD5=Q|J%|$2;`yi%?howoS?%bLi~7)? z$k+p)XzAiSbQO-Sc>u@wbipx&;p}aM#B`*?vAMZJlxGx;D8N>&D zhJ`#s4>DfPLx1{;E_}LE9?p~xg){5M;H*@6fRw3#?XN)E>qw#RTa40@GV>+ zEe&5)k(JQ7tH1Wbm1F>}6x74lJCiYgVhv&`NFA=?9nLjKT%YpA2PGRW5U7H~Ip44+l_x==ao5oHPA{1~xKjH8@^eutin15vQ z4*jEyWt>|w;MPr5aGPQq+~$+cxzHTXw=d6u+ea(VcbJ;<>82x?`~7~ba0`C?EDe39 zY%$zv>&$s18-8-@0Q{uKNkTVIRYn38EKFU(^7i7gn--0MRERr?p`IRaYgj{57BbVE%QR{b2qL zwzL9}IX7iLfz{u1toZ$;V7>;sJD9I=$w7dL5f5ZwD7+3bpl$*q3j;$z0|SSTZwQ04 P3lIl~FmM40T?;M%d{}{0 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Hebron b/testdata/zoneinfo/Asia/Hebron new file mode 100644 index 0000000000000000000000000000000000000000..53a3c14312bc770bf9bca1d2e7518763fec7a485 GIT binary patch literal 2968 zcmdtjdpy-=90%~nl!h*A-Ay8ulv{FZ6pA90L@y*xB~~fNSShJrI+V*u?h!U3NfAnk zq+AjmxumdlY?DMeDK)0q@A>@p_x!)d>-aqH=kxtNFE0-4o%edIB;zg#c7nd>vLE*m z2|adfBKw*(#;(A!jq_;MItdAKBn$b_Acdi>@9sl3T=^U4k82hng;A%FjX9afCxSp^ zQ&<~ApKIQek8JUh#rZ3}-8_2!>Vvv1&DXNG;Mc9ZM(V!)5i!mF;scm}BRm1WO&Ej+ z@(cO27av*7(0mvD68)gF6Z-eQa_B!8MxY;ZNP|BrOou<|HDUhKm^tQ$=Sra;?y7@F zhF78gOJ%Js{XTwqEL?>AoZm=O`r~UJO_{8f@QmJ3c&5^Jq})g~@|(zmNcr+VMTA}R z4m>9!LWZ$4)^7JL<~0LUVJ(X)^jbZW;1%xcd4yfsrj^K* zW=oMeN|{LAMKVY|i4dgz?43vhDKp$_Fcv5x>{>Oz!@b|WaDxqnYhk0irts=(i{LeB z%CK>i6l`*0B5dk%61mp32f5DlrkJqHOg)Q7)BNktwlvpIeJ(=2^5)ar&_5TpD3wBQ z`Dg^*m~O;lYhsn#30v~dk9h_Gu% z;V#_gdi*fX-D2#JJXa^=&Vc#IUB(e2!miyeuDHkD+Le;*F*1QYlqWLOp7IM}&*3~u z^4;hJcyEmyyszUWygzFc_NtQP)6Id9U*Ut9-LSVu1Xt05gCGIA41!fHKX&(1Cr$J5} zO+n8%s=y~Lq~Ra~Y50^v0pSImUC`Qf}6IK!Oil`aI;4u=WG)^-?AbNZW%2`-@4j_PdBZ8-0$~OxjXRF z&II&rGI?;Dl>_IIRQTDQBk;2>dokTSR~luI?F{<%i*a!K%~8$+d*P1TyZB#7jQ24? z@;^Vud;EXd6QbBdzr)M4Bqk6duSnQ`5bS;m_S3Cx?1{PgR{F`FSemgfb}z$1U7H@O V*{syi(a_P<)l#!rq4n=p<{umC8mj;R literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Ho_Chi_Minh b/testdata/zoneinfo/Asia/Ho_Chi_Minh new file mode 100644 index 0000000000000000000000000000000000000000..86e21b0f524426287fb3b21a82369283c4040c0e GIT binary patch literal 236 zcmWHE%1kq2AP5+NDnJ+nLI`W&1S(?%V$uIV(9z@E1)?V|*5(4yXHB0qfar^n=L$gd zC2PA6Ao{A&ZUGSeWZS0+Ao{KT43KpUT(-v<7@3$^n3#c(fg$-DNDxS}Ffb$)FaWJ8 lXkg%FV5pnGAn4;8!Vmx=v<=LG*aC;TbMoi>Qv;@<)_(UM|O=&QF`|UR{ zeP_pCFn#yz4KRIgk(33UG30Oo&oxL^TN_a#FJ%>Sye3C#cI{sqkcu387?{}4?C z^MA4?fcZbaI)nMYo;rc~zwgDb0GadWT-**2{db=unE!8`1DOARp7IJ%yfXAD?Eq1X zb*x}MQyvSL&m8+4%xCd^2IjN6vuJ?Sv6(YlfM|BLXJ9^ivn`m<$#w$F=lpgY%;$Qx z3e4xewi3+eIo1Q_3(mF#^M&$rRxmO#voJDI2pJf%xj+soXkcJrV5pnG$icu+-oeNV dVlxQ&_=Yfec!O{-hzJj1@B%WpfI_+!TmUPfblU&` literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Hovd b/testdata/zoneinfo/Asia/Hovd new file mode 100644 index 0000000000000000000000000000000000000000..6e08a261274e48f93eb5e221ba294e54ca671b94 GIT binary patch literal 594 zcmWHE%1kq2AP5+NDnJ+nLI`UCnaBdf0{?-a?ed=~AbtGYuNHu4iI>+VfN06v+#rfU z>P$44FTKaE0mPSCV+-cX&QSpK<$C17eEAwCFkc~u5zJSNegftzc|Qj8m939~`6}8+ z!F*Ne6=1#^_i`{_o#iM42&jKKA^@T_o-7AZ44PM#f%#fTI>CJHEgfLK&XQ~}Uw29t zn6KC33+C&W_<;EaDf(c(VQj_(5W~pVy8%QS+j@cdCc3&{zNxGZm~Y0*59V9FJh%a* z&U(wP1t8jH$xblecFG(u->zjgm~UTF2j)AZ)PnhrAqilp{0Sdu7dIpjuifeX1<4tH{e zBqim7T8artIo`MtB_+rAeRfHCzW(p;d*1K;UW>J>Lrecg#7^+xvHbr_89U~~Cit7B zZezHZyATw(!(Cr=N%%cdWwV_dBAa>QhWgHMDD>^X#+5zn+qq#EANU^bG^5M6tq#5) zu_D08c|DApP{ZiKD5&TTgfR^SV})lJS8xmCRW6ty--C(%>rg4aQ4ovrbnvstQw)o*{C2E^JFr*ML3g) zJj9-VJYIiq|32z1CTia0x3ZPJx7f&+XlP0lKxDI%gs&pD4oy*j$!wu2HY!ann>;o; M^3$`mNUihx0nK!Yq5uE@ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Istanbul b/testdata/zoneinfo/Asia/Istanbul new file mode 100644 index 0000000000000000000000000000000000000000..c89186687300068ac4e8505cc0012a1dbf6a9960 GIT binary patch literal 1200 zcmb8tYe-XZ7{~E5FSAXTNrVmOrEG3GwK*+k&CQxqv}sGHf@y>|j6@_03WZimUM>(6(qq%OZe?4YG+iU~q@#8%7`<^tk zL+gW{&{qJw{j7-*faZ4j>uX9k_rVRLpDDSEXC!_7&UM|3ozBb%#WR9z9=R+a^~>r-L0 zN(y(x3!zxVhcSU3DDjsx(ETOutx)=n2V)(7VBE_EC>xrA@s_tRp}oaL`x0C4qIaIW z4&_ysVN&@M%oQiPU~+mlOer`6cZHkaZpC4*D-}=~cDjM?tDMb5r+G@zd!ELi_fD(O zDytTzKaPOv3u34-Gccnj0PbrQx#)iTb@OO#@~ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Jakarta b/testdata/zoneinfo/Asia/Jakarta new file mode 100644 index 0000000000000000000000000000000000000000..c9752d2f23ebbb8b1ca5b8ac604c6f24be5d0def GIT binary patch literal 248 zcmWHE%1kq2AP5+NDnJ+nLI`W&04ie#Vuk-eV4voh0HRk`v_1gQyTtB+`KR|ccYyep z!rm2t=<7DeI6(BR|7r{%`pedR9gIxOEX=ITYzz!33PAHfBntyWx&i~xhRg~EJ_d%m x2@E0(3LKOf2 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Jayapura b/testdata/zoneinfo/Asia/Jayapura new file mode 100644 index 0000000000000000000000000000000000000000..7c22f539d948e5757a0847892da344309b582473 GIT binary patch literal 171 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#Vxj*)uuJUV3=n-GV&?}C{blQ-3`QoPlI9m6 m8zf{-F9D1(CrU99|M z5Xur7gV6;m3nExibc5xVNz1Z4UA)vL*oUT$($4$ri{JdxJ6?Y8?|J@b=kVGc2OD){ z(Iwy~=%&lQ_#+4Sv8DXZnCDmR{U>osH&cF=^5xzj0pniqRem>1Jun&pU*DKR-v2@h z20Plokk13YIeiKoI3H%|b8j1Z!NEf*$iof>9v;~Pf3JQDAClC=Kcr137zu$N`}E-O zgF^5VcM<&D*U!@bAMrc_x%Okoztkq)|JC1!{F~8<{JYx(A6;1jA8Vch$I}OpPbh9C zIB|krBN4Tm!{z3C=-1Y{IhwDN?MJ`f!Jywjir|WrN%V?$W0>C<3Bor$PC}nO7{z>! zPl|r?!v^%qa{_p7S0!BK^kH6oG8@jAo}t&6F2l72P3U!+yDq{nedZi`LwYCN@XL!n zPbgw(pBEGyrp%8yS;{TLvmE8t&?NG0w-WbLaIFVk*mK84`|WM5@S>Kh9QER(MtF(M z7XDxOx4KClt+6fq{jA f!QO*`!^by-LEFFtgpCatxNN|*ovw+Mu>ltVLVFjF literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Kamchatka b/testdata/zoneinfo/Asia/Kamchatka new file mode 100644 index 0000000000000000000000000000000000000000..c65155402db6a465c05a8cd71ec7a0fc0f792762 GIT binary patch literal 727 zcmajbODIHP7zW^P#;6HJL%Twx6>Z1*%dcZcvD2n;WcbJc94jT5ibGl*A3aa^Zd0X&`#IGtSEA5t{)p zazO#3#@}Fc|09g)yo9k0Cos;q594(kFhM;J6T>H9lJ@{qDI9miqI#W!$q%zHyr=X@ zZZG;VPjz)c^^OImt<*q`tq7)%XkkWgEY!C6L&2iA5{uXq3Ns61U{>uX%#M`99O2gO z*8|KAd%q)=+?!+cypL=2e5V6lcXfzfutx(18vLr`iRgT=#(R$?hB>p(AU z9z-`Jn$XKio6yTW)6py94d@lmMp)^Q|_xMZz@nzQ7f@#?~dSF_vM;=Ve*9d@V zg&amOtr-0YOe=Xm2Gh#cSHQH2_E9jcD!mO%t8p&})9Ngj1wiJje>noCHJ%(+0P!^| zvLW=9WngiwBh$gO_LdGXt+S*OOzTd`0@Hde(O_D?#0N|pq}YOK!`O@oAoGlhoWZoQ ztrwU!2~q{qrm{L<+RTU@LjUCh(-zVy0w8@BcRqmmmcQA+e5*Z|zRvAKwrLZ37DiZ9@YfZ3(0e8MthKEIVCGE&u>Lg9`uv literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Kolkata b/testdata/zoneinfo/Asia/Kolkata new file mode 100644 index 0000000000000000000000000000000000000000..00bc80a65e9a7aa470d63fba1ce1b29ef173d922 GIT binary patch literal 220 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I)VzK`~ptegw14KJNe{BGw+vo1t1)@*g?g5LR zVJ(yZ@y|>(S^=Ujl?csXWMXCkLI#GQ8z3u#E-C-|Z~>XRrdGxVTmbC&IB@^~ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Krasnoyarsk b/testdata/zoneinfo/Asia/Krasnoyarsk new file mode 100644 index 0000000000000000000000000000000000000000..e0d4fcb5c3d781943a65dc53cca9fab5d1905f9f GIT binary patch literal 741 zcmajXTPTBJ9LMozHd=<uk1%`m8Rje;K||XKG!Ea}*}U9>4Rl`1 zAv!;57G03HiY|2TM;9q3&_ypZutaEfdfW?3?<$~ay$Y5&x;Qq!d`gSvO%HN`(Cwd} z=>O}#Pu+!tRQs@@d=n87VzCOugfv@-7dr*?v{;F_tehumE{$#--CE+ANzd$ft>-T! C>VmQW literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Kuala_Lumpur b/testdata/zoneinfo/Asia/Kuala_Lumpur new file mode 100644 index 0000000000000000000000000000000000000000..b396deca1927d0cb76b903f57140274594434871 GIT binary patch literal 256 zcmWHE%1kq2AP5+NDnJ+nLI`W&04f7vh5tZMXBN5&M7K4!E(X!N()}iY=mT6&5Gf>51_iApRwf+z%jo#3sIDU}R!uVP#`wXJCjA1BoTZGO#c(Bo%;6Pgh{%0g((q yGP8m~h=HMQ0)qqtLqP+BjE`>!Log6)8<>NzkpYM_29cIPY{9@~10?NqEw}(}OFg~- literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Kuching b/testdata/zoneinfo/Asia/Kuching new file mode 100644 index 0000000000000000000000000000000000000000..59bc6e40b7bb0b4eb199dd8c17f416ee00ca4158 GIT binary patch literal 320 zcmWHE%1kq2AP5+NDnJ+nLI`US0xDw#Vu}Aiu(peB0*Ky~?%n~S_gAYofa%ZD0U-Kd z>>4ot;ME0S{$aZZ3?T8t+b&-K(MJ`8!SY9Eu!H4~GrEK2k5^iO*zBf#>PJaRuUGBcq-7G?&9^a7BtGAkHZ7#KU}aNed$|31nF^aM=L)cDfc^0DJ^|K>z>% literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Kuwait b/testdata/zoneinfo/Asia/Kuwait new file mode 100644 index 0000000000000000000000000000000000000000..5c7f106a35195a2386041e5cef07bd22f019a7db GIT binary patch literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iV#E77zCD4_EPq*=>=fyKu+ghAWDn1Ra% KNZRQda{&N)^$pqp literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Macao b/testdata/zoneinfo/Asia/Macao new file mode 100644 index 0000000000000000000000000000000000000000..c22f75e42db6b12db3c837056436cb77d176b83e GIT binary patch literal 791 zcmWHE%1kq2AP5+NDnJ+nLI`Vd2P$I)Vv+wq(3%R8aeg#PW&$+lAAo}kV80sc4@PJ500UzHG2It@q25mzF25kdN24|NL1}>n0t_2qWpKFVf literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Macau b/testdata/zoneinfo/Asia/Macau new file mode 100644 index 0000000000000000000000000000000000000000..c22f75e42db6b12db3c837056436cb77d176b83e GIT binary patch literal 791 zcmWHE%1kq2AP5+NDnJ+nLI`Vd2P$I)Vv+wq(3%R8aeg#PW&$+lAAo}kV80sc4@PJ500UzHG2It@q25mzF25kdN24|NL1}>n0t_2qWpKFVf literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Magadan b/testdata/zoneinfo/Asia/Magadan new file mode 100644 index 0000000000000000000000000000000000000000..16bac8444656c393288dcc0209a96c7c3f487a19 GIT binary patch literal 751 zcmajXO(?^09LMqB--dZONO_opas?UtyoCSdw^v^3xN{X+ajbJv$9s~Y zaxoGnOiN(m=sQeuJi+Al8<=7_g(|}#Ox0|{G=&SMhfP7X^uR~+)$bcH<8gzMWezv` zy`IE<*2xIe>^WfeS_jn5+hESP3FZ#vLS0W16g#a>8l)do!@RN_nBN=%3zQMCP<-+G z^#+R-!9Mz~`0g5A^7)J|Jw8AiZqLxh^($C*v<*!Yd$8O!2P=9PVC9&{N%N}A!|3Yn zS#(WW8`@m$MArry(RHe3blqz!te52by)eLrhiGWoQ9|pv-beFoGv8>t#dA;HqF7{t zB;b#q^zZB6PXh%BV>4YeZF+@C8FPCD8Dp+p7EY(YPq&xJtTsE-h&sOYe2Xm9$WN12 H6hnUiiV=;I literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Makassar b/testdata/zoneinfo/Asia/Makassar new file mode 100644 index 0000000000000000000000000000000000000000..5990010b649745369501c7641c401bcad4345b85 GIT binary patch literal 190 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V-n!V$uIVu<%pt1Q5MT>?)W(-67im;$I4TSHQ@` z3{;!{0c0+a1hNYn7&sUh>LxJofY|~*z99_0K&)+G0mPOJ;hrIm3|t^m*MbWGa>yuM literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Manila b/testdata/zoneinfo/Asia/Manila new file mode 100644 index 0000000000000000000000000000000000000000..145bb6fb162e192da18e0991c00578d43475b384 GIT binary patch literal 274 zcmWHE%1kq2AP5+NDnJ+nLI`W&11e($VuAlaAoB2z1cTzUGxTV7}Io^I*RAmUCdf&XSE_zV4I_V7^|| eh!6%YAfamn;_CPs>zV2q=o{1flEe~U*aShKSK|AeDs0@^`d zTI&+Io4LDkFQ<1TSk*Pl43Rh)BviN(1V67wn3Cr!{15YpSR~=6waC)_b{ESL8xAO2 zE`^cPMi@1m1m&GF7+n_#W6HcxVSIU*e^UcflfAyo0-G;F`>;||6@-f}D_3{LvI zJivY8(Kb}?IAM}=5hgE8z?888nA+D4H7yR9RzK!q`?Ng`Fg>>oW>n?FOj$A1X%#-d z6QM!MY1li%jTkxWD+W1x{}tKj;Unj)ieT>E6Euy#z`Ugs$hDrs{Lx1j+gD)OLN+%a zBNr;?kuBymovQ;sKY<-=BCH|d0&w63$Lj^3`tcK;MLmb<0o3Xfg{(gUa{J*b% ukJ2$hD&1_Cy^-(<=^o(;32EvkVs`Sxh8H~pmuVFlfF~oS3zR0WOt%xKc3qm%Mu#l8Ala-`A z7Me0)Iax?7CLuO92pf6c`=70vb36Cf|K9W6#V0oObZW?D32cHlFVXcU1~%r-+V_{$ zhC>$3-8bKbvorEn_AhV)f-D>g^f3FvkE;o8(BmcUWezVMDcIhKEVp*=@Eo#L4;5?W zFmz4_!^RU~c&`FRH2J_t(=UwDy})SI9gLBm!&t8qsFXgd`TNTETNw9nqvtt(WY+1$ zG0qcCccE&};`FDAk5Qt#$5R=Jae5mftr)({>xIu#f7ARpq=9Sv0-j zf7LD7ZGyz@pC!eyRB*i{f`mP6< Ieo~g_AMfvp!vFvP literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Omsk b/testdata/zoneinfo/Asia/Omsk new file mode 100644 index 0000000000000000000000000000000000000000..dc0ed422f6193fb5d7dcb59dd0eb3e06eec8d4de GIT binary patch literal 741 zcmajdTPVX(90%|-8!eZT!e;KwFyn8Sx&Oy5jSXo@qBOS@B}s?};Z2e#Ng?ti<+cZ{ zOnH(-$;(m-4<1b6MGWVB_ekyg?{_|Z&;OkN)8E$I)1@YUBcLbPu-N=x(a~c;bi#jV z*7tb_^Kj#ZWA`H!<7><)$zC`!TD+SGKOX0plBb6?rqnIP`{~w$8fRg{* zE!4_tc|xPTjX^K^fm1`sVKaXTOPwhP^QHH+TmZ?-tSJT4vUAeFv|LX(n3k{c0MiON zmS9>jMhi?U`ACClWg8wat)l%GOsh)&c>pp`jr%Q_R%ew=0P)qoa)D`$C%?h8X2oI% zedS&N0}yB(xeMlNZ#f61b(ZW0)4EeOfN8y!gQ6B3*uwXKk%^gwnF$%PvVkBIgu+5HF)$dYFaUv;0RsyI zgIfRt2QVolF!F#%1|aDczz7tva9|Md@eN_nHZTTaQy?}2ViN`~8z9e4*OUtYB|>k~ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Phnom_Penh b/testdata/zoneinfo/Asia/Phnom_Penh new file mode 100644 index 0000000000000000000000000000000000000000..c49800e7ee4dab27f9c0c3ccc1bbc16cec8d63ad GIT binary patch literal 200 zcmWHE%1kq2AP5+NDnJ+nLI`VN1u6q!(f>fu(c`KDq9-oa<^s`YO`kP@=!=o(3PAKF zYr7AOOw24y3=ByzAPbVeF|YvH1q_@F3pSlhtd*Z@dc0m91uO}nb;2yeMvvD0Ax<+IVLb2 u^`^9dk%^g+nSr772}q*61Ejfb0s{w_WbyG0Vek$PVekTCE+9kKk_!NE&?7ql literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Qatar b/testdata/zoneinfo/Asia/Qatar new file mode 100644 index 0000000000000000000000000000000000000000..7409d74983c8d0cd8347a663c3bfbc1c041124da GIT binary patch literal 152 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%u<+Ad1CTzJu1N;4yNU6JixR< zjwP5@jL`zqNFW`X}y-oU|PSV1xy>Hl!9r)*aa6r<{1@LgK1;i zCNOOh6bq(JWmCYknUOt&{_6&&Eu>=tK>951YJmBczwN+$tG!%czV&SdFyCgGI+(WI z%><_H+Bm_q{j4Wo+9CBdn09PoxBxOQ^}#U(MkZz!W+rsV3KYf#S(q3Yte1e@_=YfO8<+sGDG-}6aM=J^cDklq07{*2Bme*a literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Qyzylorda b/testdata/zoneinfo/Asia/Qyzylorda new file mode 100644 index 0000000000000000000000000000000000000000..fe4d6c6d6d44f0f6b7dd1f55702c4d640270a1fc GIT binary patch literal 624 zcmWHE%1kq2AP5+NDnJ+nLI`Uy0V-nyVuAlauu8IR0f^qZ_^$&{j6qbrdjp6TlQ^IN zqQyBjLg=5L7l8N@FF%3hC2y;P#ih=agZa{XS}uU(W!98}Y1uhxU|Oyx98AmCcz|hz z97`~*7^4NIm3*YZw6YBkm{!sL3#L`2-+^g0?)zX`os~NPWWM^BKVVwp$?pUZU$bH= zn6G)|f&+-Jb>uvluf62}nATac5lrh&Sp=r_S|)>O{gM_iZIDt5rVV2kTmb1eDyjz4 z#T59V*uroDWL}K)jRlNM%q+}I=#Z5Oiy%}H3ljr_Z30NY xg#!Z%1A|)t0|zioBrx)TNCqJ37Qo2i;~T=DZD0b#ra)}Qz-0qu+3A{c0RUQhZm$3U literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Rangoon b/testdata/zoneinfo/Asia/Rangoon new file mode 100644 index 0000000000000000000000000000000000000000..14b2ad09ead50a62d5e2b426396c51f9beb293be GIT binary patch literal 187 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwq5nV-wypCbh+g=qI1ogi{`5xzL|>eh{(+H+ znTdfRN*`n{kOb<9&S2nRV5pnGz~|!|!Vm<++6HFE20+r1fy)NWw$nAUGB)4>0PImF AssI20 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Riyadh b/testdata/zoneinfo/Asia/Riyadh new file mode 100644 index 0000000000000000000000000000000000000000..01c47ccb86ccbde2bf9ad0803298e8df87178a34 GIT binary patch literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iV#RoZL|P(b?(NVAp!1B;Ju2!pnPF$0$k KkhIe^<^lk6It`Bi literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Saigon b/testdata/zoneinfo/Asia/Saigon new file mode 100644 index 0000000000000000000000000000000000000000..86e21b0f524426287fb3b21a82369283c4040c0e GIT binary patch literal 236 zcmWHE%1kq2AP5+NDnJ+nLI`W&1S(?%V$uIV(9z@E1)?V|*5(4yXHB0qfar^n=L$gd zC2PA6Ao{A&ZUGSeWZS0+Ao{KT43KpUT(-v<7@3$^n3#c(fg$-DNDxS}Ffb$)FaWJ8 lXkg%FV5pnGAn4;8!Vmx=v<=LG*aCnw=@)4Ef9!L(kB9hlZH(FfB8DGFfPFxIC4WROvjI+!-L z)dSNeLE;S{aZ_12Fl}b|6GH!G0Mi!IVnA6228%n7zsz zRwO|dR@{)8m6?H|^#sWDx(N&{3=As{Fmf<3%-X=f10orLWX}Qy0UzHG25kdN25mzl TAT|VI0|qV|Aj?kI(2xrNZF7bJ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Samarkand b/testdata/zoneinfo/Asia/Samarkand new file mode 100644 index 0000000000000000000000000000000000000000..c43e27c5d4bd341649b3aa32de068d76618c81ed GIT binary patch literal 366 zcmWHE%1kq2AP5+NDnJ+nLI`V-04iezVuAlauu8Jk97Jzj{MP{}#vrQRy#YjvNgPlB z(c&B%A@tAB3qX8{m!H7$lDE~t;!;4yNU6JixR< zjwP5@jL`zqNW6Eh1l z6DDL}usaD-YvI7a!oc7bz`y|vmjp&05Xr#f;~T=DZD0b#ra)}Qz-0qu+3A{c0RW;& BJ`?}| literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Seoul b/testdata/zoneinfo/Asia/Seoul new file mode 100644 index 0000000000000000000000000000000000000000..1755147fab44e07b7527ce1eaf3ae991473fb222 GIT binary patch literal 415 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0$VuAla(0%$Nf%!Mj>OKJRZ(Z*KtGm6HAI!h=>=BrMx9206|Hxkx%zu)-9c=DXVTlZo zzGq3yVEdj6`n&+~U+5Qr`7fS-0n5MQ4+8UF9lr+VzkY85=D%6K1I&MWUJT5C*FFo( z|6p2J0rI!P;)DqxS}`vjOe-}zfoWww&k2l7EX+{I$chBPVhjxB93YM59SkfC40RJ2 mfV`dsj67gAP^5JRBae@72!nTU2!j_8d%J`%Z~-~GmRtaloVXbP literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Shanghai b/testdata/zoneinfo/Asia/Shanghai new file mode 100644 index 0000000000000000000000000000000000000000..d6b66984a2f36ae36b35e174756707aa7286c292 GIT binary patch literal 393 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%P-o_>38EKFU(^7i7gn--0MRERr?p`IRaYgj{57BbVE%QR{b2qL zwzL9}IX7iLfz{u1toZ$;V7>;sJD9I=$w7dL5f5ZwD7+3bpl$*q3j;$z0|SSTZwQ04 P3lIl~FmM40T?;M%d{}{0 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Singapore b/testdata/zoneinfo/Asia/Singapore new file mode 100644 index 0000000000000000000000000000000000000000..dbbdea3c8149004cfd525a0fc26e5da72b20e8a1 GIT binary patch literal 256 zcmWHE%1kq2AP5+NDnJ+nLI`W&04f7vh5tZMXBNB|M7K4!g6Uo9eiK0a16)rMK=i52 zPr>x*iSZmD{w0sx40Pj65Kc0Z3+6 wFbFX))JI+5H>OZk;Wj>5{NArxNLx=ovsBJ0BYwwz5oCK literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Srednekolymsk b/testdata/zoneinfo/Asia/Srednekolymsk new file mode 100644 index 0000000000000000000000000000000000000000..7fdee5cbee2b1ba0904a672dde16240404466fb9 GIT binary patch literal 742 zcmajXPbkA-9LMozHq4)clo{Ln8-^MC&HUYr`M1~>X&1xEpJJCK2XVwf=FdS6ODJSC zau`WF?4TS-k{p(U!eJ>bxsc*{K08u-*7Ll2KYM;(n|)+hL!vGoeZe+cw&9aVx zQ-0{$&!~829&dRb=^aT^RCh5&Vn=|PE*!mqpBs%#acCX?X9RBptTV6VXo+9#WG(gP zLfKj>%yRKz_S6T=alF9X-g}s5zJPMwDa=>y!2*dJ7ADO@h2SL2<|{sSVbSw0OHw@1 z8S!oo_a*0(Q0a5P((OK|TCu{i83QaIFNf;E9LV)soNSP0OaUwE%b>P90anUVU={Zo z@%tUtNaDlnyPAhPbnRCNUFSbR>w=eP{mw0{KRbYiSs!e0FTuv4RcM^{I@!FY)(Ld; zz#_V(z>aQhcB0#2^=Om48*O^)f$e;4#A_YwcoISLp$uBCG+{R1y6}UxnZ1uZe#}2V z!T;BPpT_bDS(dV)u1z8!#1r5N32`5hWOnlC=?M^_#cCr;PEEIlZjL1C>1j}LT;eYf CU5tYO literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Taipei b/testdata/zoneinfo/Asia/Taipei new file mode 100644 index 0000000000000000000000000000000000000000..35d89d036d07c3f28dec64092ab1b533c21ae2bc GIT binary patch literal 511 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1S(?zVuAlaP;%~r1c*Ky>e&FIFNH*c>C4^KVET&F z+7BS{tFB56Ao`lmelY*K&3-Wd23uMINc^VkC$RdP&u4<=Z~a#T%ilh67A$|~0mR(9 zs~EuY_lk>Q6a&ZGE-;_-Zf66C&vkC^2M{fIdtn2J77Dprz{teNOcZ2bD0~6ZRL}s5 hfVv3`93YaB$HzB>!8tgD!3&6;T|yYRfE-;5E&yjg_Y?pC literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Tashkent b/testdata/zoneinfo/Asia/Tashkent new file mode 100644 index 0000000000000000000000000000000000000000..65ee428ce1c5093a4b3dd29512d98a33b4c753a0 GIT binary patch literal 366 zcmWHE%1kq2AP5+NDnJ+nLI`V-04iezVuAlauu8I-6GU%a{N4bhUsSzz0f-ip*dzd= z#W^-Afa#x4CxB>)mroXeXvy1>V0o!CnP9&3p0WcVahWygU|M!g1eliV@dVTIHCA9+ zAx9fbE5^uxX(blVPk!oZMJz{mj%mjnhL5Xs2n;~T=DZD0z-=0I%5z-0sE+3A{c0RYJz BJ^26t literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Tbilisi b/testdata/zoneinfo/Asia/Tbilisi new file mode 100644 index 0000000000000000000000000000000000000000..247caa631ab9964c1de8b35294fe4551a9167af4 GIT binary patch literal 620 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1}b9%V$uIV5Vma>BZyulISWibzr_;(GDlQ><^d2b zCUMRHM2mBrbpX@97&m}uiB}8AaR*B&0tz~P6?Qn>q!OE z@-<;#S|P_BOe@A%fN3QkO)#x&BL${abhyE^s`MW)t;YQpOslg>CNKbj`d2P6t?`tz z0L0h4axVZxYaKc00HU?G902ommMjMIb*C%>^YvOIaGB9nB5@`Tb&R`fj=>Ui} z33A*3qD^JP4uEJgBV{n(?5_owZz1gfR&Q}v3e30stpw&yBD$hrzJ@{>n6GhrE|{-*dJdSc zwNDAm*Isi0tY2q-m<33mZXYvPUaz4OEU%w$4wg4a+zXaB49Eh@8##Rd%NrZL2lGu- zOTm0o5oNG?Gq#mr^=4ng!1CtL?||hku62RsEl&!7<*jz|gZb90r-J!5vz)-{ZF^3D z)!S8V4a{g5~|HtikgB885){0nvG2`9SYnFh9ulGngN&vkpAfzV%un<(0`rqB9)Q&+Yo}Q-GBdHVurf1I2pJd*z*YlE76t};4@M3K215%5 vJ_ZK207el81`7uU2_N4Oh7cguHZU8zf{-F9D1(CrU99|M z5Xur7gV6;m3nExibc5xVNz1Z4UA)vL*oUT$($4$ri{JdxJ6?Y8?|J@b=kVGc2OD){ z(Iwy~=%&lQ_#+4Sv8DXZnCDmR{U>osH&cF=^5xzj0pniqRem>1Jun&pU*DKR-v2@h z20Plokk13YIeiKoI3H%|b8j1Z!NEf*$iof>9v;~Pf3JQDAClC=Kcr137zu$N`}E-O zgF^5VcM<&D*U!@bAMrc_x%Okoztkq)|JC1!{F~8<{JYx(A6;1jA8Vch$I}OpPbh9C zIB|krBN4Tm!{z3C=-1Y{IhwDN?MJ`f!Jywjir|WrN%V?$W0>C<3Bor$PC}nO7{z>! zPl|r?!v^%qa{_p7S0!BK^kH6oG8@jAo}t&6F2l72P3U!+yDq{nedZi`LwYCN@XL!n zPbgw(pBEGyrp%8yS;{TLvmE8t&?NG0w-WbLaIFVk*mK84`|WM5@S>Kh9QER(MtF(M z7XDxOx4KCltL@ZNizm68z5L@ZNizm68z58jufuR{>FhkD*MivH!x(N&%KE5FgUM@f!9Kyf_ IBy=sg04jJ!hyVZp literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Tomsk b/testdata/zoneinfo/Asia/Tomsk new file mode 100644 index 0000000000000000000000000000000000000000..c3c307d7b99f39328cf289360526399c55984af6 GIT binary patch literal 753 zcmajZODIH97zglk%~g|`G#k$`UW37SjPV*~a2aDT9;I9IioBu}NqJ;3^4dril%ymR z8%cRAqzFsRLLx~B3!5PTmt!wBsyj8vY$DA^&@@J~ASzUJ))M&DlxEXVYX zyFER?Joab+3H$=MUnxx&LLQQR|{=xO|ay+Um&zfCoRaL z?G^u5S@gcoNj&~o{NG~_p8LHdoP?0_752Q?KzKsB?3|R4#x5dfJ0~wG6^T}tM%zF; Nop_n(o*kd=^#inkiIxBW literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Ujung_Pandang b/testdata/zoneinfo/Asia/Ujung_Pandang new file mode 100644 index 0000000000000000000000000000000000000000..5990010b649745369501c7641c401bcad4345b85 GIT binary patch literal 190 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V-n!V$uIVu<%pt1Q5MT>?)W(-67im;$I4TSHQ@` z3{;!{0c0+a1hNYn7&sUh>LxJofY|~*z99_0K&)+G0mPOJ;hrIm3|t^m*MbWGa>yuM literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Ulaanbaatar b/testdata/zoneinfo/Asia/Ulaanbaatar new file mode 100644 index 0000000000000000000000000000000000000000..6f5d3a15abbe48b8a4dc72aadc88c416160a56a6 GIT binary patch literal 594 zcmWHE%1kq2AP5+NDnJ+nLI`UCnaBdf0{?-a?eaSxkUoCyI}<>(#LE*6AX@U)pAR5f z>Wps#h?d@CPynK3*625YXxTYJV7^?BAeb*-{RPZd$o>rGD@I=f^Od}>g89nUJHUJu z?d@Q`s`M-{UyXYvn6J*V?E?c4sDIf8q8K!u%mDK>ugn1RwT@JQ`Py5mz0jC zFyB=+P=EmlLPckR`C+Vy1t5Od*BUTC{Hb#RBQq0;kbxn^1Y}B50Vqc6CNOd^FcdT} a@c8(KFlZZ?1F(#LE*6AX@U)pAR5f z>Wps#h?d@CPynK3*625YXxTYJV7^?BAeb*-{RPZd$o>rGD@I=f^Od}>g89nUJHUJu z?d@Q`s`M-{UyXYvn6J*V?E?c4sDIf8q8K!u%mDK>ugn1RwT@JQ`Py5mz0jC zFyB=+P=EmlLPckR`C+Vy1t5Od*BUTC{Hb#RBQq0;kbxn^1Y}B50Vqc6CNOd^FcdT} a@c8(KFlZZ?1FGsnw=@)4Ef9!L(kB9hlZH(FfB8DGFfPFxIC4WROvjI+!-L z)dSNeL7ZUPR8{~?n;E`_(0@LGX$xug4mcL$t`BrP6N}9&1(uk<~g}mfcehJePF(eY8067>RbTkyRq7U`R>X= zV7~jiNHFcmYyzRrS%Yb>$6{dGdz~zp_Bmtp0c5^!?|(4gFZYWBh#%s;>jNVb3o|BU zWy2zfsf>l0otce+q0J3sT0sK?3j;&l1W-DgwSj?$fnmh~Mgb6;5yEexkxD*yw8(>Mh3YI3Pz%nrq z^owA*I*z!?Zy%5=K0lBveW%D(em}Bd>mF8neb6{_0&CoBu(odt)=ha`ys0K1y;uih8-uZou{49RjU_W9VoHdVC0mjRB`ND+(i}+1!LB41 z%YnI}kd)HEIV^EX#EH>%mcixW=JOUwNKm2Badi}3Q_ z!kWK%t|7M<59vDdQj~R&-o9gZq>p6u6@Kj1lD<#7`0saZzoYg)%|uIWCM$Kox()`; z#=#(q49fa>7~ICekg7KrYP^SGX;&~@c?jjw9T?%h3Kil@p5`mw4`AfOelT@ZZ>z(r z6?~6An1;%&aTv4I2V*B&VBByOjPEi*RlN=-R5w{^p1M;H6LkidR4RwbfiW;e?dtH$ z6KbU4Jl)gWzM{3CF6dO-1v>5e5uLvL0(HA5Fk|E#X3ng`tcFdPJ#=KHc{zDgXnoxp zI#=F<&eL1a`OX#Sg0OaUfxR0Rib@=wl|#e58X7mW&~#eN)BK_dDcWp2W}L|Bk4OCX z=if)2MU3?=(9n)SCT7es$4M9)urd$YIbpZVF^Q?j%#eh{(+H+ znTdfRN*`n{kOb<9&S2nRV5pnGz~|!|!Vm<++6HFE20+r1fy)NWw$nAUGB)4>0PImF AssI20 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Asia/Yekaterinburg b/testdata/zoneinfo/Asia/Yekaterinburg new file mode 100644 index 0000000000000000000000000000000000000000..a3bf7f29b6f14debfbd0f8ccb45f1ea338009ef7 GIT binary patch literal 760 zcmWHE%1kq2AP5+NDnJ+nLI`Vd0xDw%Vv+wqFgu=89Yik_+6bclZ(aP?0Vu~Hs@}Z; zM2krrPyo^59QzHx^v}-=K(xfmPhfe;+v*A+zSNm=FkgC4%LNc$W=$!WmYtIZrsaCV z!L)ph2bfmKu>{kKFl8s*~+NT0=B4KUyGw;h;owU-Obx4x|a z=G!b&2h+B@nZUGN8z-2ypY;SxJEXn_(~d0+7eMAYxt;~{os%Dd`7WyK!F*TeBVfK8 z>qIc$U3nRp@BVHrnD%7ufY9gq!L--oEHLf8t`JQ7oM{gLneW>d4CaUUFgh?Yu`pwS ztk{Jym9nt_{eKf=s>wkH5Zi%)1DGNc7{ zA;%p|E5=xWX(b;`Fs*DO1*TPWxWTll^dB&-#{CvdtFuZbFaUx2S1vHE@szUw#Miv? z3ruSrc@3tux7-2KI!n%iY27LNz_eb=dN8eDvH(mQq)Y_U#vPEFp z%*Yo){|y1t7SdS>3_xIU*9^?J{OtqgTkVwq^Q~{|f%!JeOu@A6ZUHcD*Cr08?Pq-g z(+;UW!L(xw-vb69aB{s3<~t{U0P|f`_k#JZ&X>S^H`e)JzPs`kFyH;%ZZPf1JPksh zn+vAB9#?>A?{)QH+ULyF1O_1R?Mnpn{nnHxFfub?fh>$rh(!)rJus|yfK1dfU|?Zj ma0_7M0EUJG0}qH~9Q^!QFhJaVq(#U<8hIYr_((IKn@ z?EBIB_$cbFHD{wqy)CQ?^|rcx%xMp|N4-5a7Wub68LZhAsCW2nM!h2;82L`oZPqyU z^XfW2jC%K>PS~?|#+5wIJF7wXUauW~P?xi=6vE!gOxV}^5cW64!hy1I__0VTCvyff z6XB<%7&sJj6%L05!I1zzsPH)eN8KFZn8*^2o9e*{eGgYM@3W=@>#7BuoYI9~`qkl7 z^G`VaY6{NC2H@<|RycRB63#~yz=iWt_%*OaPUbKAmcwuEd2q=-4SqL!0Do+ZhRfV5 ztcw9~Md2%FelwH~w^afcE1|BU0P1x~;ntc&s9#>eBYg(B`Oq*W9d1jIK%>Z8(D*_a zG&vavO})g>%*g|8=Q}`i0}HrAOBY%wyGzJ?i=|!Aa?BiB^=yGV>r|n&v$iqmvo2Xi z%r~m$k(i$~iP+{*AGD2afp*u*p&%#^3QzU&INWt>zm%BXzxP^CDl7f-QdRkrr|F4# zilXT;OG=5R7v?!?G_4q-w8)F$FkkJ3dGe>G&Esq$8A{K~TTC5fwv9l@Y!PKG5KzZF je8tR-n9^`!(k?POY@*$Qq5D)bycCq`62!VbxxOa254p z(C=RhNu*x1updSdv&DL7*t>>uk6vApXWgC7S~N#=J4heVd) z$(I7l_x=bx5z2-?c)UE@7e@3BmXX$W_+x(-Jk`?$f6lB$f4a?w^V4&4cpkNM!qGP& zI9A+;er)hQJd@f1&-gCD@h>(w(LE%v_a%>}e3Eaz3_ymHKO5cuqJ*DF8!u~H^1`2+Q}vd>uvG3!@AKD zxa?FNtiQy;hQltA)`+q9J6vw7fh+b-z$Uc{t~5S`tCmWzSs51SF=9^6!qtCpDyn_`NL z&a~A3H6Y1ujR!L(e@ z1TZaM(+H*&a*DvTVoWlaR`Lk})5l@ z|3{#5Ao&3tlne|U3=Dh%j66QRAq=_(h794ZAwV1)!oUS&8Gu+izQ%f{dItK2I=+Sm HAQl$@o9a^A literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Atlantic/Cape_Verde b/testdata/zoneinfo/Atlantic/Cape_Verde new file mode 100644 index 0000000000000000000000000000000000000000..8f7de1c0a19a8d3e0e749626c76c8d4dbd3c4de7 GIT binary patch literal 175 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwp8r5F>Dj6UAo|SIISL^9Qb~;f$Q*9*?+%Pi vjLiT4zx=|$@c;kg2MjF#|9||z$N?f5IDC9V7<3JcfY^|M%LYi=8FB#tdL1f2 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Atlantic/Faeroe b/testdata/zoneinfo/Atlantic/Faeroe new file mode 100644 index 0000000000000000000000000000000000000000..9558bf7180acab14d3b3f63c956f5224f680b2a3 GIT binary patch literal 441 zcmWHE%1kq2AP5+NDnJ+nLI`V704ie!V&4Bi(4D&^0?1|%Ren7IM2iXE0n_5lXCd_G zePCMR@p>>Vd3gbtmO4BUOiSjNmeXKbzhn=XHb_|urVV3n3NSL^hyVZoTmiBh2v`^x_yia^e0)O~ g!d*c)ID~-<$T9%2bbO8VO!W-(4Rw4C4L~d|08D2^!vFvP literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Atlantic/Faroe b/testdata/zoneinfo/Atlantic/Faroe new file mode 100644 index 0000000000000000000000000000000000000000..9558bf7180acab14d3b3f63c956f5224f680b2a3 GIT binary patch literal 441 zcmWHE%1kq2AP5+NDnJ+nLI`V704ie!V&4Bi(4D&^0?1|%Ren7IM2iXE0n_5lXCd_G zePCMR@p>>Vd3gbtmO4BUOiSjNmeXKbzhn=XHb_|urVV3n3NSL^hyVZoTmiBh2v`^x_yia^e0)O~ g!d*c)ID~-<$T9%2bbO8VO!W-(4Rw4C4L~d|08D2^!vFvP literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Atlantic/Jan_Mayen b/testdata/zoneinfo/Atlantic/Jan_Mayen new file mode 100644 index 0000000000000000000000000000000000000000..dfc509570a5be7ea90f64610ad5ca5a58fa3d172 GIT binary patch literal 676 zcmbWy&nv@W90%}chGn5|ZMI=-Z1eSFKW!*+n&n{MlkY*IghcJM926IFaB%pNgQ7?d z6n0TAMk!L!FMhUW0LTA-e9xREawUGQ?o1h4!m7#Wnoct9`E z`R6S!^2>5NOw3u~>x2#_M;Z9mBY~;T6im0o;5!?I8FdJLFiC;#{j}vHegtbvG(lACkd_{V!NB=F8Bl+(kM6SfI^^#mdiWySi<#^)ubkoKYx!5cY8qJ*3+GMqxIftEU HbIN}KI)2g> literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Atlantic/Madeira b/testdata/zoneinfo/Atlantic/Madeira new file mode 100644 index 0000000000000000000000000000000000000000..21e84571ee1694758dd244ed0702fbae962648e6 GIT binary patch literal 1372 zcma*mdn}b<90%~{gygb1i{;*hgdE3vjxK7Mm8rE@jZ-d5t#qGEXS7DOgRE8l;7qMV z?rS@9Iiy@hl3Rz|5_LpGNC-)h)#-h{??3%j-gnRWJip)fd7g8Z1fD%5CjY&7>cLc1BKi-my76hArl=#-^rKTDYatk2nBi1iAcU+61FLQ&_bp1}NvVpxzKgj{*u79rachvRUb6|siIrQQ=bRS8#(@ij?rVB{jB~tjiq0h~SD z=h1xI19@{zKp4$iq)Oy1bG=FN+msi#y1~+^GJiUE(!3vO*H&rB!zQY!JIP^ zI6vsAr2j7y!=DslGNY7HO$RfeS%(~&*Th1LiUKwz#4TBRhy)$uWK&E;r5ovaO! z!gYs(p|zI;+U)Rz>jhh&t)(5@U}y^MbUYI1e!JOC(0<4kI&`jr8|!qTWAPjmWRF6p zq;4p@)&!lyDnlTH90%|-V`(I%CKMAxEj5>vBAMF@_Ci~UH(Npxg~&TJR&oh1cr}c?l3OW7 zd!ZCDw_!8GTxWAPmznEvp6~tuFFdE`e9!0i`#qgH9a&L%Sv>XUVlfkBlO_B6NG3Dp z$!vd`SsjWN4M}xxC`EEW-_}ENur|M${_t!P`lBh)=#S3Tp}!;vMt?aq znorIxn**mwu0&;Mkc&~M>o@{fH!eo59j>Fk-WdsRXs6)KN)EiG?uGTac6eJgf!qk%nYFpS;JIRRiw@&A=vs6gIv0!Dhc|ckVYJ53GUcAI=rRM;nPq%Sb)y$CEtx zL|FizcDdlQ;$--|$_!tKLtv{!3txtR!?q+7((V(C`W0^;zPkQ`ubpc6X4L}U8XMue zu?6^kRslb>kHC-p?(gQPXoa7eDs{Ut<=_lcpVylsDj;Cy`M?k%)>F#ZfuTGncuExWA5R Bu;Bmz literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Atlantic/South_Georgia b/testdata/zoneinfo/Atlantic/South_Georgia new file mode 100644 index 0000000000000000000000000000000000000000..7fa5f4683538498b93d1e639c14256c1f033c354 GIT binary patch literal 132 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iWA+4lDUHq&t<8 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Atlantic/Stanley b/testdata/zoneinfo/Atlantic/Stanley new file mode 100644 index 0000000000000000000000000000000000000000..1a4c8ea86361731f4d7e854ac66d96a5ce6b2dbf GIT binary patch literal 789 zcma*lNk|)E6bJBc+^W$-0~Oqtx?rr!B+tpt<)!qQLS@ReLJPbe`v=~LYgA~y!6i54=7kyd zpPa&h{bYD+WexuEjl_?$;xmvTvh%Vu5S4c*Cb59 z)~cVd^{NN9r7yy^!`HA~vmIoj?5o`>W$nMOu;XJr{4y{F*S*)PQfSDX6CNhc-ND1| w!#Vf+7{fJ;^Sz)HDgGuei{boKl^)ZCMb^D?vbUo1WuxdK(FUfm2vr(2x9gG87XSbN literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/ACT b/testdata/zoneinfo/Australia/ACT new file mode 100644 index 0000000000000000000000000000000000000000..1975a3a4bd0ed93db1d10a2c562eb5bc3baaa489 GIT binary patch literal 904 zcmb`@%S%*I90%~lC*b>sI}i6Fw%A={F(-JvHQXgzoGtg30@dUB~H}0Js92l3&zYX!r1$} zFm7-R#+NU^gs#Uh(exfBHMI%<3_ydU9wtXURd|t-^-#Fl57RVt!axf&9^}DvzYAt8 z>7l867+!o6Bu?htUesC22F$L0%WcYOKY^FBdtmO3b>ZnTylkEpZmvPI?v-$Q3g#dA z;FZD83NI{MFJVE~B(w%Qpsnczw7>R3>0UD|>@0yrWlmV!kPJ&QOz^7oQ+P(uVKflO zv2%#JG;jp3g;wD8?QP;XCk|lQdHh(4WwIUs literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/Adelaide b/testdata/zoneinfo/Australia/Adelaide new file mode 100644 index 0000000000000000000000000000000000000000..3bfbbc563cf97dc2548ff8974ab23dcde28e8744 GIT binary patch literal 921 zcmWHE%1kq2AP5+NDnJ+nLI`UK0V-nwV!r=CP%PFh0-~#hm zeZaKrK|wGrSGgEW%TM3Q0WwD+vK7o%Y`6-hm7ErV#g#KZfoT<`7BH>qc?C?XF{OcN zbu(Zz ylXD`3UcZiki4hGlF!Wb|WM^$)WMN?FS-`;Q;~T=@=;{I@fN@HuYhizMQ z+6<~xl9$isYO!#f@J?|NLYVTo|c^ zZ-=`uzStwFbPs)71r(C)B4xvI8?xb7IZTuU?nf&$rhey6=%H!-HQaGON2K*hpT5E5 zYY8yrc^sym`U=ycV=%q!70d|Vf|-_4xU=CBck?F9@*RV_lKNHJf4B7lH?G1xx)68d zJj`Bo!M!~-&^(h4Etem{eRp4ov`@~-2(tD12WYE&fPQ=H2HbD!hPl=6x$8gSfxHRs z;yajUjB=lh!-H#G@KAI~rE?t1cVK?_8FW4kLs!FXC=E11chhO;X)l4^QW+N1S>R!F zE-dsg?%zb{%QlO2j&EfRx#-Upa`E&W@{!N0$R)8KuypDrEQ`#-@_R8@aqcnn-mH&D^$s(Ev8(;e$k^bh tE`_m3lo@M63iAi+wMIr0P?(8+^NWhTl3xxej*we&x}B0ER6w}ArhoaP!bkuB literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/Canberra b/testdata/zoneinfo/Australia/Canberra new file mode 100644 index 0000000000000000000000000000000000000000..1975a3a4bd0ed93db1d10a2c562eb5bc3baaa489 GIT binary patch literal 904 zcmb`@%S%*I90%~lC*b>sI}i6Fw%A={F(-JvHQXgzoGtg30@dUB~H}0Js92l3&zYX!r1$} zFm7-R#+NU^gs#Uh(exfBHMI%<3_ydU9wtXURd|t-^-#Fl57RVt!axf&9^}DvzYAt8 z>7l867+!o6Bu?htUesC22F$L0%WcYOKY^FBdtmO3b>ZnTylkEpZmvPI?v-$Q3g#dA z;FZD83NI{MFJVE~B(w%Qpsnczw7>R3>0UD|>@0yrWlmV!kPJ&QOz^7oQ+P(uVKflO zv2%#JG;jp3g;wD8?QP;XCk|lQdHh(4WwIUs literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/Currie b/testdata/zoneinfo/Australia/Currie new file mode 100644 index 0000000000000000000000000000000000000000..dc2ef554dc389f4a34146329935e5c3581a0f2f4 GIT binary patch literal 1003 zcmcK2-Ahw(9LMqR*&O10>IpSMAzT=$NdH;UD17l3?^!HTJ zsv{&%@Wmsq{)#VoOq;xNR+7^z(sy>~U7y0<9<>sC=c5aKS2+%YFUw%)SPPt%9}}OO zp6W)wdG3X=NE@69ox}cH)r?+z-H%?124G^U11_H*!Tw65j=w&U_lCjpPzIWJzpT;FH7 zX7D~->l}mY`Yyxu#(QwX;hvPsmtdY_56ssdfCVKd6@Dm~ml!G(S``>M0gK}0uvm3N z!?+$APnqDRn^EG~+z~*RC^N9Md5D*3i~lFwT6z&~+Z%&rnl5NEr+zon-)HFZUvY&W z%yWb2ir55t`;!Z3%Y!hwa^MJB>{rp&UMJdi#*dbccET#}RjgMx)T3+cr_nnMMzlR| zAKIQE^v(qf+VSZdx;F9y?i!thbz>EkI}K ZAKwrLN9SM=;S$2Y1!C%2S{WN~0RXyMNZ0@X literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/Eucla b/testdata/zoneinfo/Australia/Eucla new file mode 100644 index 0000000000000000000000000000000000000000..9080f5cdb1216ef6397e7de6205173caa794c646 GIT binary patch literal 314 zcmWHE%1kq2AP5+NDnJ+nLI`US1}b9)VuAlaP_m3`1BjmEcSQtD?{Sy{qECk$fzZdx z!QyAOXMpLm%OgcV_HgolgwWggz_b)&1cY8*3Z^wxgCO+!{Zl~dT?@B>X*bpwFzv2f z1eSMyR|%#)nL{A-xo8n4MhwWnP;midOs5PZ3j;$n4+EEvZwQ07fu)HlkhB1jTsC0Z LPS?W9#FPsFy<IpSMAzT=$NdH;UD17l3?^!HTJ zsv{&%@Wmsq{)#VoOq;xNR+7^z(sy>~U7y0<9<>sC=c5aKS2+%YFUw%)SPPt%9}}OO zp6W)wdG3X=NE@69ox}cH)r?+z-H%?124G^U11_H*!Tw65j=w&U_lCjpPzIWJzpT;FH7 zX7D~->l}mY`Yyxu#(QwX;hvPsmtdY_56ssdfCVKd6@Dm~ml!G(S``>M0gK}0uvm3N z!?+$APnqDRn^EG~+z~*RC^N9Md5D*3i~lFwT6z&~+Z%&rnl5NEr+zon-)HFZUvY&W z%yWb2ir55t`;!Z3%Y!hwa^MJB>{rp&UMJdi#*dbccET#}RjgMx)T3+cr_nnMMzlR| zAKIQE^v(qf+VSZdx;F9y?i!thbz>ESc3xj8CBH~ZPplON0 zpFt`XLL(wI7^I`5G10-FK}?!1ItboP z9C?*|%VSnGmt=i~U%p3{Dw`vNd|e%9S*#tAknt&4&9%eoNI$H3(!!-n0$g^jfXnCC zMb=lbd6Z#U=@nsZAdY%f=UR&0SNmU3uc?}bb$vIm?)?F-)komk+bdX~y8`Qvcj3CX zN!YLz6WM>p#InS)UfO~A(+Rj?C;$r^E|`wEVABi_n_GF>O^nPoQo;NTk@i*2^f|wit!mx5KbwEDU!noT0zdDZyQ%A-J0l ziLBq*H3#?P*irAT_QJg%!4#*+`kmQ||4c$cHSF)TJ(5kx{sosyNbr#46S9566}j9V p(%~HR5Cf%VLEZ)Ilql^ux7Aaj*(}JQ@{t&V literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/Lindeman b/testdata/zoneinfo/Australia/Lindeman new file mode 100644 index 0000000000000000000000000000000000000000..131d77b54a2087ada0bb3a27d03bf752f84326a7 GIT binary patch literal 325 zcmWHE%1kq2AP5+NDnJ+nLI`US1uA0(V!r=CQ1o`u6%akg?@$An-lNX|qEClxhS0}T z!QyAOhk@y{%iY2Bxdp{w`Sb0X4M4LPmSc3xj8CBH~ZPplON0 zpFt`XLL(wI7^I`5G10-FK}?!1ItboP z9C?*|%VSnGmt=i~U%p3{Dw`vNd|e%9S*#tAknt&4&9%eoNI$H3(!!-n0$g^jfXnCC zMb=lbd6Z#U=@nsZAdY%f=UR&0SNmU3uc?}bb$vIm?)?F-)komk+bdX~y8`Qvcj3CX zN!YLz6WM>p#InS)UfO~A(+Rj?C;$r^E|`wEVABi_n_GF>O^nPoQo;NTk@i*2^f|wit!mx5KbwEDU!noT0zdDZyQ%A-J0l ziLBq*H3#?P*irAT_QJg%!4#*+`kmQ||4c$cHSF)TJ(5kx{sosyNbr#46S9566}j9V p(%~HR5Cf%VLEZ)Ilql^ux7Aaj*(}JQ@{t&V literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/Melbourne b/testdata/zoneinfo/Australia/Melbourne new file mode 100644 index 0000000000000000000000000000000000000000..d3f195ac2fac23afd46cc16650e0a2454f5a3923 GIT binary patch literal 904 zcmb`@%S%*I90%~iM0R@f%RMLR=G>;Asy4{+1(a?a;`f9KqL;mGxEt(kOY zY19)uxa6~6@v6r{)e-quEuUc^h8?}LsKB6&*j4$xaHR$Pwb^@cJ>Z6)$9>q}@S7F& zTNL^*4~9j=b0qCuBeM3;0ngb^gj;b?7xi5@^9SmGEx_|*vBVYr8h|@RI2jyjN8#0>Y2r$(>p@QHe2$!4`U0l39l+G&$1tsG9bOA*g4fMc!i_a();$wWy@faT zeK39alfnzj=2Mu_^#)p}+oA1|Q{5%94|@Pwel zXdo`f&JX0gz&^|mF2jQDZQ?4N+=WH+LFgPFzduC&J^s(gJ53nTlX24B_Q+J?D(A^7lb+`c$<7^% QN3vTbtKH(sW^7sde@9iYAOHXW literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/NSW b/testdata/zoneinfo/Australia/NSW new file mode 100644 index 0000000000000000000000000000000000000000..1975a3a4bd0ed93db1d10a2c562eb5bc3baaa489 GIT binary patch literal 904 zcmb`@%S%*I90%~lC*b>sI}i6Fw%A={F(-JvHQXgzoGtg30@dUB~H}0Js92l3&zYX!r1$} zFm7-R#+NU^gs#Uh(exfBHMI%<3_ydU9wtXURd|t-^-#Fl57RVt!axf&9^}DvzYAt8 z>7l867+!o6Bu?htUesC22F$L0%WcYOKY^FBdtmO3b>ZnTylkEpZmvPI?v-$Q3g#dA z;FZD83NI{MFJVE~B(w%Qpsnczw7>R3>0UD|>@0yrWlmV!kPJ&QOz^7oQ+P(uVKflO zv2%#JG;jp3g;wD8?QP;XCk|lQdHh(4WwIUs literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/North b/testdata/zoneinfo/Australia/North new file mode 100644 index 0000000000000000000000000000000000000000..a6a67300dd5ef87e421c9749702039a6bdbb928f GIT binary patch literal 234 zcmWHE%1kq2AP5+NDnJ+nLI`W&0xDwxV!r=CP%Jhn0z_8}F&BX7IesTQ!1Nw74iJ4h zWEX@!o&y#?vpp6}pIz<;rq3;?0?VIoH|StwW`aTnhN=}H*VIh_*)(|tBPRnx>kI}K ZAKwrLN9SM=;S$2Y1!C%2S{WN~0RXyMNZ0@X literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/Perth b/testdata/zoneinfo/Australia/Perth new file mode 100644 index 0000000000000000000000000000000000000000..4f771828c9b54d9bcaef82639425df4b3559b5e1 GIT binary patch literal 306 zcmWHE%1kq2AP5+NDnJ+nLI`US1}b9)V!r=CP_j(y35cHKcW(ih-s7zRqECmMhtS6x z!QyAO7lG-s%aa!X^)hhs|Ax@pB*3&3V-kd3UJs@Aq-p~ IQrChD0G5hMm;e9( literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/Queensland b/testdata/zoneinfo/Australia/Queensland new file mode 100644 index 0000000000000000000000000000000000000000..dc9a980a65923b6629d788e4e03b4358ac151c15 GIT binary patch literal 289 zcmWHE%1kq2AP5+NDnJ+nLI`US1S(?&V!r=CQ1o^_2Z)~Icc=kO@6l%f(WgT;L+InF zVDU5C!@%^}Zz ylXD`3UcZiki4hGlF!Wb|WM^$)WMN?FS-`;Q;~T=@=;{I@f zeZaKrK|wGrSGgEW%TM3Q0WwD+vK7o%Y`6-hm7ErV#g#KZfoT<`7BH>qc?C?XF{OcN zbu(lC*b>sI}i6Fw%A={F(-JvHQXgzoGtg30@dUB~H}0Js92l3&zYX!r1$} zFm7-R#+NU^gs#Uh(exfBHMI%<3_ydU9wtXURd|t-^-#Fl57RVt!axf&9^}DvzYAt8 z>7l867+!o6Bu?htUesC22F$L0%WcYOKY^FBdtmO3b>ZnTylkEpZmvPI?v-$Q3g#dA z;FZD83NI{MFJVE~B(w%Qpsnczw7>R3>0UD|>@0yrWlmV!kPJ&QOz^7oQ+P(uVKflO zv2%#JG;jp3g;wD8?QP;XCk|lQdHh(4WwIUs literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/Tasmania b/testdata/zoneinfo/Australia/Tasmania new file mode 100644 index 0000000000000000000000000000000000000000..dc2ef554dc389f4a34146329935e5c3581a0f2f4 GIT binary patch literal 1003 zcmcK2-Ahw(9LMqR*&O10>IpSMAzT=$NdH;UD17l3?^!HTJ zsv{&%@Wmsq{)#VoOq;xNR+7^z(sy>~U7y0<9<>sC=c5aKS2+%YFUw%)SPPt%9}}OO zp6W)wdG3X=NE@69ox}cH)r?+z-H%?124G^U11_H*!Tw65j=w&U_lCjpPzIWJzpT;FH7 zX7D~->l}mY`Yyxu#(QwX;hvPsmtdY_56ssdfCVKd6@Dm~ml!G(S``>M0gK}0uvm3N z!?+$APnqDRn^EG~+z~*RC^N9Md5D*3i~lFwT6z&~+Z%&rnl5NEr+zon-)HFZUvY&W z%yWb2ir55t`;!Z3%Y!hwa^MJB>{rp&UMJdi#*dbccET#}RjgMx)T3+cr_nnMMzlR| zAKIQE^v(qf+VSZdx;F9y?i!thbz>EiM0R@f%RMLR=G>;Asy4{+1(a?a;`f9KqL;mGxEt(kOY zY19)uxa6~6@v6r{)e-quEuUc^h8?}LsKB6&*j4$xaHR$Pwb^@cJ>Z6)$9>q}@S7F& zTNL^*4~9j=b0qCuBeM3;0ngb^gj;b?7xi5@^9SmGEx_|*vBVYr8h|@RI2jyjN8#0>Y2r$(>p@QHe2$!4`U0l39l+G&$1tsG9bOA*g4fMc!i_a();$wWy@faT zeK39alfnzj=2Mu_^#)p}+oA1|Q{5%94|@Pwel zXdo`f&JX0gz&^|mF2jQDZQ?4N+=WH+LFgPFzduC&J^s(gJ53nTlX24B_Q+J?D(A^7lb+`c$<7^% QN3vTbtKH(sW^7sde@9iYAOHXW literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/West b/testdata/zoneinfo/Australia/West new file mode 100644 index 0000000000000000000000000000000000000000..4f771828c9b54d9bcaef82639425df4b3559b5e1 GIT binary patch literal 306 zcmWHE%1kq2AP5+NDnJ+nLI`US1}b9)V!r=CP_j(y35cHKcW(ih-s7zRqECmMhtS6x z!QyAO7lG-s%aa!X^)hhs|Ax@pB*3&3V-kd3UJs@Aq-p~ IQrChD0G5hMm;e9( literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Australia/Yancowinna b/testdata/zoneinfo/Australia/Yancowinna new file mode 100644 index 0000000000000000000000000000000000000000..947b50995f4045ee6562cae21120dc8a05687653 GIT binary patch literal 941 zcmb`@?MqWp90%|-cZYY&XTu`fa$6GC-0n7$X+F)nC4#fi8<=1am0}Md3bG6;$l;|# zM5#syNioz2fN@HuYhizMQ z+6<~xl9$isYO!#f@J?|NLYVTo|c^ zZ-=`uzStwFbPs)71r(C)B4xvI8?xb7IZTuU?nf&$rhey6=%H!-HQaGON2K*hpT5E5 zYY8yrc^sym`U=ycV=%q!70d|Vf|-_4xU=CBck?F9@*RV_lKNHJf4B7lH?G1xx)68d zJj`Bo!M!~-&^(h4Etem{eRp4ov`@~-2(tD12WYE&fPQ=H2HbD!hPl=6x$8gSfxHRs z;yajUjB=lh!-H#G@KAI~rE?t1cVK?_8FW4kLs!FXC=E11chhO;X)l4^QW+N1S>R!F zE-dsg?%zb{%QlO2j&EfRx#-Upa`E&W@{!N0$R)8KuypDrEQ`#-@_R8@aqcnn-mH&D^$s(Ev8(;e$k^bh tE`_m3lo@M63iAi+wMIr0P?(8+^NWhTl3xxej*we&x}B0ER6w}ArhoaP!bkuB literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Brazil/Acre b/testdata/zoneinfo/Brazil/Acre new file mode 100644 index 0000000000000000000000000000000000000000..fb5185ca60283bd56f795e9a956274c0b6e63325 GIT binary patch literal 418 zcmWHE%1kq2AP5+NDnJ+nLI`V-2P$I$VxIp%Fl|-a1Q5N0KaBxQ|BX2SqIZ4_2msN$ z?oDt2(YGv4f%&)Ih=J)ll7BCN#P94Z1H~SZufB)__F#kb_KbZezhBR3H zSJo;p|J#8Eu>5yEs{7CynFoMwXOKO) zDgZ>wReU}GqU9F^UI5Vw#;*^6XvM}>u)GrY6ENQ+p&rZ+s%JUC#E1tnGyVU6pn!ql l|Nr9$7+HV;v4MdD#Aaae@eN_nH825UQwA;@AZcgH1pwW1w6g#J literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Brazil/DeNoronha b/testdata/zoneinfo/Brazil/DeNoronha new file mode 100644 index 0000000000000000000000000000000000000000..9e74745ca79137918281337fa270c5fec4bd7da1 GIT binary patch literal 484 zcmWHE%1kq2AP5+NDnJ+nLI`V72P$I*VxIp%Fl|+83W(mpZ+!tw|23KbqIZ5&QvlJs z?xhKU=vx*G!2DaU-+<{ml9v~N#P96%2Fu_5%?=j7H~RvZfB$X|nExO|70mxK{UccY zSJnV9|J#8uu>5yEfe9dUegw*a`9F?t2h0EBIs#VzYsD+D{O{L4!18~(^Cy7(DSNU( z0YuAHoCNdb7pN})@fC~@g87P#(F!2G68A1JUpazl0f?{sC`kZBtC~Mq0H&|(1oO?m z?Ev#Fc9etpmiMnJfaEP-GJ^G6pZExtx5;Oiz{E%t{Qv*q90rE}|37|UWcmO9@dE}9 VAKwrLT?0cPHe%qi0g`q`TmX|XySo4Y literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Brazil/East b/testdata/zoneinfo/Brazil/East new file mode 100644 index 0000000000000000000000000000000000000000..a16da2c4d5a980cd944d86c34ea8a2f597e39b71 GIT binary patch literal 952 zcmcJ}-%C?r9LMozR#LOHE+Q(_$A-vi+G%I$EHi7^Ty56!U~@(Y)zG>qqNpwcqmn=< z?3Z9S4_$vgW7q3dYIPf`F{QZuX@JWm)GV zJT?TE6y;&R%PaZ(ta7>bTCra-`xg7&z8mP3lWFuFw_WHvhb{D~Gr91t!7lXb z`XBJ_uD@_i*(kiH!-V&)`_7p>zVK_J#-c2c1k=9Plx;p2X|fo+5}pA*(TdpY$+ zM-JRLvH^}{O~aAi1-NM{0Y`5daI?{(%h%Y^);Q0y{kM;0jRhIAtaQq@)UrOjW6Ogf Rjg=~H`KZiZCBLgx`#+zs5jOw; literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Brazil/West b/testdata/zoneinfo/Brazil/West new file mode 100644 index 0000000000000000000000000000000000000000..59c952ebc65169dce30078a3e1ee371e0da52ae4 GIT binary patch literal 412 zcmWHE%1kq2AP5+NDnJ+nLI`V-2P$I*VxIp%Fl|-63y9vqAN~PM|MlAdqIZ6Dasbi0 z?ll>J=vx+h!2DZpIKcEB$@d39;&*nYgXQo3RtAgToBamNzkhcHnExQe5zPNGgBPs+ zD{Bsz|Ls5#SpGYo&IXV-LhoqO>@p^wOVUsb1!a_h#+h32XiZ-QDS9*B1JEZAyHA0FetGf zW&{eewrsjAon_86r)6eal=d>U96^wjMNn1*(l2(O@BRSmT+aF2?{l7e;9jn^^iX9k zGwo2o*}QD?X!_hsubkwr_9i6sD{mDGVHg=4ah!)3*N})!PbN`F~8|; zbk5D`{m8f86vMXA7TEsO2mL-7?C|WcQUC4p0^~b2hheA9?4kNydnfEFR>44Fsg&y7 z8W#Cp?s3?Y{4?g<6zu&z2JcVQN~yo^?GG3Xe}Mfx5jfzk@zDN*h5+(IS0)@hQ4b#- zya0zvPQu5V)gI~}-mnMx$;Lq#Dw#k%6kPi!_7 z$-Y8S>N}VoKN9oT02EJkz>J6oN`~rSX0V^7bF$j}a9N`pF2Cr6D^6EK=@C0zxwjmy zGFzc+lL@X?=0SOu0H;aOZ*G`0?%at literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/CST6CDT b/testdata/zoneinfo/CST6CDT new file mode 100644 index 0000000000000000000000000000000000000000..b016880653929aa40dd5ac0e82e4094a9d787cdf GIT binary patch literal 1754 zcmb``YfzL`7{Kwv{UQjZBm$vHxgogR;v%kz!4Ba>SgseW(IHKuX<|#1ai+m_B26cw zG{@}1#anoxMK?ksVMQVaYbHU74c!*9l`v%$Qv}*=&;OI(^h4*J^FHVIT+aLH)vPF3 z8!zs=T$~+p%cZ&hh~C-e>D<8%=UVAzuavR;P_$0Qitp}fWvtvX5m$ZIi}#%^5;DL4 z-8(iJ52!n-A6#w1hZdWte-*Tc{_2EATx~Z{KQie{e8jvPA06I=k2MwJnyx(jb$Kq< z8`5!Y$y|K=i&Z-L-4prCwK5vsS%AOEOvQCCN8oQ2VYpu9flqqcaYN`8++elfMh|x( z?`dpn!QWrD;!}FFP3D_g+i`Q55gS)@~%Uh-)mflFPit@ONT$w%DlO0BmRBc+t^b667DO|;Qo?%_>Zh4 ze0k+G{O2;2P0m|0RYJxq$>DfF5sv?wBJiM>z=OB@@l|U-{=2&sUu$c{*PHva@}42R zMJJ=J;tak~)`D+tI*5l058zv?w&H(sw&2_I3-Fzo*YL=b@7d%%cLNsUQSW>_I+8DB zerzBMkN0HZf7_$5{bUq&RQucH|0F*3C%9}K!mhJ2I~3R_@C5d$*)Q9Luk8~&!Lp0GpQ+X+^Zv&5cw)m&9B_E2OpCz1Mfjm@Mfl;3 zOYx+FrFe2~3J%Ij!H>)d!BZkbaPW*|tvpQi9>*cBQ*p@6V4X~a_Ko4NbEEjt)0c4g z@r!s`RWqKxAwaf^$2M2t8B1>9h}TcqVA zC!FjRhEqZZZ1Rv|wc|Ns9XPekg6H-g!z%r_PA29xeu$qgGvoQ6YjIkk5icm+p_P5l zUKb;^>N zQX4A^6R+W|a5vB(0vE50c3D6P3YUX6KxDm~DXg)sn+zKjO<-6}TzP ziGPYO!p+il+!F96Zc+1btLF_x>|Z(jiY(Govl6!zF2`zdGH%aFz*h?<<7*3oaYuTn zD)u_ZO>~RwiZI|VZ$Iw#y@tE%Tk-E5XYqAs4fbv=QN&*F`a)UcjWwI`&8J?(e=l8y z|4Gik|HdrFw<2@c@AI?Ze&ZtCe`}#Co^!iv1|DdR#)EZ!c&K6w)((2z;{PD+=ut%& z-fhGq);8dgxjnL|`zU`YB1g#$*f*sf-(@Yw#;`JcxBti3Bz=TUJ+I+=)U|kY%ZF}B zKli$_@tDe2vESi*Rn+}IeGHE+T!F`}OT^=IX5$IjAvj=x83!f|;h@MtJaLLymh^L< zu?+_s263==KoNCwdm9d^_uxsjwfKIg3y1FAkHhkNRefBVym1qrl647BUA5OO>f!Mx z@B<6q!qWmi!4cD+#Suft6@5&KGNt1v&kj7jI|@Hovkpf$J}Qg38O2XvOIak2DVU3` z+fCT^e735ONwIm?@yzr&IBwYwI6h($o)zoB5BX|1!TgIlOy zUn6~nxiH)>_}_U=JEQ+}O}p$i_-NXBmt^GgXx{x7XV|5Asrt>-?+X3OcFCk8PA^7h S%(TQ>tkD@Zo5g0an*IaqsOC)o literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Canada/Central b/testdata/zoneinfo/Canada/Central new file mode 100644 index 0000000000000000000000000000000000000000..7e646d18e18851bfde743b379e52df4ec5b5a20f GIT binary patch literal 1294 zcmciBZ!FYt0LSs~`O}?4B&X{LQQZ!myYnZ1OJT+`;uO_dnv$NlRLleVwQTVyQY*W4 z(LBi7!mRn%q?p;t8W*|fx+IxDC2aZEUBB<=*K^PM-oC%r_x=6-dGg(rRSorZZ6vxUrEG!rn{qRH z$afj{hqCRkuP?ty=>7NUXVJqM!{`z30rZEER`e)oL>ojkXoIN=Jx2KGvHsKOapQf4 ze(zI5rG{$kDn@^5NvPk#h7xA{ZM6AyZPggkHryjx~yRrC{DUzRX*VUukSZBsYkmY8|SR~Vtd`yI4% z?uJ6r%(?Iw+MBAOgW)Bi!?F7sdTV^#BFR5cN@5z1}`BnQb= Oaz#M0QYlx;6~e!?Qp8jM literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Canada/Eastern b/testdata/zoneinfo/Canada/Eastern new file mode 100644 index 0000000000000000000000000000000000000000..668e70d765dc3fb0eda16fb0f1932af607b53412 GIT binary patch literal 1717 zcmb`{|5Fro9LMnm5$Qky5i`X?O^-vkJ0Sc57Nj6yU05BHTItph4D|y$R){l(eIbcv z8YZEfvcXUkQ0oLegCM>r5lu6x;8#LijK~mh#jk-L?dRDa;5gI!=CiMReD?L(`{~xc zCNn)!y63p*4Y9=7?|o#yUK_8kDP#JqAIcdJSyEG^h}`kRWm)7m`Q|o}rC(LWi`-f4 zsfpZ`T8YcHyn=U!fJ!V)-mwF<`}egMLxO{@znI`upze!~2~U{B75# z_`A>jv7;I)Z%KeUadNt8M8Gjz1N^QlbgB$Ug=n8yRD#hmlKf#?* zTV-*s(^amB>Q}=Eh+P@IbZ^*}C z9d=o-N#P}#*nDsSw&XsItwqytL`H@tdXei#a8yz}Pdf|odk6w!OU?mhfO;c*6{=d6pW6okp(%)B2ZXWtu@_^*UcOR~P&)DozVuHS2 f(ASIlT4|RII->Q>Fk6&4(rgX0MMRh*%vQs{dz=-7 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Canada/Mountain b/testdata/zoneinfo/Canada/Mountain new file mode 100644 index 0000000000000000000000000000000000000000..645ee9453073acf4cff9f9420b358a8ebbe40f93 GIT binary patch literal 970 zcmbW#TSydP6bJBcZFP62EvItLOV+04w%a!D#ZB#MwVM?!iH?N5gkXxkBn3ea)s!n_ zFHJ>Ih&Jn`j6jWEiiOmqpqmdH1$No29t?|!3JMIT@BE+kP3RlWobx;1IWP|+A82au zu{n={Pf*a2=U%DhW2rncbbihz#wRIv-5pdZUyGR(%G#9+uoiEFyU%@wdm?F!?t7b` zz13<-HQ2m!LJsYi`QkL|FY&2=3d#~(&sZ{UA9U& zweqh*IjwvKHhB`T+5Qf;h$FDThGF4*H#~nb3R@?J`8Hzdvo33$V!Z}7%9F?iFEpi;3p)(LMp{}tZaaSAR!JPvP*bSTu= zzHbQLQGWss7F~ox!Gmz<=R+~Yko3$mCL#IaKWbgStTFzZ-qH+4UGG$x8MPH}ac@{= g;UJG{9{YJz%1q!W;Z1kgFZm>oJM8sJUdbc;1G${^$p8QV literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Canada/Newfoundland b/testdata/zoneinfo/Canada/Newfoundland new file mode 100644 index 0000000000000000000000000000000000000000..94d790baaccb72298bb577041cf3c8400339a7da GIT binary patch literal 1878 zcmbW%e^AqP7zgl;A7duvm!mrvpsq3BxPM+Q2^!F4fX{}t+DbGN?phBZp!+T zdu^15WS(rw!v`a`QGQds05@pn;cwMr@R9Ay(0^3k1ve(&gY~h8;qO+A!c9KaaMOJg zd~CcJZoaI8zrV1jm%d{#Rlz?rtKpU-+HF)nUXu>De)s|WW2pc>QCtL{RPx}qbUAEH zn1tK;e7Iw&e>UCI8JKEAx^KciO~t~dp$o8Ct9+Zz&3&9k%2Ou{5tLmVN1#ke9r5*fa*QbLvYWv18^^^4IYSbmDBk^ zq1{3`xL0nayqM*!pd5OW4-dy*hc79(u+{%8JQC-GM<(>}Xt1A(=0*q3SSW2{8u+rl z6z5~+t?=*ra^Wjl8GN-w3}35^g8#@2g~wlAfUgVOustKfO84Ff3ARu=_;avhdIolK zY_PL`2)=1I!;>v-@SolF@L#9Q3YwoXm{gRvboKCbtq#8Z{vLRytO|C$riR_QJK)(( z>F}MzH2AKd$U^tr3yg#3xN>;z?q)01=N)`_!MX~*Z{flZjDE1^sMA8fGuG!5Rtok< zy|7osdDy#rLP2$(LWhddH}5>mN$G+8M9nZa`WWmVR15Q1pTfLb@4}Bfq>|eJ<*MvZ_c;x$>nJIOeVLi{#jK zpTVoL3dhO(@SSkn>Qp%H!F~gi61Wuc&a8X~z8X@L0 z1`FWKB|&gz>qa=ZvX%Q literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Canada/Pacific b/testdata/zoneinfo/Canada/Pacific new file mode 100644 index 0000000000000000000000000000000000000000..c998491112ea5e4430b8266498cf7f23e1266bc5 GIT binary patch literal 1330 zcmc)H>oZhw7zgm<&LSsSB-II7i`K6DC5aemGRRVTp){q@OoNo_jhHl(>EcMu)HH1; zy~)(LjA=$AhBv0B)Y$D}(Iyo;i(Jb!r{C}U4|v&g<~h&#JoEki-W>Jeg8X1+%`zhi z+O*VbAE_WQE7C3^sodDoaXK}v?E;+-+oU|5Z>l_Ct@m6JwKmU}rBhex#L@X7-WL9t zH4T5_Oz`J09o)yfh4s?suzsik?qBT{==p(89v(Ebz+dX0@pNzKxC4K!x(N?y&cojd zis0e09Qb?60r*F54E$3b3Xdco;^;l2&KWG7Mp-m$oC$$VHlDCaD}~2KR^jpHd3d6G z2>w;0hbJ3X1bWX@aT`2cZGdMkb@6mRTi6ND9eE7@POF3e#9e{sgDT+#zdD>>bjpX9 zY%AfVh07ehXW5t!uk@XO|GwG_ueK(`;uC+C{$J*f)r8|64`%Z^oS(^uUs-CfI(c5q8k`unZ~3&Kh{#i$>U~zJa5A_FfIV zzKVyPFP6X?3eLbTIa#nYMGd<~MZj+IaM;}|lV?b6v~!0&%)?-hnNWf5Hx0YNo?2IU zbJrrgrFj9~`e*>=N&`3&XSP+e!(Q2ru=lBcmhOGRCgJV-Uc$c8URdU@fn}=`0*Ntl zNjWSxyodcw$KZgDW;jq+#?#ymO)acwISL1ror9IN39#zqEsn&P;1VA=B>5~HnrRJ( z$+F?_U?Uu16A4FpTCwC96FKSuM=g)S(cLR>%)o1SXOp`?VoYq?Q+QYP5*&B`2E4m) z5RR{`=V>k>tpnb3{2H7XB*00Dr{Sbo9cON4ZedAY|LqaQ>$e$36d&+rmZDf)&e-DH o0dIDHs+vhpB%Mk6An9~9BO!<+%fQqSMX*8{n5t4KR0^f!AM7IBd;kCd literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Canada/Saskatchewan b/testdata/zoneinfo/Canada/Saskatchewan new file mode 100644 index 0000000000000000000000000000000000000000..a3f8217a544ebb0993473bbffaae8e2d723c4ec3 GIT binary patch literal 638 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1uA0$Vu}Ai(Drw-42Yh$WBmjWJ%2ZQ1Bl+5>i+>m zZ!_?C0HU|M8iM&d1hl~XovOlM{>~3PVE%4Cg94Dc-RIwd`Fq|8f%$uPawmYq4;68M z)gMlL4VFI=_zKKFYB3osf6VX&T9aP-`m#?=HKsZ0P`Qr%LMZuW+s98kLtX^{KuXy zVE&UhT`>QtrW%<4%-u@>WX^LTX9f`cLR|;UfAL8b%zypt1DOBj+GQ~R?XgP&OpI6| zGYeK>h+@|N|K~no02;A+0V4~LJ%ND(%;o`;Kr2=+U=Z=~4Po$g0pegF4hQ0Z5C&%; Kn+r&oaRC5Dz-C|o literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Canada/Yukon b/testdata/zoneinfo/Canada/Yukon new file mode 100644 index 0000000000000000000000000000000000000000..40baa9aba2a879f7a38a5a0f67e16e7a2d677a5e GIT binary patch literal 1029 zcmb``+e?#S90%}c%R>%@K_2GX?Df=~rmMBNdFW)5G23*t*VSxxViZb|bXYef6Go5` zj-D^(Lp;cM)!Uz6v+Zzkr)3RT9t~)p2-Dls!d&2i4yw}nZhxZ1q!#0Bix7yCYtv`|i)tJ3@5by2DY1ol>8g|4+ z;I^f9c;9GDqB?WF?Ztc7mB?8Q>`Nu#u6rr?@WM3g4}XBW<0J5qz%%%0)c;K`qiGVK=v2=PUB+H<4AEO&O=VGV7#8^a@&(EwFXD#1ZsnaDgpN+;tbCAZ(O&4yua8tS{ J6|`9t{{Yyp^R)l~ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Chile/Continental b/testdata/zoneinfo/Chile/Continental new file mode 100644 index 0000000000000000000000000000000000000000..d3fc9b8343369abf5f14be781397f426c5969608 GIT binary patch literal 1354 zcmciASx8h-7zgk(i%aUHrn#jxS(@cGI-`!J{w_u1wUu^oxv)nZLRG`0wkg7?ZHPPX8fpsyL2um`9VX52~Hq)eWG^T%m z47RWyge_jr!j_8;@QPsrY&G>2wr>BVpvQ>K&^Rn>7=u?{9)N92dtkd0MuCnI`-EnA zRdFBe;8O!TZodexwr}FuoRjwv*lDgBb}`R`T@1Tn*O_S8ty>MRd9LROE%$S7ut%2$ zUR(JaUe_px9C>;aj%uHUHRYXfbb|rrG9L5v7>OzE zg=3XB;B5)#;W&pgur{cNqhmz-r4o*}Z-(P%#R~R3VXg*F9ISwM7_#A{euDYr?g%*L zfd%r^^m>8NO1spFJUw;--dT4R-sSs^V|j+Y3f5V_g0sSAa6YT+qrmbU=ZA1k<1;vS zz60Jhj@&vZe2TpNfME6PLdKB9Af=e?+`@M5cy1BKLJ8HFL z*^tl)mMm<`uNi4j0-YtK@iotiry5Uu|BXC$kGaSCV2VNc8#k0AH_)~DiLK7V6XNM!*2jHmr zY&d$z0Iz*f!4VqkI-}v3K_k4r;TOE2Jr<5VEmN_%jZP`NDg7tBx$rH#C29_iGZ2B$ zi2FVX$A9_;Z=JmkCoJBFx80lI+1&P-o3Qf6RXB0P1t+zhg_AGW!ztA@u{0@fVEjOD)wE+<-@7+99XXyh12||F>fHju;FO{`sweK0-=%7{~q4)SOI5Vn1ZwV zJg~8T0M2%~VXou}PuIxKy1TGRdk5ZSxdi8gU4+f*VUCUw^XCRQH?$kh^+;9hyJevn z&Kq~ad)x=%{857Wf}sr9`oJIk!s1qe&?vexfPS%Q7T(*^0q;|O`dr+jF*HISZ%~iGfAbV gnMN~}1ZGkh_4J);OthvatCRI98cm{A_xBX|2T4)%{r~^~ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Cuba b/testdata/zoneinfo/Cuba new file mode 100644 index 0000000000000000000000000000000000000000..e06629d36841463326ff3350bc2f94d0417c3cdd GIT binary patch literal 1117 zcmciB?@Lor9LMpqO--himAY(MD@|AFbhCvue_Zg_N;j`;5NU!$Ej6TwU{M$m*yb{^ zRfmF~ph?5I`YrAJSR9`zG9PUo{TTJ(@mE)d5(KfjZsf3ZTITc*bIdXP$RR zwC>M7iSz#cdidQ$5@G;7Ch6?vKcw0^J`it%Rdt2loGjEbx-I3;Ta3 z2jOK;E4(tsVA&g%_-|mWcOgJgcqS#P(mesI&MpY#xRx&>HQt;mQ4@sM@S1e1Ku**R zz=@Gd5?ReWu=+>4Ku(%(gOfjYN#wOsExc~L6<$AbA5Q7)6KH=!!?yr+qsu2zHyQnK zYV}<>t?4S9o)deX#&QDQoY0K@3~e=>u~-goS<=JWx5os=$JUS<&KxR(w_S9Iw7$JZ z2kRQm@QyP|cxOce&S%-b!r56x@Gip?oRfAP&ebePjE~$EFYebzX0g8eb2q$aZWP}8 z;xwG+y94Lnv%!Ym3vj{Z0=UrK2pdn;qNXDyXi-f*x=%PN((}xjAJF}#;aHb_Xt6f- z-ijB40XlbJ=@EKx>M3do-9$@lua1`<$@gYC@|jWACNv=MA_fTZ3~o zp9axGs%WfFMC>09hv3@&4z$i6!Mg2QH)?-rN9*15sCfIgs8A{Y(}({*ry1i{iN(qC u8%dEU%j3f=xz6TfRz52#`E)p$nqSNudA1^h$xv8Om}fH@4MzUWsQw4Ss79v% literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/EET b/testdata/zoneinfo/EET new file mode 100644 index 0000000000000000000000000000000000000000..231bf9c3b713e3676dbd8f3ced867973c601e104 GIT binary patch literal 682 zcmWHE%1kq2AP5+NDnJ+nLI`Uy2P$I&VyXW?P+~vB1w_woP;3CvJ8ND(0Mp0TUjWf3 zKP7|trvz36fcR&gdkcW*v#WeQfar6JB*60LCubIb`1gh9C4lMeTmc~WaK4F40MXnM zUm*0^bs#PS&))f9ns-TP1Bk)b6APyKTg<_3w6toIV3%fNXfcPTD zhrs5GD!-lp;)@C20n_5lXCd_GePCMR@p>>Vd3gbtmO4BUOiSjNmeXKbzhn=XHb_|urVV3n3NSJ= zF*C8Uu(E(?;vq1QY(P!|k}M1iS_X_9K<_Is@B#y0fI$$%W)$`D4PkHuVprE-5D~)Q f48}kX7m%lG1QOTrHP$oLGtf8I@ijC6vrM=EZ;PKG literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/EST b/testdata/zoneinfo/EST new file mode 100644 index 0000000000000000000000000000000000000000..9154643f4c9189998392afb8a93e2e2eb9eaecf5 GIT binary patch literal 149 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%klC�HV9UB)(u|`u~4x0Rsb&lwe@_ Z|9|HO1`Z$J5C&%;b`1_;-~tk+Tmb&%9IgNW literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/EST5EDT b/testdata/zoneinfo/EST5EDT new file mode 100644 index 0000000000000000000000000000000000000000..2b6c2eea14df07392729ae9f5712a44ec4f02bae GIT binary patch literal 1744 zcmb8vc~FdD90%~HLuD)FSXb_AZECl}O63S8VJF8nxh5}Dn&pq)VT2iS6v+%R8pbh8 zbU9ZSR%{`w$+%iaIr5f-h*vpM?0TNB|CxR}&wlswdw;)Y|Jv0o(ys6$|1BFj!450U z|5x;MtP4H8th8e6#JwzaIfHnX$F6+fSRUU&;LO8!;S+K7@X6%&0(+jd@;sca%Ej}X z`IRE;=StJyJpZ$Bo+TUer+e;!PuHfxXIgpqtWgV}GtYz1>t@0F!m;p$ByTwX=vNYrz$W!Zp51fXEeNjgj)5!MqB+*D zbPa(ks{`RXJ4Lu^_}9P5bzslDwn1d`k3wF;kE2ZRlOd(>Q&k>ZO)}vc=`OfNNQR$T za(TA@yetlWQJV(8JhhEu{aWKH_*GggEa=p5opw50pQMCeM~sFWV!Fd`q7?$$Zw&Vq zS-uT$hu_KE;P<^-;3kJJaMSlk@P|e-{PD>}xY<+;e=0R|?4Hm1DxRfytQh{1UIe#n zJ_xra9Du(r-2i`!Tn~SrycqtWTm-j`UMH}7e!5M7+npA|?QIK0*6(;14F9SQf`3;G zge{i`z}8%=Kz}2I9JGimY*On4mbU8z*p9bw%=X-Go@JLg0>{!JY zr4e$tcc2U0NA3*w9VX`pt$t3;aDQ88xPOa;XMK;lW_ZBEkMO|j_u)bL_u#>q`S6fL zg8iXe_rt@Y>fzxl^#Y+aLRAiroVgDkCC!0lo@-#4r0bS00!_gZ|T%(YMJJ2mCH46+nSoWw9<*%M#eTu88u6kiej;Z)WRWASVq`B z7zHWasI-e&mZ3rh<)v~NCMeVvk;_b%PQ~T2_dNXpe(a3x+3!5h3qw@r9VnEL1rLi^ z&^JBmg&Gk50gKhK<#ZOVF@ou40|>*2QzR`l;) zIpE$4g|PWf3H<()4(>a9FNZ#7OW2R+ZH^dt#J2?=>DOWZW7KJAw3C)hLU z8tj$E!G4inzmZ;eN6688kNKcydmcy6?vV zE_h3Isf93StJYwqx$UUdLNiUKfzx-U!14eW_8DRxoMAZ#XL8)&%%>dev+Q5t?DH+? zw-2&(ggJ`*HuQ?h-RKoJoaj}>8(~#LC3@9htB#oybwmaFf^56ajrD(D%zu-H{wAS_ s*0LSs)l?_R(6_xt_b-EO;|Jp6o=H?`&9 zFgwUehJ5Q=GMH@!%xSsFjIbV_hM4VElK}^e%!xT&5}KG>*b49F>-@t7WdCCcAN|BT5!Rb6!lxDr*7-iz zprQn1f8(GAHVuctXZ5}CdDR9@)?eJJLpNvJ!V6D-|tkR=Tpw17xFHlHIe@4#mf=s9|2MDXT)K+>!gd;j`g6IH>S`l%{A!NX&tzhTmsjXjj`l^q7&OLAaXqvP&c?3>KXb%eMuUt z$^jbkV^}*jAa6kijjHWviW$b;60}Li8rrnd0&NyIiss)IL-UYkXpzK++oc82Qn3iF zT-50lGpv2up^eU4Xlq-{I#B_4Xw#rwYX-C*FXEH?97@aK&X!c@cr6_| z34*%<<;LKBpvWm;0X&eZ7A^HaAzyCZB43bkvnbSX1P90&+W6U*=2~R0=B@qQlCE^2O#(e}YDen*dSF1_@ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT b/testdata/zoneinfo/Etc/GMT new file mode 100644 index 0000000000000000000000000000000000000000..157573b1d340e0f57a0dd4d9698bd3798cbf7136 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT+0 b/testdata/zoneinfo/Etc/GMT+0 new file mode 100644 index 0000000000000000000000000000000000000000..157573b1d340e0f57a0dd4d9698bd3798cbf7136 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT+1 b/testdata/zoneinfo/Etc/GMT+1 new file mode 100644 index 0000000000000000000000000000000000000000..98d5dcf917c6f1d9bd0018db0dc4dd0590e6a8ca GIT binary patch literal 113 qcmWHE%1kq2AP5+NDnJ+nLWtMG^8f$G4-5>t28Ik=HbBzOkP859w+SEs literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT+10 b/testdata/zoneinfo/Etc/GMT+10 new file mode 100644 index 0000000000000000000000000000000000000000..ecb287e667868e92d97cdf5fee601e09cded0ff2 GIT binary patch literal 114 rcmWHE%1kq2AP5+NDnJ+nLWtMG^8bHv0t17tp#cMz4Un`mG~faNWzh&i literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT+11 b/testdata/zoneinfo/Etc/GMT+11 new file mode 100644 index 0000000000000000000000000000000000000000..e941412971a4d805e311e8e4e7eb37e10994e4be GIT binary patch literal 114 rcmWHE%1kq2AP5+NDnJ+nLWtMG^8bHo00V=rp&h_ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT+5 b/testdata/zoneinfo/Etc/GMT+5 new file mode 100644 index 0000000000000000000000000000000000000000..589990ae8966d1af67f1e05c21e14149adec2089 GIT binary patch literal 113 qcmWHE%1kq2AP5+NDnJ+nLWtMG^8f$N4Gavr2Br*LHbBzOlnVf6w+OTV literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT+6 b/testdata/zoneinfo/Etc/GMT+6 new file mode 100644 index 0000000000000000000000000000000000000000..fcb60ca2465a3e0c4febd41ac1a05bbb39fd96ed GIT binary patch literal 113 qcmWHE%1kq2AP5+NDnJ+nLWtMG^8f$p1q=+j24)OgHbBzOj0*r{_XwE) literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT+7 b/testdata/zoneinfo/Etc/GMT+7 new file mode 100644 index 0000000000000000000000000000000000000000..c0427a40eef929dcf25451be77c74af6e9111065 GIT binary patch literal 113 qcmWHE%1kq2AP5+NDnJ+nLWtMG^8f$b2@DLn2IdT0HbBzOoC^SBHwbd{4F!k* literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT-10 b/testdata/zoneinfo/Etc/GMT-10 new file mode 100644 index 0000000000000000000000000000000000000000..11d988e10a3e318a7cba485d995872636d1acaf0 GIT binary patch literal 115 scmWHE%1kq2AP5+NDnJ+nLWtMG!obk8fPq2V(13x<21wfJ8X9l`08Lp2#sB~S literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT-11 b/testdata/zoneinfo/Etc/GMT-11 new file mode 100644 index 0000000000000000000000000000000000000000..f4c5d5cc29b5c1687e9728b6b63cd2a5328c9dfb GIT binary patch literal 115 scmWHE%1kq2AP5+NDnJ+nLWtMG!oV10?Nqjko|e4F#zH literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT-3 b/testdata/zoneinfo/Etc/GMT-3 new file mode 100644 index 0000000000000000000000000000000000000000..4eb17ff0057b8843a0b840c6fef4b77accfe43b5 GIT binary patch literal 114 qcmWHE%1kq2AP5+NDnJ+nLWtMG!oZ+qz`&qwV9dZ}10?Nqjky3h4F$>o literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT-4 b/testdata/zoneinfo/Etc/GMT-4 new file mode 100644 index 0000000000000000000000000000000000000000..13aef80cbbcf0c938b8d11d92b0755e146a501d2 GIT binary patch literal 114 qcmWHE%1kq2AP5+NDnJ+nLWtMG!oXnRz`&qwV8Xy<10?NqO}GF%4F&4} literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT-5 b/testdata/zoneinfo/Etc/GMT-5 new file mode 100644 index 0000000000000000000000000000000000000000..83a28169552f4fd39e9d0322398d787aad303e3c GIT binary patch literal 114 qcmWHE%1kq2AP5+NDnJ+nLWtMG!oc7bz`&qwV9LN{10?NqO}PL)4F(JV literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT-6 b/testdata/zoneinfo/Etc/GMT-6 new file mode 100644 index 0000000000000000000000000000000000000000..79a983e5454a35f134cd4ad736ed912f3deae64f GIT binary patch literal 114 pcmWHE%1kq2AP5+NDnJ+nLWtMG0#u#Az@Tkl#=vC*B<*y~xBx#51}y*p literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT-7 b/testdata/zoneinfo/Etc/GMT-7 new file mode 100644 index 0000000000000000000000000000000000000000..e136690e165a933fbad2fdc0aba8d97886714fe0 GIT binary patch literal 114 qcmWHE%1kq2AP5+NDnJ+nLWtMG!oZMJz`&qwV9vm010?Nq&A9+U4F*mC literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT-8 b/testdata/zoneinfo/Etc/GMT-8 new file mode 100644 index 0000000000000000000000000000000000000000..bc70fe416fdbe3abb2c636a7bc1485b79e03af13 GIT binary patch literal 114 qcmWHE%1kq2AP5+NDnJ+nLWtMG!oX0_z`&qwV8Os;10?NqEw}(f4F+!j literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/GMT-9 b/testdata/zoneinfo/Etc/GMT-9 new file mode 100644 index 0000000000000000000000000000000000000000..d18cedd524f4cc132106d822fa8bb9bd3779edab GIT binary patch literal 114 rcmWHE%1kq2AP5+NDnJ+nLWtMG!oW~Bfq_BWz>21wfJT5^GWBn-F!C&C4S literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/UTC b/testdata/zoneinfo/Etc/UTC new file mode 100644 index 0000000000000000000000000000000000000000..00841a62213e6cccf7f0b7353e5e8ae214185486 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/Universal b/testdata/zoneinfo/Etc/Universal new file mode 100644 index 0000000000000000000000000000000000000000..00841a62213e6cccf7f0b7353e5e8ae214185486 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Etc/Zulu b/testdata/zoneinfo/Etc/Zulu new file mode 100644 index 0000000000000000000000000000000000000000..00841a62213e6cccf7f0b7353e5e8ae214185486 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Amsterdam b/testdata/zoneinfo/Europe/Amsterdam new file mode 100644 index 0000000000000000000000000000000000000000..4a6fa1d4945d6646652e2972ee8b632ca64c00cc GIT binary patch literal 1071 zcmb8s?MqWp90%|_-CD>^Z?opIWv;buxjFBgjb8LZnS&xHt1c4eqEL*$7i*31MG%G2 zi}qp-p(0Du*)pcihib#khtv$rWrd-`S4l`@7DQydsdK*j1FUm6=X1X2ocrT)uULJq zzL;6JNyrU4XcO0eR{_FC2aGR zdFlCsi)+a3E-i9LRT4SikRf+kV#p75Cy|5v7<_bU33kalQm$6BwBF<8Ysew~19E8U zEOPgkdgPwqVdUP#9T>i@hkbo{u-|ovrF91U$Kar&06w{ps{2%6k)MfC7|B|N(b7gQ zeJ=WS7I{c@9(ibf1;&1LVm}^9AP*QE2d(b5X@ygs<|(iNEB;D(x-TDYr1gxZ5PxZ7ZXIyDdXuqw#QtUg+w z|4{<>e$>Hzb4pk+DTn&OHE0NYf`!dVXl$B>MV=TG>bjxHxxl4K{=G}nY2P6Gug);i zX8Q7qfJBP*Mly#Pmh6m56bzHeF)H%u@+ImDyU0`?7nw4mUJ!}}GMmV3wTWbqgAB4N VG|{EOZZ_^W3I@ALpca`k{sL)%tV93+ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Andorra b/testdata/zoneinfo/Europe/Andorra new file mode 100644 index 0000000000000000000000000000000000000000..38685d4219d244f56f665c8afb92eaa6737badb8 GIT binary patch literal 389 zcmWHE%1kq2AP5+NDnJ+nLI`V-1S(?zV!{7FP-nJz3W&bqcpIdhL1xW50T3-aXFiyg z>zM$i_1pp_iI+y?e literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Astrakhan b/testdata/zoneinfo/Europe/Astrakhan new file mode 100644 index 0000000000000000000000000000000000000000..aff8d82d2a2de0857f78217cc9d04a112d1e1a08 GIT binary patch literal 726 zcmajbTPTBJ9LMqJ^={F&3l|P!oAWG(F|%nHUS<}iq~*e)_$%Haw{N+K!C zh4Teh4oPmrT)9IjR}N`6QsnUbf9~Aud3&Bu-{*aw=i>FW^m@%K>=5`DG--IkACdTH zaz3Mf_*hpv{p5Z?*~s@;tYP7Vj8k8k$oQzB1V4mbQvJkE$b=g!-X~s;qcw-K_q4Cw z9EG|iKTMkJfyu+oFs080Q`>AX&7B3)?TIiWR|)l6MTqf{sr-Znxxq(mcvHiy>z5Ad z?6YTd&fYD|4FsWa?il8c?ZABh3N&@kz=HO}5S=#<%)`R6WoT&{f>zxKEHbzL`PB(+ znn53(v)xsri$7b?B}bX)(i=P4zUF{s2T8DeLJunz8I-({uyRZrqWh|xk7!5NH@aGX zfp$9X(KYfdv@87-?Rq_jwPN7Us|{H9Fahhgr=a_C)kpU?O!uQbZe0g;^Lva>5F`FQ zGC?MYw1j^|L1fIRqPwz9OvYGEqY%aai^TYzO%hb@1`o?I74m82)4~*XzLpy;ieIJ! Bh!p?; literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Athens b/testdata/zoneinfo/Europe/Athens new file mode 100644 index 0000000000000000000000000000000000000000..231bf9c3b713e3676dbd8f3ced867973c601e104 GIT binary patch literal 682 zcmWHE%1kq2AP5+NDnJ+nLI`Uy2P$I&VyXW?P+~vB1w_woP;3CvJ8ND(0Mp0TUjWf3 zKP7|trvz36fcR&gdkcW*v#WeQfar6JB*60LCubIb`1gh9C4lMeTmc~WaK4F40MXnM zUm*0^bs#PS&))f9ns-TP1Bk)b6APyKTg<_3w6toIV3%fNXfcPTD zhrs5GD!-lp;)@C20n_5lXCd_GePCMR@p>>Vd3gbtmO4BUOiSjNmeXKbzhn=XHb_|urVV3n3NSJ= zF*C8Uu(E(?;vq1QY(P!|k}M1iS_X_9K<_Is@B#y0fI$$%W)$`D4PkHuVprE-5D~)Q f48}kX7m%lG1QOTrHP$oLGtf8I@ijC6vrM=EZ;PKG literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Belfast b/testdata/zoneinfo/Europe/Belfast new file mode 100644 index 0000000000000000000000000000000000000000..b9e95d92623c6cc4c35b16f7ceba3006f5ce4934 GIT binary patch literal 1599 zcmb8uc}SCC0LSrnPAl(aIc=KGEM>Ols~w0Dk_2U`XboCMsYHe-F-0ts2>*ysB4!wN zXug`Im0Dh9YNcu3<~b3|vqR^RM_Kb)z0dEZzr$yY&-;CjcjIM~2Ze{ZQ~w=2b_aQr zA^-o840f9V`(FQt9imf)&BS|7`3&qa5EIkdXmomZ4ZNS04l`0kkhxkeCi^mDm(f{g z)6fs%8_?PQW$>Zb66POm3xPS#buiaO$~mEB$bFtrU7Tu5%sbIe`rF&3=&E}*u=-*ue0OOD)+pj&ZD2M-_P_TyiLUdkhV_ab z%-8oB!X}}UitKAjJpr3L>|o172EN_ET#fuF2Uf=H)qNfwip=UBKqh~{X&~sOU(LWA{!JonV;k<(> z)_-|9qJLA|IiL~pcizbSYNCvMlX$V&uuyWDSD;8LP`FYd}W=Os4r1KgMeJP z#?TY4rIR={w$M-z$=RTTMl=4@aDk(Wc4EXtU=QX!EE6wBU{mt`Dq&7I6Z& z!7U4JRLnt3#|ah14xvXKwBolyYwKLj&(Gi{Z4wmKBtx6w9056Jn^yogS0_Td>ndoU z83DzS(a<5m4{q_5L&s28xK+9bZaaKLMegThVvTlo*@1SR-vuQ`=A3FFbkWSh?Il_$ zZR~6l` literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Belgrade b/testdata/zoneinfo/Europe/Belgrade new file mode 100644 index 0000000000000000000000000000000000000000..a1bf9281ed1bc2c9b82ee64efdca60b4af762ede GIT binary patch literal 478 zcmWHE%1kq2AP5+NDnJ+nLI`V70V-n#V&4Bi5NGqj14N%%p|-hMG`Exl*207zbD%{nkG zJ7+$amg|`SrsZoI!L&k75tvqtNe0tOJ|SRQ*~S%2tLT`4X;m3@Fs;TT0jAYiohN|I zSO01PrZt|bf@#gGVqjY9C_9+e-tq%X>nwQ*rgf*>0@Hder@^#-$sRCmkg^s`8^+!g zU}Pc;85o2uK=$(qFt7l9sldqL;~T=@>dvkd2lLM@at8CyPci}17n)ST^u;1E2)%6@ z14#X)hAgbsZ@%eS>ov zn7+w$5UlRz%L)NdI0*Z?fN2rqUlTxlQRUZQT1@y3m=T6)i30g!%~HS55%?40>vTCQgTn3k_;1k(yRMPOPnCK*gC`GkOJWgAy8t)gQF zrd4Is!L%BW1ejK5b)En+U;V2InAUiz3Z^x$ih*gZqwHW>d&>_nt+V7MnAV+g3ry>^ zoCeeSC40cMLCRV%Z5Vq~fQbn6S>(K|QN>!DsS}id!m568)i8~32&`2Z(8iT=r7z~E%5eAQn zSR@`x4U)2mMB@D@+So*-EE183h4cNpNEhekJHPw??l~v-NbP;SRouUWXDg^^NdIrC zXUh^vG^rc0hb!QuD z)uBa2nWjf#V>42rrMraPI zVA)X;EcbswaXkVn=EBf2aRMuc0?_K&g0{|(z{khMJP9#5_WPgAaf(U$F*YZ#>+AVs tj!PFf1@-t0ms{dmSvecqXp*=l7E;+ug^gOG+it10SVgzZN>-LhoqO>@p^wOVUsb1!a_h#+h32XiZ-QDS9*B1JEZAyHA0FetGf zW&{eewrsjAon_86r)6eal=d>U96^wjMNn1*(l2(O@BRSmT+aF2?{l7e;9jn^^iX9k zGwo2o*}QD?X!_hsubkwr_9i6sD{mDGVHg=4ah!)3*N})!PbN`F~8|; zbk5D`{m8f86vMXA7TEsO2mL-7?C|WcQUC4p0^~b2hheA9?4kNydnfEFR>44Fsg&y7 z8W#Cp?s3?Y{4?g<6zu&z2JcVQN~yo^?GG3Xe}Mfx5jfzk@zDN*h5+(IS0)@hQ4b#- zya0zvPQu5V)gI~}-mnMx$;Lq#Dw#k%6kPi!_7 z$-Y8S>N}VoKN9oT02EJkz>J6oN`~rSX0V^7bF$j}a9N`pF2Cr6D^6EK=@C0zxwjmy zGFzc+lL@X?=0SOu0H;aOZ*G`0?%at literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Bucharest b/testdata/zoneinfo/Europe/Bucharest new file mode 100644 index 0000000000000000000000000000000000000000..c4a391e73b97e1342d352c5cc15a0bace202deef GIT binary patch literal 661 zcmWHE%1kq2AP5+NDnJ+nLI`Uy2P$I$V!{7FkaPY42Z-Lj;S!kMY4_ncVy03^S6$1E_tZ$&ql-an%TOdsgT1=9yB;=uHw41X|vIKlx;AMr2* z(?>0o!1OTr-FD8I!q2LDrAX?a$`vQm-F}{!hqD7VOHh^d`;d5YG zoOwTl{=5N9OFUi(rX?>=0@G55o58g7p7jhMAhTuxn3kP05lqYVG=XXPnqn}mkdp$Y z6=Oodw33e-m{zs{1sel{ijD@DR+W(i(`r0iU|OBkv;o9W|H_pBqBWlU2Gg2X-hgSX zBX_~H_Lg&CT4%|AFs(af1DMupnGE)?e#s;--yo$F%r}f(_kaNijEbtk;b3&K=K&)# z6B&@1fkC1IWE7ADM!%K;BL^@z6c~7Yd_x$VfY{YF7(|3HZ~+NjBM?`|*I3U~&p_W; M$JfvR%rfBu03YwVYXATM literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Budapest b/testdata/zoneinfo/Europe/Budapest new file mode 100644 index 0000000000000000000000000000000000000000..940be4670a64ece1265dd28523d78a80f9008dd2 GIT binary patch literal 766 zcmbu*+be@%90%}sMj|w^1LkaI%xs2I?q*lKMcyk>ij=rm+6Co;wJW)J9U{zW&V^E3 zD9Z6d&WB+xv@nOeA?0ekzpp>Qh3D;gK7F6}_x#=iSJ_aX%ltV+LIq74+}}rvg)*@) z!@q^mDDQTV!(s9o=(_ch4)+pIj!dn>(KQ~9*$3eG(5{5;Pt>&{J1w!ulWafS|5!!8 z!{-v@qj@>%j-4jtlb$?yYE!|p!4?noJMY}LkQZe$Jb76nZ6{rYJE*(TtibD-X?PRz z`#g8R7V6!vE!e+z&iUxvL-{-2q{K9#VU*5KP`j1hp+DAqk z?<}M=^#sbIHlbX+{OgAkDjs@a%!M7s?sW5XE^d88LMj)QV7y}tCUo&Iv8@9pH8sQJ zs#=&*%E8nkGfdMKK$TJr)58={9c1FEzxp!|W_VRlvHTQ0uOyncJKS>nGFcA_aq?F|tlevNxjtLc(Yy(9tYt-fI^jg-S ICv%LUKPFBV)c^nh literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Busingen b/testdata/zoneinfo/Europe/Busingen new file mode 100644 index 0000000000000000000000000000000000000000..388df2969f2dc56738183bd4f0d5755c4533a797 GIT binary patch literal 497 zcmWHE%1kq2AP5+NDnJ+nLI`V71uA0!V!{7Fpz`5W1BfoX!qx_&Pl;zSfayntVEXiT zA25C9P%y}N22thL6F{_>@EtHM&U_X^f8GbCB_6K_(~_4LfN8126T!6fp1lGfeKKp- zfoa(}^TD)S&jc_nU(*Pt6>^Hev|>y$m{#%$0n^Ghu3%b4#|%uX%BX{BH695tt=5u1 zG-;$S|411>wwh1Be|%(i5C0;s9K7mC-tBlLBJaoiFvFQ<*z@5G?6p+V8)2 z2|l=W8a}*O2?y#9!ABMO@Nr2Be3Gq!gS*4vQ?(R63)ldMT!e7A&uXUke}25mNRE6? zawcE2N*c(~Yg)9eF&vI1H<KZkZvg@7b;HD0ANR1U8daMyGFDgfe<+V@o<4ken z#2BfJzD=<3v^uErJO{Ta4lMZhFjTwOT49o+oaJCwq+-60ml$p`S`f_w?RwYa;&4Q+ge3-6}gc%YI%#^t=I46bKVl|_Y z{aR=t_s+TzET{XEh1@s(hhVuab}+B&J{5}a=);z3z!x${xt!_7gc@@rp1KsfN62&vk?08J}@ou zcs-bwyu1KROC6pFrlt4n6#(g%S+fpI%g&h(rsaAjfNA-fMlh|AQv{|JW0JwNl1~Vj zR<>~k(<(YhCD zf@$3;x4^Vs%V{vJU$O^G8>FlS(}uA(1sIu`NQDdx+-E?}0g}L|l~G{iU|`@AVBq!f l4PkHwVb@>~5yHR)By_1pvDSt+D_B literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Dublin b/testdata/zoneinfo/Europe/Dublin new file mode 100644 index 0000000000000000000000000000000000000000..17d2b1582df89d5794f20fb028956dd9da154922 GIT binary patch literal 1496 zcmb`{eJs>*0LSs)l?_R(6_xt_b-EO;|Jp6o=H?`&9 zFgwUehJ5Q=GMH@!%xSsFjIbV_hM4VElK}^e%!xT&5}KG>*b49F>-@t7WdCCcAN|BT5!Rb6!lxDr*7-iz zprQn1f8(GAHVuctXZ5}CdDR9@)?eJJLpNvJ!V6D-|tkR=Tpw17xFHlHIe@4#mf=s9|2MDXT)K+>!gd;j`g6IH>S`l%{A!NX&tzhTmsjXjj`l^q7&OLAaXqvP&c?3>KXb%eMuUt z$^jbkV^}*jAa6kijjHWviW$b;60}Li8rrnd0&NyIiss)IL-UYkXpzK++oc82Qn3iF zT-50lGpv2up^eU4Xlq-{I#B_4Xw#rwYX-C*FXEH?97@aK&X!c@cr6_| z34*%<<;LKBpvWm;0X&eZ7A^HaAzyCZB43bkvnbSX1P90&+W6U*=2~R0=B@qQlCE^2O#(e}YDen*dSF1_@ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Gibraltar b/testdata/zoneinfo/Europe/Gibraltar new file mode 100644 index 0000000000000000000000000000000000000000..017bb2e34746c8a11c6955d49cc492c974412801 GIT binary patch literal 1220 zcmb8tdq`7J90%~bragw(ikvoW&C0EbSm$uV`id!*>_53ujr_DI8a5m+gwIY)!bVd*Y}#RENq_UYJ;*KV z8=%wVMcwI}2U|rlhV-=-?uKnH32Z;M0d`bSurtFXBz;}XAaeJS{m^9=q3#;j!Je!s ze2zO)f%|(?{m33kEV3tQ66ZVve)M~dHtc(+_}K4LUqJ2~y9|BdIYCE0!~Q@dOTNde zwoc^NO=HM!sy@MiG7;+jf_CJ$=528Ba4zaYJC(@qXa)v!VetJXJN7?BE8xdPG|RoS zR3yKHfj{bD)KEEG>}H|3@gj__trL>I7+V=!Vkv==^9)>i>NJ#Qn_=wUOt?%>!{r-O z;0o1R7#Aalval#94^3vs{qmoy;mSZ9RCq*C**piXsv3nV>oANj@Im#NHkgoG3pEGq zP`mG?a2D@>C!hCcl9T+uoev59*PNdIH9>w(xR4h@q~>yeos<_wD%1k3BlHHEO4>zJ iTZvn^MRE#xxP^dQ#cRn@Wk^)7QEOBNt%jJ8DEJK=B2RJv literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Guernsey b/testdata/zoneinfo/Europe/Guernsey new file mode 100644 index 0000000000000000000000000000000000000000..f2d87c6bffb6f59351ea8eab944941c97259c896 GIT binary patch literal 1611 zcmb8uYe-XJ9LMovo0(?1%v;)J=8f5$N3#$iA}h+<&>A%Ag-K*czL-NKi->{UcGEPcq^aqKtkjvA&P!gp&2+Q#{LY)+S!bN{+4p(==P(XTb|f(&h+6ir zU?<2)4%zaz++)YA*wbx^J#IYA93tNFDP^G6Qb^41q|tZto8Z0dyD%rq4KkPNg=8)_ zbrGF+A{%}GY%4lnS_dEOTEO~4?_;pQw*?mZi8&{X40+BYs)tkKg!N*>3@lM6!P2(( zu&h7|%b7HW+*fg#Mps_zLRTrGV70Oe*2G9)ZTJx(nSV?R&`*L=VV(UPeCi$@+q8skG!^YED@bwuJY?7zJ=Gc6O%)bdaif##Q zglf4K>uQ}fY`vJHAam`bkpf~zk&BA>E^iOI^I9}Xy%2MO zdyb3n+}?0KTC>RmtqC)!$h>Ayk9n=M1p8Vu5Bq(RtLVP@8&GGb;GCF*A4Xgla{tG- z@6i3t^XP$^aX47!jCK9>cJz?)0Q__+1?$5H{m`FfDmW5k3%~3v#r~+f2#z_*us*i1 z8f`Eo!*SgdoajFUC+j=mRP}F${I0LJE78*zPNHXW&Y@@H!_jl+x~)Ettk__4;2W=eH%*3;Ks&uxao=t zZq7Xgg-J^2aUmLRiIPFj_yFi7-T}QMB30yhKDMrCUq64e?~h<8va#pXI72_fEZkaS zgyOay=zm=YB}KI`Amurv)3Z27y{Huy|NG(d@Ug^=-1XlcvGU)>{+e2`v}DR5Z^BMs z!6#Cy$al(?eb+(@0j^G1;YUTwsIWsaYCr3qedJ^#Y%hDUVV7ujOB}sTvRy(41d5{r IY4XkH4=c&|=l}o! literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Helsinki b/testdata/zoneinfo/Europe/Helsinki new file mode 100644 index 0000000000000000000000000000000000000000..ff5e56530570974516d249927952c69da601b664 GIT binary patch literal 481 zcmWHE%1kq2AP5+NDnJ+nLI`V71}b9#V!{7F5WGumHi%wQoG%TcPoE1+0MTa-JWT+q zVGvcm+W?})gwKI#apwIH`tt@bE%A8$1fVp7S)C_<%vb+v z0;V;ds)A|Ft72eU>nJ;z*52|1OzSLp38re#ss%ZIH4SOdH1D6kud# zA_N&2#8W}m14&>|Y8fzc0KKZf!0Y21!r%eKuCBo#B7}hpNaz}YxH`VZdZu~?`o=oG Kh6Z4k2^RpC0aq3P literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Isle_of_Man b/testdata/zoneinfo/Europe/Isle_of_Man new file mode 100644 index 0000000000000000000000000000000000000000..9f5aaffd4f803b999658c91e3353d31d3d396076 GIT binary patch literal 1599 zcmb8uc}SCC0LSrnPAiXenod*GnHSoeuXYecND`E$QaNZ@q!JmTgo;=e5&jWjM64*R z)O;&T%lj&`OVhk>orvb0={)i%YdW31&+nzb#ph*w-tTj~8!t>66dvYDtvPt?4)P&G zy7rMYcAF0SF=VU!;%iYbJ}$0V@CCrCv0zo7-_x1MpZ)My^QGm&x5biy(vB_jLZ zchA8Oy(i(v(hm5kK*Nyr&ksw`<;hmC;&KxFa%BZp%HmtOOu_~9Y}z&ST&NFv{(3O_mv0#S9efZj*lou8 zA1{0KUup)evgQ6Cs=+q&qGk;1OXWpq^*Hz5mak@^S8Cozk^dz>s#-+Uc9B7yW0`P+ z?moDYzQw7uhPr}C&RPxBn+<^ag_aD(4ue)2z4`7k+A!Y)Z4}*)7Ce$b3OH&G}8x!XlG%BoA&?-GY{tccIl#hJc*2&d!C~DiWd1Z8@}k z8UaO-G0-l-A8z-PLi3(h*KeiuF5&MqgVyS zbsf;{eh-wqDuM2?A0VBW#5v|bY4O&3@p=C*a+1G}^V;kEDlM(mRdo}26@~(yHj&!I tzGe~6fXqL^oe}%*l|j6@_03WZimUM>(6(qq%OZe?4YG+iU~q@#8%7`<^tk zL+gW{&{qJw{j7-*faZ4j>uX9k_rVRLpDDSEXC!_7&UM|3ozBb%#WR9z9=R+a^~>r-L0 zN(y(x3!zxVhcSU3DDjsx(ETOutx)=n2V)(7VBE_EC>xrA@s_tRp}oaL`x0C4qIaIW z4&_ysVN&@M%oQiPU~+mlOer`6cZHkaZpC4*D-}=~cDjM?tDMb5r+G@zd!ELi_fD(O zDytTzKaPOv3u34-Gccnj0PbrQx#)iTb@OO#@~ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Jersey b/testdata/zoneinfo/Europe/Jersey new file mode 100644 index 0000000000000000000000000000000000000000..c83814dd6ae9edc95de7d58f756eef687edeb948 GIT binary patch literal 1611 zcmb8uX-E`d9LMqT&U-Vj)O5`YZCyvR2tgt(N>iy^Xt5V2ktOH4H1S z(JVEOJj?9TG!OFD717i+GhL57%380rd4BVzchxL2pZz}1e}-jXMPX5qUesR?HFkoW z=Hq6big3OJ2KAFo)*hJ@F z%tAj(YC{)<)WOGxH?aQ1={ziSX@Ny<0?s)lL!R@L>gSZ1VZB7L1WQ|EU|D+~EH4a! z&zMAp+*fgvMpxeLL03tFV0By-tT`owwE>bNWwWc4@agf7;^uok6q}| z<~8(K%`6-*H^;g>y#qZFcLIKnj>r1s88`G7krYmO8Njc;W!Rs#c7-#hBCOAB=%W=| zv2b>H0nUwv!uk4cxKO>$kl*#~VI_Jo`4W05_ZoURA^^Q|JskZ#FcSUQasLaYycfNun#TTmLp6G1hI?jhpf7Fn)@QIqPVyJbh2x{y4 zKppxPr@{v6@?tpKR8Vgz1nO5=F%)|k^w4O-v`w^8g$dd?b_~sXAcQ+lH$am_9^B=b z4^71@(9B^@O0kFep%!SN(FrXri#R8r!QIMR(5fj7T2B=6$bB}Y<#119Dzv>Vg?4$- zkRKBV?URGy-XIZli12`pf`ia0@T8PH&)L8d?c(N+c3Jg?u6o9tGIQvrScdy*lu*## z58cy;p|H3Xdc?nmbZQ3Yv?Hai_P-xZ4Sck4BX|9`M`-`s*dJ5s+uJH_@+ORUYMMl9 z2l-AJu3SNE1E&UBFZmRL>*`KKSoYA{Eo60J$8v^w*OelP2Hv FegniE_Q3!E literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Kaliningrad b/testdata/zoneinfo/Europe/Kaliningrad new file mode 100644 index 0000000000000000000000000000000000000000..0ec475647055bd235131c6620aa46da7f43209ac GIT binary patch literal 904 zcma*jT}V@57zgm@w5{f_C5byur!8&H+^n^^TBWr*9xbcLVy}mCaPYfu?lh^CuRF?y0IxIOm&(HJzOm70uo4z#M%6aDC<9YE;ROGxj#afEr z1zFjc<@Y7|$ExRS@q!uWtyv|=xg>o9x%AoHMb5Sd*I-$)3zlC#3)ghUp#9VVxb{dB ztO##`mG#wdo!bf>HY?wbs`5?HY4FFnael3W)gNWJe%1(UUVMkHkp<`;%);86X}BRV z4mX}lK~Jn7ZaVskxV#-h(AO{w>-JxS{<5oZv-f1qU+pkZ+8yU6@IH#X_2+TqZR39A z?b#OO`k{TWVayG8bo=1WJ~Irq6~SEz7jf-YzacBJmB@{bIb>D&g4|>nLvF6jAUA)0 z1NZ74<(zm5TR!x{P$~(->4$M{B3CXTYhl-!Wzye6uhTC#{4;c7@qfn(JyBtRZ*H?o zqBj>%9#M@)5+7o-(`xarf|7+-s07FIa6}_Tjq*Vwl^azwk!YisA#!g z&JG~H)S1a(zVx02A3%JWH50+K?3^YrE!R^FrsZo=z_db6D414^aRbvzKIULr*+v6Q ztLR9AX;m36Fs;V@8$$OgJOG)m@l?D4L~CB<0MlAWeu8Q3Ew8||&XU_;T6fABFs;|J z7fkDytOL^qDf7X!VeDxJ5HOq;7{JKH%*w*b!pw#V*_q&w9q73^AT2yp`P(c#H|PHHzu!G~_`JUEE&~f$0>42`z-%G!4&%({7PrJQ~C zf}FE=2Xg~gFmLu4>PB~9e*X&8cTB^Amct;;8~Wy;v1}O@)(=9HdKeZNn*RK1gXY8m zKh2r%9mvI>KID?4OytsA3$kV14$BUbVEMQPS{E6#bw$96QB{!MtE_rLwzq#HJ2V%_ zRrUwuYHpPw#uCdXc?ub*mr=`?sW`RFu#b zdWDOO>E`LlY(0}QR$V8^`0uc>NZN%coJZp%+U@bO9KDgZiFYCMG&p#>n4E8UM)@zw C4T--1 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Kyiv b/testdata/zoneinfo/Europe/Kyiv new file mode 100644 index 0000000000000000000000000000000000000000..753a6c86f38586797589233f4528837f5b09151c GIT binary patch literal 558 zcmWHE%1kq2AP5+NDnJ+nLI`V72P)$LVx|8;5Vq}j3W#1Mxg1PyT_TwP;-5OJcL7A7 zdG0L$qR*}rp8%rIEpi6)&z)US0J2Y1efb3tEhcft0Yr;)+ztTKzxWS;Xo**RV0p>g z&JG~H)S1a(zVx02A3%JWH50+K?3^YrE!R^FrsZo=z_db6D414^aRbvzKIULr*+v6Q ztLR9AX;m36Fs;V@8$$OgJOG)m@l?D4L~CB<0MlAWeu8Q3Ew8||&XU_;T6fABFs;|J z7fkDytOL^qDf7X!VeDxJ5HOq;7{JKH%*w*b!pw#V*_q&w9q73^AT2kI6G#R8}8#GCSkxFI6)HF>awim{rG!4pH zjAkS6&?xfAD}+?!6(J%k38{3?_x{s=+&gDK=lA=bb9VRctnlb5e@kk~i$$*>gIvO; zx5UuPR?>sJNMFZybM%Pu!!cpRB*(Ks@NX^Z_8FKTWPpA_ z@GV$)SRNKzI>8dvI>yCPSUM?%Wp%|e@;RTEJc2J$ywNYeABnmmQ3hXL3WSvbUa-pJ z5Uk$A4kG(&b_h_v+IbJwdSszr+t~-}<=Pmhc(7r>M@IHF7P&Hxr}dNib(kY#H}gE2 z60DIoRXLs@d2_G?d2>xU&S?qNMBb8h68$%>BF2nVo_vv*oYN}_g?;h< zus_@#ehNMa2YhVdpsNY|ypIcqEIDvk{|_AD8uQ3`UzBth7nI=W*l#%2H37di^uqCH zEpS3w0ly{Y!O2JolwH09r%sFDci$W_Ie*$s41d_g!5OP?_>+GD&T9CLTun_KO?9v)Pfq$`_)Lk#_AX9wfvqiQfq27 z!*z1yjMKSLYcLgRx5q=BstCv}%c01nnSJXeMfe<{@QJ z;Fk?8ygJpW6|Cjoa`f8&$8vYdFSSsfjhnT&IO|Kksfrp)o=7RsPnE|~CLKy0b4@2_ nA?0rGMqbFED?55(M>>jhOF%MHXDhR9W&(2yQ)deSnJNAQHdoT( literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Ljubljana b/testdata/zoneinfo/Europe/Ljubljana new file mode 100644 index 0000000000000000000000000000000000000000..fdb9e86d4a9a51ee4f1ef24b61e2ca58c5f21738 GIT binary patch literal 478 zcmWHE%1kq2AP5+NDnJ+nLI`V70V-n#V&4Bi5NGrC35Y($WcmO^pLy;r0HV*X6rTX1 z&n%p|-hMG`Exl*207zbD%{nkG zJ7+$amg|`SrsZoI!L&k75tvqtNe0tOJ|SRQ*~S%2tLT`4X;m3@Fs;TT0jAYiohN|I zSO01PrZt|bf@#gGVqjY9C_9+e-tq%X>nwQ*rgf*>0@Hder@^#-$sRCmkg^s`8^+!g zU}Pc;fx$QjWIvw(0}IfX3XB{+z99_Gt{@y7!oUS&=^BEVI=;qwrg{cCzJ>-MTHlxp E00cm4j{pDw literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/London b/testdata/zoneinfo/Europe/London new file mode 100644 index 0000000000000000000000000000000000000000..b9e95d92623c6cc4c35b16f7ceba3006f5ce4934 GIT binary patch literal 1599 zcmb8uc}SCC0LSrnPAl(aIc=KGEM>Ols~w0Dk_2U`XboCMsYHe-F-0ts2>*ysB4!wN zXug`Im0Dh9YNcu3<~b3|vqR^RM_Kb)z0dEZzr$yY&-;CjcjIM~2Ze{ZQ~w=2b_aQr zA^-o840f9V`(FQt9imf)&BS|7`3&qa5EIkdXmomZ4ZNS04l`0kkhxkeCi^mDm(f{g z)6fs%8_?PQW$>Zb66POm3xPS#buiaO$~mEB$bFtrU7Tu5%sbIe`rF&3=&E}*u=-*ue0OOD)+pj&ZD2M-_P_TyiLUdkhV_ab z%-8oB!X}}UitKAjJpr3L>|o172EN_ET#fuF2Uf=H)qNfwip=UBKqh~{X&~sOU(LWA{!JonV;k<(> z)_-|9qJLA|IiL~pcizbSYNCvMlX$V&uuyWDSD;8LP`FYd}W=Os4r1KgMeJP z#?TY4rIR={w$M-z$=RTTMl=4@aDk(Wc4EXtU=QX!EE6wBU{mt`Dq&7I6Z& z!7U4JRLnt3#|ah14xvXKwBolyYwKLj&(Gi{Z4wmKBtx6w9056Jn^yogS0_Td>ndoU z83DzS(a<5m4{q_5L&s28xK+9bZaaKLMegThVvTlo*@1SR-vuQ`=A3FFbkWSh?Il_$ zZR~6l` literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Luxembourg b/testdata/zoneinfo/Europe/Luxembourg new file mode 100644 index 0000000000000000000000000000000000000000..682bcbf61ac74f99905a5ea01072d5868a5a0189 GIT binary patch literal 1087 zcma*lZAep57zgmXbPXl-rZ$%@TdlRSxfi!dM4+_xA#^1)Q0xW45lK;FNK`~53{v#N zH3BQG-PUZ)oLXsVP0O6kD0}k-8-0*Oq=K>{h`!i;{_FcXhkJha|D5NX50`7NtT|M` z#2q4`gB}|8_(vQJEnTtvnHOKyrnp9QbN-k{t`j zuz!2Ti`*G0Lk>Roqrb~vfZWaR!G6#AOyoNaN3eg_sXs^e+;i1qzqd@wQ|{YUsUYv` zS>y)=Ct!ctkC;nyaNye{d^p{xp#DcQ-(hI%BOL6XfJ2@Jp7tMK>O+3gngfSVw!o){ z>)}YnDHtx&@zg)MbszGxZNo59F^zg8ngqvo=uv;UP{LCGcp!@-UwJLauP>P3o8vw3 ztxF2u?Jnl1Z=$&vd9p;w(SMQRtA?qK*(~KWw-uSKErcr_YM5@9!3^6@mijV{e~?!x zzd&im2bh&G9`olAl+AU+)e}6-9%+U-p+T1Jk#}~%HEkZ4+r+`OXX>Ehs0*&!Uk%rn z+M#m06>iWJLX}(%H?ELDwb;VZ{pw#PxM^MmH&01n-lzm_>HQ5gzE3d!ViaoKFQBeA z1oe&}G#q%(E)!uUCj9?gE*9p$bFtHLR)!IW@qHAcM21OanIu|8DO6+9Q4veR#-uL_dj^m`pt5>SH zeGi^Z&_#!|{}vY;JHRe6!H(P3mmE1T6W%5VWgA-di|C=wHXl77Reblr&)2X%zBq#Q ziIFOFKz3pM+1(uU^PU^4;Et)^}Ie`%^n4DR-O$nJ)ZAy_XhGJb0lNY9a^{2MN0o(Xfl4 zixcG{I_0#w2sA-gqNo?@An+yK+)(L46p8Snfs~4-o!{3#z^k6aIUl~i@ADkSf$=ph z&DYtvOCj%|n-+imk!pFHQoc2(@)D*3P2}s+0|5pXHc81hA12?7v3m0DlN0oP9s_z$ z{Ri~@okQpc>TaTc=hP#AZ7o5+@S~EW^NSyKBDpkRNB$;mAur#*3s>5-nERdnFzpMJ zSutO&@M9iK+ZSja%6o}EwA+P#P31;^X#0%$;rbkY-;u#D(Eg)wFXqR`UgW>8+{h<8 z%kcEks6gM1`9{KoqOlh_LaKqv@`o_;aXb2`g6A+=Z^JxBoeeMOv}bMu0n-4n=M!zgk>yM&y0yB9ghQOhxTCFhS2>{8Y)dTr8o zs8cSUxi<|{wuj;6fCuVlpTX40DUQw?20y_xsSl<<6=6n4H_U8pgIDVA!K+RlX5DhY zY|{;xV=%(p*c51tvWxV7z#EjLh(N?`Hvvsi)1Py8H?kX%IV^n-BCpko~h+Wp_QV^WiywUEhd-MLKfN7{{Zl9 BGR6P^ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Mariehamn b/testdata/zoneinfo/Europe/Mariehamn new file mode 100644 index 0000000000000000000000000000000000000000..ff5e56530570974516d249927952c69da601b664 GIT binary patch literal 481 zcmWHE%1kq2AP5+NDnJ+nLI`V71}b9#V!{7F5WGumHi%wQoG%TcPoE1+0MTa-JWT+q zVGvcm+W?})gwKI#apwIH`tt@bE%A8$1fVp7S)C_<%vb+v z0;V;ds)A|Ft72eU>nJ;z*52|1OzSLp38re#ss%ZIH4SOdH1D6kud# zA_N&2#8W}m14&>|Y8fzc0KKZf!0Y21!r%eKuCBo#B7}hpNaz}YxH`VZdZu~?`o=oG Kh6Z4k2^RpC0aq3P literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Minsk b/testdata/zoneinfo/Europe/Minsk new file mode 100644 index 0000000000000000000000000000000000000000..30d3a672bf64d0d787ac92bc75d9bc1cc62855c9 GIT binary patch literal 808 zcmWHE%1kq2AP5+NDnJ+nLI`Vd0V?AJVzvK35Vq}<28doIxyk}WZ(Smp0HROD6F zyy64POWt;N0P&^HOa}9%_bm7T;>)a=2&QG{G=XWko?>tsv|@}Km{#&J z2h++n8em#QM-oh{%5Z^c^{)~IAagaIiZ_60&8r+>TI#MKA1L)JzB literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Monaco b/testdata/zoneinfo/Europe/Monaco new file mode 100644 index 0000000000000000000000000000000000000000..f30dfc7014f46670a12fab61dbd74d3b0349afbe GIT binary patch literal 1114 zcmb8tYe-XJ9LMo9-CXI^Gp)ItrMc$H<}PlNilAbRiZ&fIXjG=4NRq@Dz8F!EAk?ZC zTS!D&TQ={TcCpl)W|@~XyHb|)B8rkIY7s&7B0K+|y|>QcIUm0N^X!3*+4oddqwtFp@^*C=8nQ?m6L3U_~3=1?U-Nm{6_l&x#&P? z6TEax1RK>U@bX~`3>s@-(|);=&TCc}(Jjh)*y_l^yiIr%-S)+RZl5hdcTC%0Xlx4% z-*17PEppfuD00%dSB?wNS3L*eHD@;F*Ig%Iw~Y^P?9kx-P0a^%Pre2ACXdfM*9ZH) zw!>R5N~3gs|I1Mr8SjAuy{&N2U*e?qx6hqK51o&~JMJoY_dqcmb`-*Un*>hUKeA4X z9^G&jjyXb@kIgI&(EEwBy_iqDwZEaB3|FEb%m|~a0RO?oj_ASx>LNAqn zf|AtNFfDd!-tU7@`mPHudlrD{!#*gB46t-gMyL}mZ}7tvr@b)qNDa)Ya>14R%3!v| z4&@uoaFwb6Dl(KXMh}t`=D7ssjtJq}?w?Q<{0Q^vW}v!u5^Aa= zP+J~`y5d(XFE-|XZ+^_*J5KPgH^anzrf(3VWB3e{#PSwVF^Sx7mcagVF@uYTw)B#{Vp^Ff_g^s%Jj%UfhmShojppzDoJYKKzu?b64|_9x5IOUqcb4-l z3Z!6gRAIBLPUc|9Kf&HHpC}sAp+DwO6Wo88wRVcL$?O?>$F8x=C~UbgpMdi#bFAg- z3cR=G!wToM(^ruzrZNT2w!4GSe*FS;Tsi~So$rE`z58L+;V4`m+XkJ%YPg}+3SBl6 zbeAnakL*eE{+=HeSpB6u#d%}jv!d_k(f7Xi25Tl~U~Tpdth@FUZc0CZo6lyTuWJz2 zADJrfe*V)#upu-8x9sbOjrJ7W>OWNU_c7R1(U;_PO&=r3frSp_?N8juJMux~;Aj|z z9y?(3fD5(^6I8lO;m)+J!29h|XOY9l{~$+PuaVX8C*-Jn54qL(9JzJw72K`M7JWMo z_k13JZTBz3*!1lr?;pQ%3R#QUJ0)F-PG6#z4RWb$FdBr5u4VskFP>;J5IF;Ug1GC6 z>Mu%0@qCV-TZW|N;!7#gY9g?>D4-@p|eETzUGxTV7}Io^I*RAmUCdf&XSE_zV4I_V7^|| eh!6%YAfamn;_CPs>zV2q=o{Mk!L!FMhUW0LTA-e9xREawUGQ?o1h4!m7#Wnoct9`E z`R6S!^2>5NOw3u~>x2#_M;Z9mBY~;T6im0o;5!?I8FdJLFiC;#{j}vHegtbvG(lACkd_{V!NB=F8Bl+(kM6SfI^^#mdiWySi<#^)ubkoKYx!5cY8qJ*3+GMqxIftEU HbIN}KI)2g> literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Paris b/testdata/zoneinfo/Europe/Paris new file mode 100644 index 0000000000000000000000000000000000000000..00a27264c2cb3e28f2f46e5c267e12d575236a9d GIT binary patch literal 1105 zcmb8t?@Lor7zgmXxw*2bSIxQ9(p>YF&HYd(6+y)s6>Vq;E%U6wc@bvN7a^mq&J@ex>0La+5y~ z*cecGL!2%yqE!fJUJEu4~Q6ZJZCbm*%1#P#i}Nd@Vxmm@7x_oN>Zn zcpL1RXoKBt8rb7^2z2j_lXB#n4b||Lkc0Yd_bJ%xl)*c@4CvoAd_wLku)+Ss$b$0& zaNt`9y!WaiO7{=G9*3bw9~|m$hr>1-JdHeZDGDFdy5PgZWpK2#1U}j#7wG)h z1|#zLrVB7!8bm!jyVOtph>LqiKAGFil9Pcn5Bap&f;@Gu2u?fRw$UJX<1+gUodyzn=2s^$w+ zrM!h{F_R1a7>4Q(J#fVfKTIF>!i>-mOZQ|3yWz^lCb;UX2WB0sgV`=OT)n>%=Gb_s z*=&Vtbj47c$-!Ku8gg=rhwkTo7QwY2wQ$`_70eq`!1cYqpswXJ%s)R1_4SXTp(X^4 zRb9|j_J)%p|-hMG`Exl*207zbD%{nkG zJ7+$amg|`SrsZoI!L&k75tvqtNe0tOJ|SRQ*~S%2tLT`4X;m3@Fs;TT0jAYiohN|I zSO01PrZt|bf@#gGVqjY9C_9+e-tq%X>nwQ*rgf*>0@Hder@^#-$sRCmkg^s`8^+!g zU}Pc;85o2uK=$(qFt7l9sldqL;~T=@>n6S>(K|QN>!DsS}id!m568)i8~32&`2Z(8iT=r7z~E%5eAQn zSR@`x4U)2mMB@D@+So*-EE183h4cNpNEhekJHPw??l~v-NbP;SRouUWXDg^^NdIrC zXUh^vG^rc0hb!QuD z)uBa2nWjf#V>42rrMraPI zVA)X;EcbswaXkVn=EBf2aRMuc0?_K&g0{|(z{khMJP9#5_WPgAaf(U$F*YZ#>+AVs tj!PFf1@-t0ms{dmSvecqXp*=l7E;+ug^gOG+it10SVgzZN>jRu%j(UAnxsxp!w;~3O zq5f43Olv$92h*BYIl#2mk)L2%d&?^@t+V7dnAV+g22AU<>;=>MCF{VnLCSnEZ5Vr+ z0R)VE_kd|*+uZ^nhDp#gFl{P37fhQORY2&!^ z(I5viHpmPN;zb|>fFuh8gUTjG4q)IZFz_%iXc;g7t>6=25CMrWN-!{3I55hB#2FQR zd_x$5fY>KEgu&G{guyr1o52}KJG%k}e1lzpfW+Ipe1G3_#$hnA`C5Ag z+xJn(JLsiH-2aF}-j*!CnS1h6SG*~ZlCM`HN6&2~49~AocKHKQ^6?wiNEf9}#EhlEg+ z_AS<#G5^vK!aSV+N22*s$wTx@k=y9M9vnfxZF!CP_VNeZZ-);_w14NV7xP%miyVJ6 zg1o!20QdT4B>MfBe>zGit~@|aay3Kcg&vrE=LY(e(qVX@a~Si~^y|oJw(|)i4yZCZ z(5nJ9$ZAauvifBna>n;Hs2PaEL%}$Du3HB)J*)6=Qw(O=>p8mL5zAjEnOzux+N>3r zqYNhe^$zB)Pr;*$Zm4@d1oM2e9G&N1O~QQF7(6!UgvW38!h()2c%tPhJSm8O63_E>aNin6`Sa;oC9>%(-CZnUimS&0h{l}V9VYFbYE`a{X7f95f&Bw>ywzo z6o0pWUlUzoQADN};xWi1@fUDXEKy@CixX?c*9MtMZjYA=W+Ipe1G3_#$hnA`C5Ag z+xJn(JLsiH-2aF}-j*!CnS1h6SG*~ZlCM`HN6&2~49~AocKHKQ^6?wiNEf9}#EhlEg+ z_AS<#G5^vK!aSV+N22*s$wTx@k=y9M9vnfxZF!CP_VNeZZ-);_w14NV7xP%miyVJ6 zg1o!20QdT4B>MfBe>zGit~@|aay3Kcg&vrE=LY(e(qVX@a~Si~^y|oJw(|)i4yZCZ z(5nJ9$ZAauvifBna>n;Hs2PaEL%}$Du3HB)J*)6=Qw(O=>p8mL5zAjEnOzux+N>3r zqYNhe^$zB)Pr;*$Zm4@d1oM2e9G&N1O~QQF7(6!UgvW38!h()2c%tPhJSm81Rdme2w5p6cm{#MF0MqKM&J#f9 ztA8~C(;81z!L;U8F)*!llpRcKZ}|bHb(XvY)4Ee`foZ*#(_mV^WDl4&NLdS}4P$Q# zFftK_3=D!UAp7|Q7+8S5RAA)r@eN^cb_LKsBJAWgN;!E+ySR{-=l9*oX}_o6^XdD%9sd2D9RqGX3tIv|K~3chf5pO&NqEQo z^4esj6XdZsriHJuc+JW=nIQA)$i(Pd3;YxgN!bfKC*=Vn_LFX=krlqhM_O0zPD0h% z2uz;shbiN2Fm=!l)4EJB-H`(`%-KQ4D>F|H)k-PMiur;XiN-_wnhzPwxqEX_&b@p^ z)*ju%Jnt>cUpj*YQwOkcWCQB@7GP1gFG%$)IB3xdw-B?)z`>% z)<CmH>7_DHayM1#{D_yxY_d1`%Uvh$WDjKMY-MD>=DF>epILGY(F#U`F0Em`& z#Rry`yzT4&;!B;G4CYJkS?~eGmsv9rOv}z`0@HFm#b8>#CIw6@j}4 zrj>0pz_f~vB$!r};R4fYy?S6;^D0LJ$b79MKf$#2mRDd}XUT0atvlrmgg$ia0s|1} zwX81y(fTC|z_dZiL@;d_y8tY2RJ05v&0uW1TL46x1Wg0erm}Ovw3$%_g#KF(rY)qW zOaQ5~xSI&(TmCKs^R4zegZb9CBfxx{W$|FzcDEInwrg_))AqAvz_de}GMIL3u@nHA z=j6r;<~yfIgZVD1&%u0G=f7aS8|z6h-(C4WnD74X8JPBDJ_w=DodDBbj~9b!?{%xd zw9lFS6F}zs_Vs}Ierpzj`Tlu%V17VPGngM3-UX(Ea#F!`uz6eqNMDGLYyu+_Gb;-a zGP7YoCUy{nh=Z9B0URU;GXsPC50J6)4;Wa0i9~^c0~nPC3_J`Bd;$zW2gxWfiU0%G vfl(49&L|6FGw}HMhA;#Jv8!tcgKw}mgENqJb`1t`T!4Z=1{Y9R*O&_c^%u8U literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Skopje b/testdata/zoneinfo/Europe/Skopje new file mode 100644 index 0000000000000000000000000000000000000000..036361cfbaf439b133fffd4323561291de936663 GIT binary patch literal 478 zcmWHE%1kq2AP5+NDnJ+nLI`V70V-n#V&4Bi5NGo~14N%1Rdme2w5p6cm{#MF0MqKM&J#f9 ztA8~C(;81z!L;U8F)*!llpRcKZ}|bHb(XvY)4Ee`foZ*#(_mV^WDl4&NLdS}4P$Q# zFftK_3=AR?Ap7|Q7+8S5RAA)r@eN^cb_LeE~#^m?}O1(V{wU!F(~{ z0|g+yIL~=7U;Oii1`uE3@j@^yd3h3;mO9)Frlt3+2g))q$gEiare)_$1k-XoO<-ES zrWi~sohdrj>2X!L*8w2AEcrkp$CfJX~N}oz=7f#8Cgrl>nkOp1chJ z(VAD@B!FnGBj>?zV2q=o{%g?^ocUl{u4e+6mal09(+W97U|KOI8B8nrgn(&f8&@!`qGJZ8Rb|w{v>J~Dm{w)_AH4rZumMfoZLy>|k1Z%MUQEv*ab1)}3+-OzX9r2GjZ_d%(0o%33gO z7<*HIk%^fwWMB|@19AYL94K)41QgGv@$n5|2zCu&a0cVx5C$$FOV`lZH8@1a T*I3U~&p^l5&;Ug18*>2w?Gsu1 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Tallinn b/testdata/zoneinfo/Europe/Tallinn new file mode 100644 index 0000000000000000000000000000000000000000..fbebdc6255b547b1f3a547f0f92cc8148f05f186 GIT binary patch literal 675 zcmWHE%1kq2AP5+NDnJ+nLI`Uy0V?AFVx|8;5Vq~i84x`$QWrw+oG<~zpWiYaOfO{6 zE&%bD6zBVZ=o1^ZJ^<0Dj!h2$(Py4}3xMdeE5*U;&nnR4)@--=7S|KMCOe@B?foUZlb1bR@yFs*EJaI0iKyE-nynqrgf*B0n>Udd%?7R$vQA?kTM@k8^)ey00E<- zWnkLab}g7T3F-jTrn3ED+RUgz0K_o+TMwo!q^C>(@oh?E5*V48m>F4EnSc}%D;pYQ zXTb(pfFTQtUl0jo%P24cW13HZffvMP5M*G`GGGv8V6bpt1O|ha0i&#sZwNyO5IegD rgNP6YS0MHc_6A}XAR8#i1r*UW0x@-bjrC0R4D^k4d<_l2EE6sO`iG<- literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Tirane b/testdata/zoneinfo/Europe/Tirane new file mode 100644 index 0000000000000000000000000000000000000000..743a7337ffd8c404d1da0d2d078ea1cd8459affe GIT binary patch literal 604 zcmWHE%1kq2AP5+NDnJ+nLI`UCnaB*py#Ik<+A5O_5Pc%Iy#Pd?dG0L$qR*}rp8%$J zyqo|smqWwy1DJkqmjI% zOWux80P&^HtOv_W@7XH=;>)aA2c~7`%m>qQJrlsRd`%;mR>&y=(~2?4U|Pv11WYU2 zxPoaF9WyYkDx(gj)p#Vpv^uNv1d#daUroTY##2==t$9@pOluuw2h-YHet>D6C6Msb zopKAz*K0Wqru9qqfN6u2wP4yX_ND+M6RD7aL1+fZHGBdLEI>aiFmm|#hA=q0f^cvM b0~e5`YY1ZM_!{e(>KW+x8XACTePb>FP|$Lw literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Tiraspol b/testdata/zoneinfo/Europe/Tiraspol new file mode 100644 index 0000000000000000000000000000000000000000..a60bddd7b2c96628f11598f143918915c98052cc GIT binary patch literal 1207 zcmajdYe=5u1 zG-;$S|411>wwh1Be|%(i5C0;s9K7mC-tBlLBJaoiFvFQ<*z@5G?6p+V8)2 z2|l=W8a}*O2?y#9!ABMO@Nr2Be3Gq!gS*4vQ?(R63)ldMT!e7A&uXUke}25mNRE6? zawcE2N*c(~Yg)9eF&vI1H<KZkZvg@7b;HD0ANR1U8daMyGFDgfe<+V@o<4ken z#2BfJzD=<3v^uErJO{Ta4lMZhFjTwOT49o+oaJCwq+-60ml$p`S`f_w?RwYa;&4Q+ge3-6}gc%YI%#^t=I46bKVl|_Y z{aR=t_s+TzET{XEh1@s(hhVuab}+B&JIERa`d0}st?^X60mRp= z*bkwv`~r(>9eE9=wYS^>(>hDef@$3;`@pnb%X%=aU$Ov98>CDG(}uBoK7hu)cS$4W6TmY;~jWYlM literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Uzhgorod b/testdata/zoneinfo/Europe/Uzhgorod new file mode 100644 index 0000000000000000000000000000000000000000..753a6c86f38586797589233f4528837f5b09151c GIT binary patch literal 558 zcmWHE%1kq2AP5+NDnJ+nLI`V72P)$LVx|8;5Vq}j3W#1Mxg1PyT_TwP;-5OJcL7A7 zdG0L$qR*}rp8%rIEpi6)&z)US0J2Y1efb3tEhcft0Yr;)+ztTKzxWS;Xo**RV0p>g z&JG~H)S1a(zVx02A3%JWH50+K?3^YrE!R^FrsZo=z_db6D414^aRbvzKIULr*+v6Q ztLR9AX;m36Fs;V@8$$OgJOG)m@l?D4L~CB<0MlAWeu8Q3Ew8||&XU_;T6fABFs;|J z7fkDytOL^qDf7X!VeDxJ5HOq;7{JKH%*w*b!pw#V*_q&w9q73^AT2p2YyB9~FY>)8Bo-^qE7! zAY&Osm0wQ)(PF}Pz_d8?SqS}kADEVSydF$TUS0sEr4CO7)6#qP3V`&HkkB;*admu+^-T2)bbJjBK(xLw7XYW+Ipe1G3_#$hnA`C5Ag z+xJn(JLsiH-2aF}-j*!CnS1h6SG*~ZlCM`HN6&2~49~AocKHKQ^6?wiNEf9}#EhlEg+ z_AS<#G5^vK!aSV+N22*s$wTx@k=y9M9vnfxZF!CP_VNeZZ-);_w14NV7xP%miyVJ6 zg1o!20QdT4B>MfBe>zGit~@|aay3Kcg&vrE=LY(e(qVX@a~Si~^y|oJw(|)i4yZCZ z(5nJ9$ZAauvifBna>n;Hs2PaEL%}$Du3HB)J*)6=Qw(O=>p8mL5zAjEnOzux+N>3r zqYNhe^$zB)Pr;*$Zm4@d1oM2e9G&N1O~QQF7(6!UgvW38!h()2c%tPhJSm8pBqoZg5T$0QpncSN#Ks7BRk% z0HQ^eUrzwhV#0U8v^euw2>p2R(O3 zw8m3aFs*r23`}bsWe3yRTYi9Poh2{9wC;e*#o8xQr3cL!`PbwOpN3~ z1_u5>u%8teSr{1j1Qk literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Vilnius b/testdata/zoneinfo/Europe/Vilnius new file mode 100644 index 0000000000000000000000000000000000000000..43c3d7f1089366e1c48297906c2693712ac6d99c GIT binary patch literal 676 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1}ftOVzvK35Vq}%3y7ZMFCPG+7q)uM0MUy+8hilJ zi_>iMI;SCHxwpa!O2Ll7200R#&02LU37HAnTh=ACP5)2F$4vexO5k^HH-w=jy yAod1gXV(x0S0MHc_6D+pK@1n50Fc226xKBYF?D>6^-T2)^o@0V4Gq976D|N{`JSl& literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Volgograd b/testdata/zoneinfo/Europe/Volgograd new file mode 100644 index 0000000000000000000000000000000000000000..0715d58bc1873c8bae589a08752cbbae562692c7 GIT binary patch literal 753 zcmWHE%1kq2AP5+NDnJ+nLI`Vd1S(?(Vu}Aiu<)zf9T2^B33mWUzo`1m10Y&V;+z49 z7UwwY0H%L2ZUE5|uNV%1Xvy2AV0o!Ctzf?No=Fct;xcQR!L;n05-=^-lM1HgYr?>^ zLXJC_R*bO#(@H*?U|QKm;{yW_sOU(7X;m36Fs;V@8%(RSsuzId)xS!BY0WEd5;W|9n#dBNHYrAt;OA#L^iTEMk$>@(!jN|a=ce0z*QtNz?kLXBUfw}I zS7nf?9Ob6pN5)<; zimVsCFuU^s%(>qRk2c?cx!2q$=wdk|XdB7!15jxJ?_a(A)+nK8`}y)B;; z_&3Q_9OQpQU`dRbEQ%DWFm1I{V(0m=J8Ec>n1dD$zEJV3*h+QLX)~WPTSTYTLYCN6 F{{iE`PO1O^ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Europe/Zagreb b/testdata/zoneinfo/Europe/Zagreb new file mode 100644 index 0000000000000000000000000000000000000000..8e13ede8d4a6424bb62b30044ac8a20935c19f61 GIT binary patch literal 478 zcmWHE%1kq2AP5+NDnJ+nLI`V70V-n#V&4Bi5NGqH14N%1Rdme2w5p6cm{#MF0MqKM&J#f9 ztA8~C(;81z!L;U8F)*!llpRcKZ}|bHb(XvY)4Ee`foZ*#(_mV^WDl4&NLdS}4P$Q# zFftK_3=DifK=$(qFt7l9sldqL;~T=@>g z&JG~H)S1a(zVx02A3%JWH50+K?3^YrE!R^FrsZo=z_db6D414^aRbvzKIULr*+v6Q ztLR9AX;m36Fs;V@8$$OgJOG)m@l?D4L~CB<0MlAWeu8Q3Ew8||&XU_;T6fABFs;|J z7fkDytOL^qDf7X!VeDxJ5HOq;7{JKH%*w*b!pw#V*_q&w9q73^AT2@EtHM&U_X^f8GbCB_6K_(~_4LfN8126T!6fp1lGfeKKp- zfoa(}^TD)S&jc_nU(*Pt6>^Hev|>y$m{#%$0n^Ghu3%b4#|%uX%BX{BH695ttOls~w0Dk_2U`XboCMsYHe-F-0ts2>*ysB4!wN zXug`Im0Dh9YNcu3<~b3|vqR^RM_Kb)z0dEZzr$yY&-;CjcjIM~2Ze{ZQ~w=2b_aQr zA^-o840f9V`(FQt9imf)&BS|7`3&qa5EIkdXmomZ4ZNS04l`0kkhxkeCi^mDm(f{g z)6fs%8_?PQW$>Zb66POm3xPS#buiaO$~mEB$bFtrU7Tu5%sbIe`rF&3=&E}*u=-*ue0OOD)+pj&ZD2M-_P_TyiLUdkhV_ab z%-8oB!X}}UitKAjJpr3L>|o172EN_ET#fuF2Uf=H)qNfwip=UBKqh~{X&~sOU(LWA{!JonV;k<(> z)_-|9qJLA|IiL~pcizbSYNCvMlX$V&uuyWDSD;8LP`FYd}W=Os4r1KgMeJP z#?TY4rIR={w$M-z$=RTTMl=4@aDk(Wc4EXtU=QX!EE6wBU{mt`Dq&7I6Z& z!7U4JRLnt3#|ah14xvXKwBolyYwKLj&(Gi{Z4wmKBtx6w9056Jn^yogS0_Td>ndoU z83DzS(a<5m4{q_5L&s28xK+9bZaaKLMegThVvTlo*@1SR-vuQ`=A3FFbkWSh?Il_$ zZR~6l` literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/GB-Eire b/testdata/zoneinfo/GB-Eire new file mode 100644 index 0000000000000000000000000000000000000000..b9e95d92623c6cc4c35b16f7ceba3006f5ce4934 GIT binary patch literal 1599 zcmb8uc}SCC0LSrnPAl(aIc=KGEM>Ols~w0Dk_2U`XboCMsYHe-F-0ts2>*ysB4!wN zXug`Im0Dh9YNcu3<~b3|vqR^RM_Kb)z0dEZzr$yY&-;CjcjIM~2Ze{ZQ~w=2b_aQr zA^-o840f9V`(FQt9imf)&BS|7`3&qa5EIkdXmomZ4ZNS04l`0kkhxkeCi^mDm(f{g z)6fs%8_?PQW$>Zb66POm3xPS#buiaO$~mEB$bFtrU7Tu5%sbIe`rF&3=&E}*u=-*ue0OOD)+pj&ZD2M-_P_TyiLUdkhV_ab z%-8oB!X}}UitKAjJpr3L>|o172EN_ET#fuF2Uf=H)qNfwip=UBKqh~{X&~sOU(LWA{!JonV;k<(> z)_-|9qJLA|IiL~pcizbSYNCvMlX$V&uuyWDSD;8LP`FYd}W=Os4r1KgMeJP z#?TY4rIR={w$M-z$=RTTMl=4@aDk(Wc4EXtU=QX!EE6wBU{mt`Dq&7I6Z& z!7U4JRLnt3#|ah14xvXKwBolyYwKLj&(Gi{Z4wmKBtx6w9056Jn^yogS0_Td>ndoU z83DzS(a<5m4{q_5L&s28xK+9bZaaKLMegThVvTlo*@1SR-vuQ`=A3FFbkWSh?Il_$ zZR~6l` literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/GMT b/testdata/zoneinfo/GMT new file mode 100644 index 0000000000000000000000000000000000000000..157573b1d340e0f57a0dd4d9698bd3798cbf7136 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/GMT+0 b/testdata/zoneinfo/GMT+0 new file mode 100644 index 0000000000000000000000000000000000000000..157573b1d340e0f57a0dd4d9698bd3798cbf7136 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/GMT-0 b/testdata/zoneinfo/GMT-0 new file mode 100644 index 0000000000000000000000000000000000000000..157573b1d340e0f57a0dd4d9698bd3798cbf7136 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/GMT0 b/testdata/zoneinfo/GMT0 new file mode 100644 index 0000000000000000000000000000000000000000..157573b1d340e0f57a0dd4d9698bd3798cbf7136 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Greenwich b/testdata/zoneinfo/Greenwich new file mode 100644 index 0000000000000000000000000000000000000000..157573b1d340e0f57a0dd4d9698bd3798cbf7136 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/HST b/testdata/zoneinfo/HST new file mode 100644 index 0000000000000000000000000000000000000000..40e3d492e6c22c30041c31f159d4fe0ee9451c03 GIT binary patch literal 221 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I&Vv+wqQ1YN)ABf(~>g)lg6$>Lk^yyC96CnDM z@|OZIo#<%+qObNAdoVIFGP5wU{{NrD#J~U~BN$lz|F6nm;TbMoi>Qv;@<)_(UM|O=&QF`|UR{ zeP_pCFn#yz4KRIgk(33UG30Oo&oxL^TN_a#FJ%>Sye3C#cI{sqkcu387?{}4?C z^MA4?fcZbaI)nMYo;rc~zwgDb0GadWT-**2{db=unE!8`1DOARp7IJ%yfXAD?Eq1X zb*x}MQyvSL&m8+4%xCd^2IjN6vuJ?Sv6(YlfM|BLXJ9^ivn`m<$#w$F=lpgY%;$Qx z3e4xewi3+eIo1Q_3(mF#^M&$rRxmO#voJDI2pJf%xj+soXkcJrV5pnG$icu+-oeNV dVlxQ&_=Yfec!O{-hzJj1@B%WpfI_+!TmUPfblU&` literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Iceland b/testdata/zoneinfo/Iceland new file mode 100644 index 0000000000000000000000000000000000000000..2451aca76d7c555b06d358c2e30799c9b599fd1e GIT binary patch literal 753 zcmbu->nlTH90%|-V`(I%CKMAxEj5>vBAMF@_Ci~UH(Npxg~&TJR&oh1cr}c?l3OW7 zd!ZCDw_!8GTxWAPmznEvp6~tuFFdE`e9!0i`#qgH9a&L%Sv>XUVlfkBlO_B6NG3Dp z$!vd`SsjWN4M}xxC`EEW-_}ENur|M${_t!P`lBh)=#S3Tp}!;vMt?aq znorIxn**mwu0&;Mkc&~M>o@{fH!eo59j>Fk-WdsRXs6)KN)EiG?uGTac6eJgf!qk%nYFpS;JIRRiw@&A=vs6gIv0!Dhc|ckVYJ53GUcAI=rRM;nPq%Sb)y$CEtx zL|FizcDdlQ;$--|$_!tKLtv{!3txtR!?q+7((V(C`W0^;zPkQ`ubpc6X4L}U8XMue zu?6^kRslb>kHC-p?(gQPXoa7eDs{Ut<=_lcpVylsDj;Cy`M?k%)>F#ZfuTGncuExWA5R Bu;Bmz literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Indian/Antananarivo b/testdata/zoneinfo/Indian/Antananarivo new file mode 100644 index 0000000000000000000000000000000000000000..0bf86f024a06fea7711882ff24cd2baf7e5d3ad8 GIT binary patch literal 160 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#-v2-_@$=a)Ao`K e3>a7#7%UtZIedIW7+f7eI5>oX3&_$n<^lk6_Z_7G literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Indian/Chagos b/testdata/zoneinfo/Indian/Chagos new file mode 100644 index 0000000000000000000000000000000000000000..8b8ce226b6b7f67229577b837775e7d448348bde GIT binary patch literal 152 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%&{_9=4oIKDv%4D@filidKs>hq1{R=M Z2@D)Qz99_S2Btu4#=vC*B<*y~xB&JZ61xBZ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Indian/Christmas b/testdata/zoneinfo/Indian/Christmas new file mode 100644 index 0000000000000000000000000000000000000000..766024b36c50c66e097b9811e5650468b1695746 GIT binary patch literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iVVEVl9qP#{?bq&ca8fyKu+ghAWDoPo;* KNZRR|a{&N$sSVcv literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Indian/Cocos b/testdata/zoneinfo/Indian/Cocos new file mode 100644 index 0000000000000000000000000000000000000000..117503410ce98195cd30ca4f63777465b2991e13 GIT binary patch literal 140 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;uKz$#6RNfZC=hiAq&Yf+fyKu+ghAWD%-Dc| P%LYu_>6%#?8*l*t;+zj= literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Indian/Comoro b/testdata/zoneinfo/Indian/Comoro new file mode 100644 index 0000000000000000000000000000000000000000..640b3e884885b08cad45d3a3e11cbafaf955b5e7 GIT binary patch literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@$117rkBAjfPqEVz<@#9z?6Z@21wfJ HnsNaEVA2e| literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Indian/Mahe b/testdata/zoneinfo/Indian/Mahe new file mode 100644 index 0000000000000000000000000000000000000000..e7fccf8296e7eb93c2d49f26570f68be2eeeb475 GIT binary patch literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iW=Sq1A~PF1BZ`q2!pnPDG-}5aM=J!J6#hl0MNJ<_W%F@ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Indian/Mayotte b/testdata/zoneinfo/Indian/Mayotte new file mode 100644 index 0000000000000000000000000000000000000000..7a009c3122060329eed1af132b74937fd88f632b GIT binary patch literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@$&@yBD$hrzJ@{>n6GhrE|{-*dJdSc zwNDAm*Isi0tY2q-m<33mZXYvPUaz4OEU%w$4wg4a+zXaB49Eh@8##Rd%NrZL2lGu- zOTm0o5oNG?Gq#mr^=4ng!1CtL?||hku62RsEl&!7<*jz|gZb90r-J!5vz)-{ZF^3D z)!S8V4a{g5~|HtikgB885){0nvG2`9SYnFh9ulGngN&vkpAfzV%un<(0`rqB9)Q&+Yo}Q-GBdHVurf1I2pJd*z*YlE76t};4@M3K215%5 vJ_ZK207el81`7uU2_N4Oh7cguHZU8zf{-F9D1(CrU99|M z5Xur7gV6;m3nExibc5xVNz1Z4UA)vL*oUT$($4$ri{JdxJ6?Y8?|J@b=kVGc2OD){ z(Iwy~=%&lQ_#+4Sv8DXZnCDmR{U>osH&cF=^5xzj0pniqRem>1Jun&pU*DKR-v2@h z20Plokk13YIeiKoI3H%|b8j1Z!NEf*$iof>9v;~Pf3JQDAClC=Kcr137zu$N`}E-O zgF^5VcM<&D*U!@bAMrc_x%Okoztkq)|JC1!{F~8<{JYx(A6;1jA8Vch$I}OpPbh9C zIB|krBN4Tm!{z3C=-1Y{IhwDN?MJ`f!Jywjir|WrN%V?$W0>C<3Bor$PC}nO7{z>! zPl|r?!v^%qa{_p7S0!BK^kH6oG8@jAo}t&6F2l72P3U!+yDq{nedZi`LwYCN@XL!n zPbgw(pBEGyrp%8yS;{TLvmE8t&?NG0w-WbLaIFVk*mK84`|WM5@S>Kh9QER(MtF(M z7XDxOx4KClt7fthJwzF=o6m@ic60p<&5 zx`X*5ky>EBsHY~FFJ{RD=8J1`gZUClnh6X*Aj$C-%$H)~PGDqW#sdHU-@(Md047=f i|KGWRf#d)G;|Cade0)O~yn)y?7>Hd$7`T88Q!W64fkAEn literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Japan b/testdata/zoneinfo/Japan new file mode 100644 index 0000000000000000000000000000000000000000..1aa066ce38fce7bd0a680f51d6f075718d153a77 GIT binary patch literal 213 zcmWHE%1kq2AP5+NDnJ+nLI`W&1S(?&VxIp%ka}oI0f@eC#{{9@Mt%VCZ~XWL=HEPP z4d&lwXMoUaWx@2FXOF=2-Jbs+m>8jufuR{>FhkD*MivH!x(N&%KE5FgUM@f!9Kyf_ IBy=sg04jJ!hyVZp literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Kwajalein b/testdata/zoneinfo/Kwajalein new file mode 100644 index 0000000000000000000000000000000000000000..9416d522d0a3e19ab6b81317f5b94961c55e91fc GIT binary patch literal 219 zcmWHE%1kq2AP5+NDnJ+nLI`VN11bYyiT^-QXC|Qlq7S|`y#S(5zT!#%(dXS7KY-}} zZPEcCb9Ku292l9H8Ch5v80I_xiOkx-z{0@Lvw(qvfuU{!1JD2e;SLM}3=As{Fo^j0 fhA?Ow8UnEagSLSsgRY?wkZr`kWdkJbfIKb$c@{B1 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Libya b/testdata/zoneinfo/Libya new file mode 100644 index 0000000000000000000000000000000000000000..e0c89971aabea2c87842a9276b043d0fd946e34e GIT binary patch literal 431 zcmWHE%1kq2AP5+NDnJ+nLI`V704ievV!{7Fu<+AC6%c)Q_eKE_eNTC90*HQCaS6mo0*F>~*be3!`F#ZQja|&Z>P<|u9)RQn=FS9B41pmx8$fhW=9UH~MlfWC y(hweq1d4zV0|QSCNUe+lBQU)91Q<9$YzAH*-w+08*I*D4!r%(TTtGtChzkG|lxEie literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/MET b/testdata/zoneinfo/MET new file mode 100644 index 0000000000000000000000000000000000000000..31973271d2f87f7e9df4e8b0a1481f09a9e5407d GIT binary patch literal 1103 zcmb8t{Yz6(7zgk>-LhoqO>@p^wOVUsb1!a_h#+h32XiZ-QDS9*B1JEZAyHA0FetGf zW&{eewrsjAon_86r)6eal=d>U96^wjMNn1*(l2(O@BRSmT+aF2?{l7e;9jn^^iX9k zGwo2o*}QD?X!_hsubkwr_9i6sD{mDGVHg=4ah!)3*N})!PbN`F~8|; zbk5D`{m8f86vMXA7TEsO2mL-7?C|WcQUC4p0^~b2hheA9?4kNydnfEFR>44Fsg&y7 z8W#Cp?s3?Y{4?g<6zu&z2JcVQN~yo^?GG3Xe}Mfx5jfzk@zDN*h5+(IS0)@hQ4b#- zya0zvPQu5V)gI~}-mnMx$;Lq#Dw#k%6kPi!_7 z$-Y8S>N}VoKN9oT02EJkz>J6oN`~rSX0V^7bF$j}a9N`pF2Cr6D^6EK=@C0zxwjmy zGFzc+lL@X?=0SOu0H;aOZ*G`0?%at literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/MST b/testdata/zoneinfo/MST new file mode 100644 index 0000000000000000000000000000000000000000..c2bd2f949b248b835c98216b4dc66f9f6eb0265e GIT binary patch literal 240 zcmWHE%1kq2AP5+NDnJ+nLI`W&1}b9#VuAla5XZu^0YuMRW;Fps&)?170HPPP$$r^U93H~J1!S0W0RTV0SUUg! literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/MST7MDT b/testdata/zoneinfo/MST7MDT new file mode 100644 index 0000000000000000000000000000000000000000..09e54e5c7c5bb2384e37626d4b985cfad29ed29b GIT binary patch literal 1042 zcmb`_OH30{6b9hiQfNDlGAban#Rn**we|%SS|6acqQ*voHJ}Sk6CS~hsIkU{I!e{B zFiez%O28Hf(HOPFji!l0jK;*rqHaVJL^moLW7LF7q2s-O)GZtDITiC{kFCT$_~lcinouj~eRN)v*ol1BtKpZeGUPrs^%XP$WA z^j$YBUo)`JBjl1^U`cT<%@R=_oq;nB>O^K$us~utvvyi!IjcGatLEg)8Y;y8vQxL= zqFpjvy#EY&1)-G5r>Wi8}n}UAzZg-}wcu>OKiqA9w+82zQIDv2jNX-qd&;_S!DMKJPx*_v4YE zRQ!1|RR7Aqt^bl`xu=WJ-}y#Fp`x`!G^lyJh3)z%dAeT N-QssRtPZQ4`wbnj4)_27 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Mexico/BajaNorte b/testdata/zoneinfo/Mexico/BajaNorte new file mode 100644 index 0000000000000000000000000000000000000000..0d8c993bd1cf2fa2cbf002421ec9c0fb2b29645b GIT binary patch literal 1367 zcmc)J$xo9(9LDi!Sqf!)WfxE@pruesTehMivS?)sAQi=fTM&bZ0Yr&h5EK)MK?-Q1 zF<{l0NKh6rh(Qr9L}T3QK@dbl1cL0MtWswl{s4|nGw-*bd4KPFX{tGpk**}GE*_m= zn=Q@ij}*}{Q@WiEblqzj&SI_3OF-+ULJF9h($nB4t{h=*7EVvHz8)#TeZ9vF?&~XS zasJ6Q6?2_skKt}2fV zy9J&qeGgBcYe#=&K0;>>-9>*VTt)wcT|{U7a?v@jI~;q@yv=@i!K?^gn7bfi=ZnMX z@KWb7`0vZz@N%;nHr)5-*zZWLOGGTZOO`PItOab8?WJYs#z(|DR+A(lY#MG33*@7) zpd=DD=ib8R4_}DrI1x_P!xnvYxNq6@hGXYeZDp|a(>mCux>m%_xf^Bhnqn<%o0kLI zWt@WTQ}@CS(Hht>Bp7y*1i{Yk$y!3!T61UEg&zpJOb6)Lxof`@?51~w*R{{X>l^0a z4Y#{tQLc}Oj+2dr&tdlzE7;@2XO5kF22Q}6VxGa99X`Nf?#L?SGJCB5%p z?~$XhPiq4#{g|(1bG}s-u&nVg?3aHAmRCf;isR)XI!2T^p0L0AG#rp@3I~c);2`BN z94t`5DmN33K1NhSE^x@=5WJ;h3EtZM3f@-ltfONjw50~#Ub+B>-7JB3WcI+}Mb%n1 z7m?5kN2Xndqx^L6&Zv{{E}QeP+A{%G&)pIcx}uF0aCB!O95Y}C$A;Dv@c2Bw5#QK^ zUjEmIZ!na{5n?b@YKgJIP+CCD*ms^KuJoTnzuU*fYe;;uh9t5bMfX0s6E#Fg4^;F( T8t*St%H+~`g+iu~$%X#_Z)Mmm literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Mexico/BajaSur b/testdata/zoneinfo/Mexico/BajaSur new file mode 100644 index 0000000000000000000000000000000000000000..5aa6039ea4cb36077f048782b54c6275c25e86b3 GIT binary patch literal 690 zcmb8r%PT~26bJA#jA)uNDI^=A6bj=pUV~v6!(7kn{hC1|r4S1n%tDHkp_KC6D38R( zm_k`9Q5MQ$V<9997DCeXJKujm&h7lp?{oV8Hdk)!cIxTRQi%jNm;Cn=qll?R>l9II zo~J&ZJ8yBA9%rqcy>BwYUTqre{TYAd{poYRUA(2Ft}z`?{XmF|XR^f!r&N8ysWHWH zn*Ihh_{YNO;U65Q^hYh6@qG z!}Kx`#b8v-Q2?Ti-6KF0gGtaUFyB<&3d}b%Is@jLv&(?_7Sb<1fEX6f{(;HiHw!8ble7pX8V7~qA0x;hp{{Wcp*wR}7)W+cCzX;5CPRR%J zUG!VPd{>u1FyD5|IfG3M6nD2Qb70mZ~{2k2q-r)}B`m zKSFd?0Z@WCfET7OC+6|HV8E4FCVnoxs5I|NrU*3>+Ym nk>~&aof{Yhz@&(eZwP~La0r7l5c|3SX%G$%Vc-G^m~jCBO_!h*^=&u`b^MgPM&pXdAVoCC+`C zvcm``=uOA5{41PrEJwHt{|M7CV(p{eibm4Z+xxqm)QESkgF4hS$5Ers1p1CDfgU!6 z(IZ)5bWGt#$39H)^!(i)9`xw55c*!K1$}=ujec-*F-^}soP3HN>rSEL!2$I6@lo_d zXE%D%eg*yL@JaL(>q9@b1~~eigp5NcH7C%?@25NH{>4hy{Puuypxu5#|lxYP!VOcfdDJ2@hZqGWf* z#1XifQD+S8f@|L9!Q!rRxHkR~D%*46x~tQ0ee(h=ITL{!bP}EjqjJB1rSkW1Bg=5Y zHrXUol0-UpWk5fl8X~DqO5;i+2a4d2nnW$ zFoQ`(Ovtqukr2`sr|aQqMn=~}Y_&Ov-F1LIu(CLal(trHu)8b{jjfigVRaf?HLGWJ Hl~vNe?I}r+ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/NZ-CHAT b/testdata/zoneinfo/NZ-CHAT new file mode 100644 index 0000000000000000000000000000000000000000..f06065ebd18315683f60cf87839d477a1d699f01 GIT binary patch literal 808 zcmbu-xl0^T90%|>Uf_7F7mGw)vmR0R7wQJAa>;eXql%c_?1YYrH2--=QZTZNiknW0<-&2Tk1@ zFm37!Ojl=N#y~I3w2Z*44{r@0dZ4+|Zg@JZF-o?z#c<~%d?DBj7n)(t?_`+!wG8HM zoI^`*63n03gD;!Tpmk^k7Pu01Mkx&M!XndOSS$$|ZL?P~_2?xjCmK~&@~24WmY!{E z+_J3%oooBKpmFVyLg-i?h0d{fD2?~Q@=vGG)gOfNyB|>L21S=25VAbIjtd91>n)OtTQT!9_=&z?Q(bdl~`kTRh^xCfXu&($x^FPKScZ{+W;6LAHmmo40ZDVO|!4R{{itMG??cuXR iv*?GaQ&y@yUMh5?I)YV_S8|o}El1EJ$+ULUT6_eHWtUF? literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Navajo b/testdata/zoneinfo/Navajo new file mode 100644 index 0000000000000000000000000000000000000000..09e54e5c7c5bb2384e37626d4b985cfad29ed29b GIT binary patch literal 1042 zcmb`_OH30{6b9hiQfNDlGAban#Rn**we|%SS|6acqQ*voHJ}Sk6CS~hsIkU{I!e{B zFiez%O28Hf(HOPFji!l0jK;*rqHaVJL^moLW7LF7q2s-O)GZtDITiC{kFCT$_~lcinouj~eRN)v*ol1BtKpZeGUPrs^%XP$WA z^j$YBUo)`JBjl1^U`cT<%@R=_oq;nB>O^K$us~utvvyi!IjcGatLEg)8Y;y8vQxL= zqFpjvy#EY&1)-G5r>Wi8}n}UAzZg-}wcu>OKiqA9w+82zQIDv2jNX-qd&;_S!DMKJPx*_v4YE zRQ!1|RR7Aqt^bl`xu=WJ-}y#Fp`x`!G^lyJh3)z%dAeT N-QssRtPZQ4`wbnj4)_27 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/PRC b/testdata/zoneinfo/PRC new file mode 100644 index 0000000000000000000000000000000000000000..d6b66984a2f36ae36b35e174756707aa7286c292 GIT binary patch literal 393 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%P-o_>38EKFU(^7i7gn--0MRERr?p`IRaYgj{57BbVE%QR{b2qL zwzL9}IX7iLfz{u1toZ$;V7>;sJD9I=$w7dL5f5ZwD7+3bpl$*q3j;$z0|SSTZwQ04 P3lIl~FmM40T?;M%d{}{0 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/PST8PDT b/testdata/zoneinfo/PST8PDT new file mode 100644 index 0000000000000000000000000000000000000000..aaf07787ad92b65eadae63b64bba290f9f961507 GIT binary patch literal 1294 zcmci9*H2Sn9LDieD5GT^k!3}#fRvU}+Ol293PTAX6-Nw;QA|w?AV~B=#E63!iUt?{e^uDUh_zbTc#Chy5ydf$}g%hG-_ z7wo2OE3Uy@hxsMi*~H;~SN9$GbM*tXyYU?QrSu}&Q>jP4>T}WFqRr^H#I5M}%mDO< zJQ(eZPh#os^*g7b12W}8$Ai#88^?v3T+yF>W9U%*6gu2uLPrek=xFT-N8dM=*8u-2 z{{WAlY(^(?9-)(aZlk|bE~9@U&!AI*h3K^3EtbA##%TvUYg+=(PM?<2^SOa+c)slb z{P$G?Yr>C<-P8(r^yXo(L4jMte=KgRdvGB zLVqb4XI7tj4tr%dz}|;CSbFXgG77IrdItNteuQO;N?2wdHj*($E-r@U-S1(=;6B*D zu^v{o7IAbgpt1s1J>Clk79EAv716Nf;3X*;W3>4`a8P^!9Gq?qhsZMEQ0)L5W)lvF zds?yNF($lU0!PgC!)sgS;dPy_;q`SMMl!~1Xt)n=ET4rVub07_a=PHCl4_35MW-~v zG5asTv4KW7F7_}SH_{J~iCI}~o%H$xGR;5-ZYcwj2N-h2ezA3}w literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Apia b/testdata/zoneinfo/Pacific/Apia new file mode 100644 index 0000000000000000000000000000000000000000..a6b835aab4c5e2e2a31bda0afdc8646b57d19a87 GIT binary patch literal 407 zcmWHE%1kq2AP5+NDnJ+nLI`V-0xDw%VyXW?kY{_60Ypz^{R5_NC9zn5%<-A8z5zu0 zPS<__qWx+gC4lL_-3vgpe>v|15FL>A4@?IpXeEI7L2eJg{9p$jFh4}?5SSk-{|?L# zV_O2|hyA|*=7&FP1M?&9Zvyipk7a=QQTwNW`O)iJ!F0@u4Pf!u{&X-uu459IAD{0D z<|ky7JYZyEVP;`wW5t9F3>z94fc}eT0FiMX3@rcu7bh@s{r{gDz`)1Au!h*^=&u`b^MgPM&pXdAVoCC+`C zvcm``=uOA5{41PrEJwHt{|M7CV(p{eibm4Z+xxqm)QESkgF4hS$5Ers1p1CDfgU!6 z(IZ)5bWGt#$39H)^!(i)9`xw55c*!K1$}=ujec-*F-^}soP3HN>rSEL!2$I6@lo_d zXE%D%eg*yL@JaL(>q9@b1~~eigp5NcH7C%?@25NH{>4hy{Puuypxu5#|lxYP!VOcfdDJ2@hZqGWf* z#1XifQD+S8f@|L9!Q!rRxHkR~D%*46x~tQ0ee(h=ITL{!bP}EjqjJB1rSkW1Bg=5Y zHrXUol0-UpWk5fl8X~DqO5;i+2a4d2nnW$ zFoQ`(Ovtqukr2`sr|aQqMn=~}Y_&Ov-F1LIu(CLal(trHu)8b{jjfigVRaf?HLGWJ Hl~vNe?I}r+ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Bougainville b/testdata/zoneinfo/Pacific/Bougainville new file mode 100644 index 0000000000000000000000000000000000000000..7c667093c50d33ce9161662a732fcf6c5092a38b GIT binary patch literal 201 zcmWHE%1kq2AP5+NDnJ+nLI`VN1u6q!(f>dYwk=2lL>IkXG66)NaW+c;(U-JyK7h@e zcfEm;iJ6IofnnkekU-}L1|Yj<0RtxkL)`=hUIvC)8yEzAd_x!le1U|vp#g)ofhCYO OWZ<#^l6Ja=hFky?{3-7M literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Chatham b/testdata/zoneinfo/Pacific/Chatham new file mode 100644 index 0000000000000000000000000000000000000000..f06065ebd18315683f60cf87839d477a1d699f01 GIT binary patch literal 808 zcmbu-xl0^T90%|>Uf_7F7mGw)vmR0R7wQJAa>;eXql%c_?1YYrH2--=QZTZNiknW0<-&2Tk1@ zFm37!Ojl=N#y~I3w2Z*44{r@0dZ4+|Zg@JZF-o?z#c<~%d?DBj7n)(t?_`+!wG8HM zoI^`*63n03gD;!Tpmk^k7Pu01Mkx&M!XndOSS$$|ZL?P~_2?xjCmK~&@~24WmY!{E z+_J3%oooBKpmFVyLg-i?h0d{fD2?~Q@=vGG)gOfNyB|>L21S=25VAbIjtd91>n)OtTQT!9_=&z?Q(bdl~`kTRh^xCfXu&($x^FPKScZ{+W;6LAHmmo40ZDVO|!4R{{itMG??cuXR iv*?GaQ&y@yUMh5?I)YV_S8|o}El1EJ$+ULUT6_eHWtUF? literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Chuuk b/testdata/zoneinfo/Pacific/Chuuk new file mode 100644 index 0000000000000000000000000000000000000000..ea3fb5cd3c9e5e132c19a5320516dbc45a089135 GIT binary patch literal 195 zcmWHE%1kq2AP5+NDnJ+nLI`VN11e(yVxIp%Ao6g(35c#UQ`-WfX9zBS0HPOI{`>%< zPrl+x0MVBO`93f*F$3ZM|2AhpHud>{$esltv+5==aQOI!FlZYZFlZZCGH}@dS$4XH G23!C=%Q2|{ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Easter b/testdata/zoneinfo/Pacific/Easter new file mode 100644 index 0000000000000000000000000000000000000000..54dff005b876339f5c1ff3dc0aeae1519c29b368 GIT binary patch literal 1174 zcmb``Nla5w6b9himPtwl1QAda2M{eoCrUvm&q}2T1(Yg+6cG$k7M2hsCX%Quq`HtH z7(*g)SQtbD4_p8VgcoBRap-~|iNuW|(HI*viX+c^|GG77JTK>+`@M5cy1BKLJ8HFL z*^tl)mMm<`uNi4j0-YtK@iotiry5Uu|BXC$kGaSCV2VNc8#k0AH_)~DiLK7V6XNM!*2jHmr zY&d$z0Iz*f!4VqkI-}v3K_k4r;TOE2Jr<5VEmN_%jZP`NDg7tBx$rH#C29_iGZ2B$ zi2FVX$A9_;Z=JmkCoJBFx80lI+1&P-o3Qf6RXB0P1t+zhg_AGW!ztA@u{0@fVEjOD)wE+<-@7+99XXyh12||F>fHju;FO{`sweK0-=%7{~q4)SOI5Vn1ZwV zJg~8T0M2%~VXou}PuIxKy1TGRdk5ZSxdi8gU4+f*VUCUw^XCRQH?$kh^+;9hyJevn z&Kq~ad)x=%{857Wf}sr9`oJIk!s1qe&?vexfPS%Q7T(*^0q;|O`dr+jF*HISZ%~iGfAbV gnMN~}1ZGkh_4J);OthvatCRI98cm{A_xBX|2T4)%{r~^~ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Efate b/testdata/zoneinfo/Pacific/Efate new file mode 100644 index 0000000000000000000000000000000000000000..bf7471dd3fc26b7fba883acf0e0bf0a69687b31e GIT binary patch literal 342 zcmWHE%1kq2AP5+NDnJ+nLI`US2P$I*VxIp%FzM@|Eg*gDl`|c{^sh5uTJqBO3n0GK zp<4$)wDhK%V7|~8@eak-{>V7`3y4KQCJd$$8fTrqkVn6KnL7tB|-o&)Bq zXxD@Js?v2}z8ZHTn6LIb0nAr_?F{B?JgK?B00f$ifndJYOAjz#JJHyIi4iMgV3>Ob kq-DhcMivH!SsNHQe0)O~v<;1b*pPwC21wfJ8X9r|0JO|FDgXcg literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Enderbury b/testdata/zoneinfo/Pacific/Enderbury new file mode 100644 index 0000000000000000000000000000000000000000..2b6a06088ef603f03fb482b628347ff72970fe3d GIT binary patch literal 172 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#VuAlaa9HPd1CY%i6vlD@MC-F!ZeU~rDFK52 t|HB;^SpNS{4PfA4VAytnfk)TCfI-*L2#5_Cv<;0JxNLx=ovxuV7XW_87Tf>; literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Fakaofo b/testdata/zoneinfo/Pacific/Fakaofo new file mode 100644 index 0000000000000000000000000000000000000000..b7b30213e154012a5275c1384b41dbff29860644 GIT binary patch literal 153 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%P-h<60n+F9cjg90rvLxrD;OC5|4$8I hU}0d`c7cJz$2WvQ*U*qb+t8SS%LYi==^7ey0RV5D7HR+h literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Fiji b/testdata/zoneinfo/Pacific/Fiji new file mode 100644 index 0000000000000000000000000000000000000000..610b850b1dec4966d570eb36f9a8b35fd6aacd68 GIT binary patch literal 396 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%FiUvj0U(>f%v$^bn7;li0YqDj8)kGdY<6rf2y)0MQY$Pa$-b9+-~&dmKzhMG1iE=({Vybd2RE zFdcjBSONnO#7SNO^W*QagZT+e9}}1u@jwQK3@kprAq?7vh74Rb LK+;av(2xrNoShE_ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Guam b/testdata/zoneinfo/Pacific/Guam new file mode 100644 index 0000000000000000000000000000000000000000..bf9a2d955fc23bb6c2043472e8292d4adc20d4ed GIT binary patch literal 350 zcmWHE%1kq2AP5+NDnJ+nLI`US1uA0$V$uIVAoB3&84z7(rt1TuPn%DD0HQDGb$$TR zZ_M{Gfav#TKfwIovl+nrfA;D>LxI7Ffh#8z{mp@5%BR1VQ>!)VbC_PWN>#0VQ|g>a=1XGuAu=J0D+8M A761SM literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Honolulu b/testdata/zoneinfo/Pacific/Honolulu new file mode 100644 index 0000000000000000000000000000000000000000..40e3d492e6c22c30041c31f159d4fe0ee9451c03 GIT binary patch literal 221 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I&Vv+wqQ1YN)ABf(~>g)lg6$>Lk^yyC96CnDM z@|OZIo#<%+qObNAdoVIFGP5wU{{NrD#J~U~BN$lz|F6nmg)lg6$>Lk^yyC96CnDM z@|OZIo#<%+qObNAdoVIFGP5wU{{NrD#J~U~BN$lz|F6nm; literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Kiritimati b/testdata/zoneinfo/Pacific/Kiritimati new file mode 100644 index 0000000000000000000000000000000000000000..2f676d3bf5c8599994bcabd402ca30efa4cde5dd GIT binary patch literal 174 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#Vxj*)P-pJZ0Aw==g?<824En6v3mBQ0|NqZv xU|{(FKMSbz|Nr6y1}+AMBM%t(e0)O~bPWwm3_v7%< z556@8^H09wN&xXM3G#u(|F=m8fb28tPIq8rVrF7tW@2Uf|KHsQBsk*?h@7>7frWvg uZUO@b14GXO1|9~66$cmue0)O~v<(dzv<)nQv;hzsF>u)cMeKA94Y>e{!9$S% literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Kwajalein b/testdata/zoneinfo/Pacific/Kwajalein new file mode 100644 index 0000000000000000000000000000000000000000..9416d522d0a3e19ab6b81317f5b94961c55e91fc GIT binary patch literal 219 zcmWHE%1kq2AP5+NDnJ+nLI`VN11bYyiT^-QXC|Qlq7S|`y#S(5zT!#%(dXS7KY-}} zZPEcCb9Ku292l9H8Ch5v80I_xiOkx-z{0@Lvw(qvfuU{!1JD2e;SLM}3=As{Fo^j0 fhA?Ow8UnEagSLSsgRY?wkZr`kWdkJbfIKb$c@{B1 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Majuro b/testdata/zoneinfo/Pacific/Majuro new file mode 100644 index 0000000000000000000000000000000000000000..9228ee02ede240cc6c5831c8e54ed8216216ff23 GIT binary patch literal 218 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I)Vv+wqP-iC60HS9IPQ3u47g+xM0HP1RH3joe zzT!#%@z2}37l7#hZPEdZOpMG-j4TWc3mSmNFwEM(0A$xqVBlb2=vlzP!@#iO0E2*! dZwQ07p&^5|fhCYO0AeEsE*l_er)y}$1pw{IITio_ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Marquesas b/testdata/zoneinfo/Pacific/Marquesas new file mode 100644 index 0000000000000000000000000000000000000000..6ea24b72cd9552c973510d1c17ace66fd35e1cc5 GIT binary patch literal 139 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;uKz$VCBVmn@&Er?3kHV&|En?>SbTg#7<3IR RjSU#MY{0agrIoP(7XUx`61@Nb literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Midway b/testdata/zoneinfo/Pacific/Midway new file mode 100644 index 0000000000000000000000000000000000000000..b25364c599463a5683e33c16577545ee8d028908 GIT binary patch literal 169 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#VuAlaP-h z7?~Lu=G1`r3wMC@)Jvyq$^g?_pM&Wz z{%2r1R$@~CBNHV9bZEOJwrVM9bXd=rEkmy0OZOh*Z=?k literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Noumea b/testdata/zoneinfo/Pacific/Noumea new file mode 100644 index 0000000000000000000000000000000000000000..824f814160ee4a95cc6a6d5553b3c1aacc907895 GIT binary patch literal 198 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I*VxIp%FzM@&5|BQ=XS)JGG=JFc10Y)9*c>ol z(EPmvh;OvO`vZtJmT)OxVgy45hB-VSp%n)hSr`~*ZD8Q=@eN_nHZ%faLk2DzAZe#- HXvhTsP@Wrk literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Pago_Pago b/testdata/zoneinfo/Pacific/Pago_Pago new file mode 100644 index 0000000000000000000000000000000000000000..001289ceecff85fe0d0f376a6bc394329445f13f GIT binary patch literal 146 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VvhenkY{@WOiyI}&A|wi*;v8A@c)1O4-lCe Uz`)|;8^RDA9Kyf_Bn%C?07{q{2><{9 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Palau b/testdata/zoneinfo/Pacific/Palau new file mode 100644 index 0000000000000000000000000000000000000000..bc8eb7a55b8a20a8c800507b620d0afef1d477a4 GIT binary patch literal 148 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VvhenAoB2h4v4NZGke3x^#8xk6p$%(B4Ba? W1B;Ju2!pnPB?FfYkhIgaO%~b! literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Pitcairn b/testdata/zoneinfo/Pacific/Pitcairn new file mode 100644 index 0000000000000000000000000000000000000000..8a4ba4d30a6b7da8399f20a8b98c91169e04ae40 GIT binary patch literal 153 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$V!r=CP-m|91*Ff^#fgKF>Hq&W9tMX0|2rxe eSpNU-Z(!i^@eN_nHLx%?0Few_HbBzOf(rmy=N5|q literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Pohnpei b/testdata/zoneinfo/Pacific/Pohnpei new file mode 100644 index 0000000000000000000000000000000000000000..b92b254a9af107fc4e40c4ca38d1ddc110effefc GIT binary patch literal 214 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I)VuAlaAo6gh4v4NZQ&%< z556@8^H09wN&xXM3G#hlWMXDwVP^XO-{}g-$|)fra@Gb076yj82@D(z3_S}Nczk?A Z7_%< z556@8^H09wN&xXM3G#hlWMXDwVP^XO-{}g-$|)fra@Gb076yj82@D(z3_S}Nczk?A Z7_1;1{MZ} do&^k?KE5Fg0lq*&+t7f4%LYi==^7ev0RZ8E7y$qP literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Rarotonga b/testdata/zoneinfo/Pacific/Rarotonga new file mode 100644 index 0000000000000000000000000000000000000000..7220bda0adb9f04d704cb893a5d1ee8bd9173b82 GIT binary patch literal 406 zcmWHE%1kq2AP5+NDnJ+nLI`V-0V-n!Vv+wqP~&sw1c<)BFyRD9zrY%44G=A8zf}T6 z3sp8MfM{X)>0rJ{WHOj9^1l+y7qfH)^Tl3FodHrOp_I4)OrIzR^QD-a!F;I|kzl^` zBULb8ro$S{mp#M|=F4Tsg8A|bUxN7x?*GAj#m3WMzLKGg1OpH#XT4AW(JBJ}zt-9Wiayj c_=Yg(8X6cIfJg>i14|%_%Ld4{Gc@1=03*mq1poj5 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Saipan b/testdata/zoneinfo/Pacific/Saipan new file mode 100644 index 0000000000000000000000000000000000000000..9539353b2cbe7140e9aaa6f0245b4d5a4e8b090c GIT binary patch literal 341 zcmWHE%1kq2AP5+NDnJ+nLI`US0V-nyV$uIVAoB3Y9S~h-rV|6AF9>#g0MT#E_c4Iz z_hvu9{NJ+~!2Eyq>OCOw|BP~A{{PsB4}M{5)$?#n1oL@n+QAxm_fKg63Gk&Z2CKJnj!R%q6Bt++ t7-nr?<{9 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Tahiti b/testdata/zoneinfo/Pacific/Tahiti new file mode 100644 index 0000000000000000000000000000000000000000..50a064fa0166a0dc22f89cdadf957a545d3f6544 GIT binary patch literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~B_MPM~sx{xd3&SC+7eF literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Truk b/testdata/zoneinfo/Pacific/Truk new file mode 100644 index 0000000000000000000000000000000000000000..ea3fb5cd3c9e5e132c19a5320516dbc45a089135 GIT binary patch literal 195 zcmWHE%1kq2AP5+NDnJ+nLI`VN11e(yVxIp%Ao6g(35c#UQ`-WfX9zBS0HPOI{`>%< zPrl+x0MVBO`93f*F$3ZM|2AhpHud>{$esltv+5==aQOI!FlZYZFlZZCGH}@dS$4XH G23!C=%Q2|{ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Pacific/Wake b/testdata/zoneinfo/Pacific/Wake new file mode 100644 index 0000000000000000000000000000000000000000..71cca8877d33561091fe0faf319f3d3a4f14bbc4 GIT binary patch literal 134 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iVVXC`q5C@{waq%< zPrl+x0MVBO`93f*F$3ZM|2AhpHud>{$esltv+5==aQOI!FlZYZFlZZCGH}@dS$4XH G23!C=%Q2|{ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Poland b/testdata/zoneinfo/Poland new file mode 100644 index 0000000000000000000000000000000000000000..efe1a40f2a8ffd499d22cd83e6b5df6c6c1e8e5c GIT binary patch literal 923 zcmbu+?@Lor7zgk(byj2M)#;{7OYrAt;OA#L^iTEMk$>@(!jN|a=ce0z*QtNz?kLXBUfw}I zS7nf?9Ob6pN5)<; zimVsCFuU^s%(>qRk2c?cx!2q$=wdk|XdB7!15jxJ?_a(A)+nK8`}y)B;; z_&3Q_9OQpQU`dRbEQ%DWFm1I{V(0m=J8Ec>n1dD$zEJV3*h+QLX)~WPTSTYTLYCN6 F{{iE`PO1O^ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Portugal b/testdata/zoneinfo/Portugal new file mode 100644 index 0000000000000000000000000000000000000000..7e9aae727b2b660e7f5e383121f445daf033a9c5 GIT binary patch literal 1463 zcma*mdoWZ{90%~bu{BtaC}F8(lSr&bN>kI6G#R8}8#GCSkxFI6)HF>awim{rG!4pH zjAkS6&?xfAD}+?!6(J%k38{3?_x{s=+&gDK=lA=bb9VRctnlb5e@kk~i$$*>gIvO; zx5UuPR?>sJNMFZybM%Pu!!cpRB*(Ks@NX^Z_8FKTWPpA_ z@GV$)SRNKzI>8dvI>yCPSUM?%Wp%|e@;RTEJc2J$ywNYeABnmmQ3hXL3WSvbUa-pJ z5Uk$A4kG(&b_h_v+IbJwdSszr+t~-}<=Pmhc(7r>M@IHF7P&Hxr}dNib(kY#H}gE2 z60DIoRXLs@d2_G?d2>xU&S?qNMBb8h68$%>BF2nVo_vv*oYN}_g?;h< zus_@#ehNMa2YhVdpsNY|ypIcqEIDvk{|_AD8uQ3`UzBth7nI=W*l#%2H37di^uqCH zEpS3w0ly{Y!O2JolwH09r%sFDci$W_Ie*$s41d_g!5OP?_>+GD&T9CLTun_KO?9v)Pfq$`_)Lk#_AX9wfvqiQfq27 z!*z1yjMKSLYcLgRx5q=BstCv}%c01nnSJXeMfe<{@QJ z;Fk?8ygJpW6|Cjoa`f8&$8vYdFSSsfjhnT&IO|Kksfrp)o=7RsPnE|~CLKy0b4@2_ nA?0rGMqbFED?55(M>>jhOF%MHXDhR9W&(2yQ)deSnJNAQHdoT( literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/ROC b/testdata/zoneinfo/ROC new file mode 100644 index 0000000000000000000000000000000000000000..35d89d036d07c3f28dec64092ab1b533c21ae2bc GIT binary patch literal 511 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1S(?zVuAlaP;%~r1c*Ky>e&FIFNH*c>C4^KVET&F z+7BS{tFB56Ao`lmelY*K&3-Wd23uMINc^VkC$RdP&u4<=Z~a#T%ilh67A$|~0mR(9 zs~EuY_lk>Q6a&ZGE-;_-Zf66C&vkC^2M{fIdtn2J77Dprz{teNOcZ2bD0~6ZRL}s5 hfVv3`93YaB$HzB>!8tgD!3&6;T|yYRfE-;5E&yjg_Y?pC literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/ROK b/testdata/zoneinfo/ROK new file mode 100644 index 0000000000000000000000000000000000000000..1755147fab44e07b7527ce1eaf3ae991473fb222 GIT binary patch literal 415 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0$VuAla(0%$Nf%!Mj>OKJRZ(Z*KtGm6HAI!h=>=BrMx9206|Hxkx%zu)-9c=DXVTlZo zzGq3yVEdj6`n&+~U+5Qr`7fS-0n5MQ4+8UF9lr+VzkY85=D%6K1I&MWUJT5C*FFo( z|6p2J0rI!P;)DqxS}`vjOe-}zfoWww&k2l7EX+{I$chBPVhjxB93YM59SkfC40RJ2 mfV`dsj67gAP^5JRBae@72!nTU2!j_8d%J`%Z~-~GmRtaloVXbP literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Singapore b/testdata/zoneinfo/Singapore new file mode 100644 index 0000000000000000000000000000000000000000..dbbdea3c8149004cfd525a0fc26e5da72b20e8a1 GIT binary patch literal 256 zcmWHE%1kq2AP5+NDnJ+nLI`W&04f7vh5tZMXBNB|M7K4!g6Uo9eiK0a16)rMK=i52 zPr>x*iSZmD{w0sx40Pj65Kc0Z3+6 wFbFX))JI+5H>OZk;Wj>5{NArxNLx=ovsBJ0BYwwz5oCK literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Turkey b/testdata/zoneinfo/Turkey new file mode 100644 index 0000000000000000000000000000000000000000..c89186687300068ac4e8505cc0012a1dbf6a9960 GIT binary patch literal 1200 zcmb8tYe-XZ7{~E5FSAXTNrVmOrEG3GwK*+k&CQxqv}sGHf@y>|j6@_03WZimUM>(6(qq%OZe?4YG+iU~q@#8%7`<^tk zL+gW{&{qJw{j7-*faZ4j>uX9k_rVRLpDDSEXC!_7&UM|3ozBb%#WR9z9=R+a^~>r-L0 zN(y(x3!zxVhcSU3DDjsx(ETOutx)=n2V)(7VBE_EC>xrA@s_tRp}oaL`x0C4qIaIW z4&_ysVN&@M%oQiPU~+mlOer`6cZHkaZpC4*D-}=~cDjM?tDMb5r+G@zd!ELi_fD(O zDytTzKaPOv3u34-Gccnj0PbrQx#)iTb@OO#@~ literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/UCT b/testdata/zoneinfo/UCT new file mode 100644 index 0000000000000000000000000000000000000000..00841a62213e6cccf7f0b7353e5e8ae214185486 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/US/Alaska b/testdata/zoneinfo/US/Alaska new file mode 100644 index 0000000000000000000000000000000000000000..cdf0572be31d3052a98494e3d01802b83737f23c GIT binary patch literal 977 zcmb8sUr1AN6bJC%=G>o~)yl0u(`-5CoUZHL{FCdS_s%U>Hqtf9i&gJ(z=X374+=r7m(tA9> zmJJ=BphJ;Z{*weB6Zol8c{EQizNCEaiV~%q8*a=}&bxjjk-I|@6y>Ey$7IUt zojnr$kKKyMlyq0CVEv#6F6a+usBh?Q$x<%tsDzD*8#ejPu<80y*kYZBE$LaAk2B%x z3wXtc9NrhbnUko$GMk21P37R#cV}ekTgTGyn&C-!?U_-yxOW7$b@s#dy-9doFb=Qx z9)vfP_hlH5jh1@Yq3?hlH8v~t9p6H5$tQP;T$-{(jK(41EofxYkE!qxLhxaP@I*!SvMijT3a zw*uFL;|t+iz28v6Jy=`mF6Y zxbPF+{#?NPj@j4n&WyI-U5}^W-8Z!THjj_Pa-X(e_f0T6k0)xKL_^-!gG5_Dg*t6e^sp`NW?k;9f)uE)$jJt^UyO@1%{2b<|ou4Qn8cwiID%yCVwDC%yJ4p7$>coI3`C@**=ocm7FFwuL-T(jq literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/US/Aleutian b/testdata/zoneinfo/US/Aleutian new file mode 100644 index 0000000000000000000000000000000000000000..b1497bda631efdcb6635ffb6b0ee6f7da9e2a280 GIT binary patch literal 969 zcmb8sT}V@57zgloA38U!R&8r8EjOz%UGtnxm-gk^nrPAL*iJ>eFc*Db5NSdbO?olJ9< z&oAKe*9H7uQJ9seKTplU^B)x81tZg#w_eV{3p3;JqLbI)#XZBYZO>`gzBvs$T2k;5 zUpMUZ45*B+N^=x;>G#5}dQT1YU0-B)=}ag~uF41D>Ipl%?5+)7eq$D{Io>YuG3FjD zz@A+`xc2aOf%+@LmrF*ScM_}n_@qHs_9%rc^-Clg(P5W=cv4)2# z_1j_@xb5pFNvAg$^(CeM`b_4s|N9ubJ;Ru$CHK*JKxRfw>+jZ;;jBQ%irPjeb86aP yudW((<<_{uwk7!9&9|(uD6gY2g+)4e(ZLG~FGPV?{&*-53<&r^U93H~J1!S0W0RTV0SUUg! literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/US/Central b/testdata/zoneinfo/US/Central new file mode 100644 index 0000000000000000000000000000000000000000..b016880653929aa40dd5ac0e82e4094a9d787cdf GIT binary patch literal 1754 zcmb``YfzL`7{Kwv{UQjZBm$vHxgogR;v%kz!4Ba>SgseW(IHKuX<|#1ai+m_B26cw zG{@}1#anoxMK?ksVMQVaYbHU74c!*9l`v%$Qv}*=&;OI(^h4*J^FHVIT+aLH)vPF3 z8!zs=T$~+p%cZ&hh~C-e>D<8%=UVAzuavR;P_$0Qitp}fWvtvX5m$ZIi}#%^5;DL4 z-8(iJ52!n-A6#w1hZdWte-*Tc{_2EATx~Z{KQie{e8jvPA06I=k2MwJnyx(jb$Kq< z8`5!Y$y|K=i&Z-L-4prCwK5vsS%AOEOvQCCN8oQ2VYpu9flqqcaYN`8++elfMh|x( z?`dpn!QWrD;!}FFP3D_g+i`Q55gS)@~%Uh-)mflFPit@ONT$w%DlO0BmRBc+t^b667DO|;Qo?%_>Zh4 ze0k+G{O2;2P0m|0RYJxq$>DfF5sv?wBJiM>z=OB@@l|U-{=2&sUu$c{*PHva@}42R zMJJ=J;tak~)`D+tI*5l058zv?w&H(sw&2_I3-Fzo*YL=b@7d%%cLNsUQSW>_I+8DB zerzBMkN0HZf7_$5{bUq&RQucH|0F*3C%9}K!mhJ2I~3R_@C5d$*)Q9Luk8~&!Lp0GpQ+X+^Zv&5cw)m&9B_E2OpCz1Mfjm@Mfl;3 zOYx+FrFe2~3J%Ij!H>)d!BZkbaPW*|tvpQi9>*cBQ*p@6V4X~a_Ko4NbEEjt)0c4g z@r!s`RWqKxAwaf^$2M2t8B1>9h}TcqVA zC!FjRhEqZZZ1Rv|wc|Ns9XPekg6H-g!z%r_PA29xeu$qgGvoQ6YjIkk5icm+p_P5l z- z&bkfep9)t3^H1Gy2lG#N`~&kZDSrX;FC}t*0O`A2`k4VlUvYR1=3foH3g%x^I1A=q zH{A~A-(Xk|=HC>Z3FhB?FcHkZ^>1qfNdN5v#bExOd(*-EyDKLYfW+_Zs|54!cNT&9 z59URK`42Ng!2CybwqX8aPctz8Nt`^G|KgL_2ax_(K%ax?e>-Hr{Qt}UKLCaW1H<%x zA3zji`@;ty+C{&t07SdGI46MV&nrGKF@hm83zPxjLP%C7RyGLy|9`y|$c~*G7+L=R zU%h~V1I*?DlL8=;LFE7c;|CZee0)O~oLzu87>L7xI3R?<707l4ig5uMra*>{ud$wy Po`H_9p`o6ko&gsCE#d-; literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/US/Eastern b/testdata/zoneinfo/US/Eastern new file mode 100644 index 0000000000000000000000000000000000000000..2b6c2eea14df07392729ae9f5712a44ec4f02bae GIT binary patch literal 1744 zcmb8vc~FdD90%~HLuD)FSXb_AZECl}O63S8VJF8nxh5}Dn&pq)VT2iS6v+%R8pbh8 zbU9ZSR%{`w$+%iaIr5f-h*vpM?0TNB|CxR}&wlswdw;)Y|Jv0o(ys6$|1BFj!450U z|5x;MtP4H8th8e6#JwzaIfHnX$F6+fSRUU&;LO8!;S+K7@X6%&0(+jd@;sca%Ej}X z`IRE;=StJyJpZ$Bo+TUer+e;!PuHfxXIgpqtWgV}GtYz1>t@0F!m;p$ByTwX=vNYrz$W!Zp51fXEeNjgj)5!MqB+*D zbPa(ks{`RXJ4Lu^_}9P5bzslDwn1d`k3wF;kE2ZRlOd(>Q&k>ZO)}vc=`OfNNQR$T za(TA@yetlWQJV(8JhhEu{aWKH_*GggEa=p5opw50pQMCeM~sFWV!Fd`q7?$$Zw&Vq zS-uT$hu_KE;P<^-;3kJJaMSlk@P|e-{PD>}xY<+;e=0R|?4Hm1DxRfytQh{1UIe#n zJ_xra9Du(r-2i`!Tn~SrycqtWTm-j`UMH}7e!5M7+npA|?QIK0*6(;14F9SQf`3;G zge{i`z}8%=Kz}2I9JGimY*On4mbU8z*p9bw%=X-Go@JLg0>{!JY zr4e$tcc2U0NA3*w9VX`pt$t3;aDQ88xPOa;XMK;lW_ZBEkMO|j_u)bL_u#>q`S6fL zg8iXe_rt@Y>fzxl^#Y+aLRAiroVgDkCC!0lo@-#4g)lg6$>Lk^yyC96CnDM z@|OZIo#<%+qObNAdoVIFGP5wU{{NrD#J~U~BN$lz|F6nm%jrfD_Iu{Og$fkDtD77dK1QjsA+v7UaF8NS4P$$W^) zg0cs<5kwND1!4xJl|&RlGc=cf+N^9?x}WBQscqf!?bY!9IQN{-`JH=Ten0mi&+!7b z;*#(Q3R>=!j~wA+NjwY*zN%$$Kjqdt7B6Mrlivbm|AkaIaBCQTdod38=gz_XH7b$j z1}X*^<-zQC@W;X~c!;&bA$k=U^W^ z^{Nk^?uiI=Ppm!cr7Zeh!ZVj&z;j0%;f47Vm|u)KaeisY3IBPW562(p!->0Ek-iVR zsYQ}B#$f5W7%V%b5vY*YqiSA}ji(Y$KUf0moh5L_4kNra&j=fGiUle% zlb2wlG!r(?8obn47g>bY2N&QC&qra?!x12 z58lu()!iYHCldGkEE%;1yN-62zR%@myB$0Z@TlTZ?q+4YR`W&?e_?TLw-#7!7MI;_ IwOeiKzt^*oeEd=SfEud|~LmP<>G3sVCKvOnOG$C<=8o@`R zQ3D%dLPXGDTp+k23c*Lv#6(3F;3GP+FvN&X#FbUYdq4gFHlE43XMXp7cUB`Gj5Ygc z$uhA7Z(j1!SL#_TiM8Ee)iLTg#AkPT7xDT0ysq;3I``+|RN@-0`0H?K3*xw{^bh;CEG|a-eErS}d+8lTS=ha<>w`AOc zov!1s^Y3Go=R~0a7C+pCU0;ge{IPSedrDSVjJEc~VCh~VT+p@)_H^1|Z#1g&obT8# z*k4@>Z`=DG4mk7SLf;r%l$;6|XTQ~mRq^NVa7p|DTskocm%ZzO%Ll)yJh%P+DY)YD zE4cF75xDB;FubGvq{3pfb59o>Y&;By3R>ZCC8=oJZ_0zH^-t z4P)dkr5MK3ag!CR4Qu-Dh)ltKGKG2XXI;-aB$L240_?>d@k>6*ITiC{kFCT$_~lcinouj~eRN)v*ol1BtKpZeGUPrs^%XP$WA z^j$YBUo)`JBjl1^U`cT<%@R=_oq;nB>O^K$us~utvvyi!IjcGatLEg)8Y;y8vQxL= zqFpjvy#EY&1)-G5r>Wi8}n}UAzZg-}wcu>OKiqA9w+82zQIDv2jNX-qd&;_S!DMKJPx*_v4YE zRQ!1|RR7Aqt^bl`xu=WJ-}y#Fp`x`!G^lyJh3)z%dAeT N-QssRtPZQ4`wbnj4)_27 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/US/Pacific b/testdata/zoneinfo/US/Pacific new file mode 100644 index 0000000000000000000000000000000000000000..aaf07787ad92b65eadae63b64bba290f9f961507 GIT binary patch literal 1294 zcmci9*H2Sn9LDieD5GT^k!3}#fRvU}+Ol293PTAX6-Nw;QA|w?AV~B=#E63!iUt?{e^uDUh_zbTc#Chy5ydf$}g%hG-_ z7wo2OE3Uy@hxsMi*~H;~SN9$GbM*tXyYU?QrSu}&Q>jP4>T}WFqRr^H#I5M}%mDO< zJQ(eZPh#os^*g7b12W}8$Ai#88^?v3T+yF>W9U%*6gu2uLPrek=xFT-N8dM=*8u-2 z{{WAlY(^(?9-)(aZlk|bE~9@U&!AI*h3K^3EtbA##%TvUYg+=(PM?<2^SOa+c)slb z{P$G?Yr>C<-P8(r^yXo(L4jMte=KgRdvGB zLVqb4XI7tj4tr%dz}|;CSbFXgG77IrdItNteuQO;N?2wdHj*($E-r@U-S1(=;6B*D zu^v{o7IAbgpt1s1J>Clk79EAv716Nf;3X*;W3>4`a8P^!9Gq?qhsZMEQ0)L5W)lvF zds?yNF($lU0!PgC!)sgS;dPy_;q`SMMl!~1Xt)n=ET4rVub07_a=PHCl4_35MW-~v zG5asTv4KW7F7_}SH_{J~iCI}~o%H$xGR;5-ZYcwj2N-h2ezA3}w literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/US/Samoa b/testdata/zoneinfo/US/Samoa new file mode 100644 index 0000000000000000000000000000000000000000..001289ceecff85fe0d0f376a6bc394329445f13f GIT binary patch literal 146 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VvhenkY{@WOiyI}&A|wi*;v8A@c)1O4-lCe Uz`)|;8^RDA9Kyf_Bn%C?07{q{2><{9 literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/UTC b/testdata/zoneinfo/UTC new file mode 100644 index 0000000000000000000000000000000000000000..00841a62213e6cccf7f0b7353e5e8ae214185486 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Universal b/testdata/zoneinfo/Universal new file mode 100644 index 0000000000000000000000000000000000000000..00841a62213e6cccf7f0b7353e5e8ae214185486 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/W-SU b/testdata/zoneinfo/W-SU new file mode 100644 index 0000000000000000000000000000000000000000..5e6b6de6451b4408fb71ef73950712a0827d49a6 GIT binary patch literal 908 zcmajdT}V@57zgm@xShFX^l`D=a$DNkW>agVF@uYTw)B#{Vp^Ff_g^s%Jj%UfhmShojppzDoJYKKzu?b64|_9x5IOUqcb4-l z3Z!6gRAIBLPUc|9Kf&HHpC}sAp+DwO6Wo88wRVcL$?O?>$F8x=C~UbgpMdi#bFAg- z3cR=G!wToM(^ruzrZNT2w!4GSe*FS;Tsi~So$rE`z58L+;V4`m+XkJ%YPg}+3SBl6 zbeAnakL*eE{+=HeSpB6u#d%}jv!d_k(f7Xi25Tl~U~Tpdth@FUZc0CZo6lyTuWJz2 zADJrfe*V)#upu-8x9sbOjrJ7W>OWNU_c7R1(U;_PO&=r3frSp_?N8juJMux~;Aj|z z9y?(3fD5(^6I8lO;m)+J!29h|XOY9l{~$+PuaVX8C*-Jn54qL(9JzJw72K`M7JWMo z_k13JZTBz3*!1lr?;pQ%3R#QUJ0)F-PG6#z4RWb$FdBr5u4VskFP>;J5IF;Ug1GC6 z>Mu%0@qCV-TZW|N;!7#gY9g?>D4-@p|eEkI6G#R8}8#GCSkxFI6)HF>awim{rG!4pH zjAkS6&?xfAD}+?!6(J%k38{3?_x{s=+&gDK=lA=bb9VRctnlb5e@kk~i$$*>gIvO; zx5UuPR?>sJNMFZybM%Pu!!cpRB*(Ks@NX^Z_8FKTWPpA_ z@GV$)SRNKzI>8dvI>yCPSUM?%Wp%|e@;RTEJc2J$ywNYeABnmmQ3hXL3WSvbUa-pJ z5Uk$A4kG(&b_h_v+IbJwdSszr+t~-}<=Pmhc(7r>M@IHF7P&Hxr}dNib(kY#H}gE2 z60DIoRXLs@d2_G?d2>xU&S?qNMBb8h68$%>BF2nVo_vv*oYN}_g?;h< zus_@#ehNMa2YhVdpsNY|ypIcqEIDvk{|_AD8uQ3`UzBth7nI=W*l#%2H37di^uqCH zEpS3w0ly{Y!O2JolwH09r%sFDci$W_Ie*$s41d_g!5OP?_>+GD&T9CLTun_KO?9v)Pfq$`_)Lk#_AX9wfvqiQfq27 z!*z1yjMKSLYcLgRx5q=BstCv}%c01nnSJXeMfe<{@QJ z;Fk?8ygJpW6|Cjoa`f8&$8vYdFSSsfjhnT&IO|Kksfrp)o=7RsPnE|~CLKy0b4@2_ nA?0rGMqbFED?55(M>>jhOF%MHXDhR9W&(2yQ)deSnJNAQHdoT( literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/Zulu b/testdata/zoneinfo/Zulu new file mode 100644 index 0000000000000000000000000000000000000000..00841a62213e6cccf7f0b7353e5e8ae214185486 GIT binary patch literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S literal 0 HcmV?d00001 diff --git a/testdata/zoneinfo/iso3166.tab b/testdata/zoneinfo/iso3166.tab new file mode 100644 index 000000000..4ae35234b --- /dev/null +++ b/testdata/zoneinfo/iso3166.tab @@ -0,0 +1,279 @@ +# ISO 3166 alpha-2 country codes +# +# This file is in the public domain, so clarified as of +# 2009-05-17 by Arthur David Olson. +# +# From Paul Eggert (2025-07-01): +# This file contains a table of two-letter country codes. Columns are +# separated by a single tab. Lines beginning with ‘#’ are comments. +# All text uses UTF-8 encoding. The columns of the table are as follows: +# +# 1. ISO 3166-1 alpha-2 country code, current as of +# ISO/TC 46 N1127 (2024-02-29). See: ISO/TC 46 Documents +# https://www.iso.org/committee/48750.html?view=documents +# 2. The usual English name for the coded region. This sometimes +# departs from ISO-listed names, sometimes so that sorted subsets +# of names are useful (e.g., “Samoa (American)” and “Samoa +# (western)” rather than “American Samoa” and “Samoa”), +# sometimes to avoid confusion among non-experts (e.g., +# “Czech Republic” and “Turkey” rather than “Czechia” and “Türkiye”), +# and sometimes to omit needless detail or churn (e.g., “Netherlands” +# rather than “Netherlands (the)” or “Netherlands (Kingdom of the)”). +# +# The table is sorted by country code. +# +# This table is intended as an aid for users, to help them select time +# zone data appropriate for their practical needs. It is not intended +# to take or endorse any position on legal or territorial claims. +# +#country- +#code name of country, territory, area, or subdivision +AD Andorra +AE United Arab Emirates +AF Afghanistan +AG Antigua & Barbuda +AI Anguilla +AL Albania +AM Armenia +AO Angola +AQ Antarctica +AR Argentina +AS Samoa (American) +AT Austria +AU Australia +AW Aruba +AX Åland Islands +AZ Azerbaijan +BA Bosnia & Herzegovina +BB Barbados +BD Bangladesh +BE Belgium +BF Burkina Faso +BG Bulgaria +BH Bahrain +BI Burundi +BJ Benin +BL St Barthelemy +BM Bermuda +BN Brunei +BO Bolivia +BQ Caribbean NL +BR Brazil +BS Bahamas +BT Bhutan +BV Bouvet Island +BW Botswana +BY Belarus +BZ Belize +CA Canada +CC Cocos (Keeling) Islands +CD Congo (Dem. Rep.) +CF Central African Rep. +CG Congo (Rep.) +CH Switzerland +CI Côte d’Ivoire +CK Cook Islands +CL Chile +CM Cameroon +CN China +CO Colombia +CR Costa Rica +CU Cuba +CV Cape Verde +CW Curaçao +CX Christmas Island +CY Cyprus +CZ Czech Republic +DE Germany +DJ Djibouti +DK Denmark +DM Dominica +DO Dominican Republic +DZ Algeria +EC Ecuador +EE Estonia +EG Egypt +EH Western Sahara +ER Eritrea +ES Spain +ET Ethiopia +FI Finland +FJ Fiji +FK Falkland Islands +FM Micronesia +FO Faroe Islands +FR France +GA Gabon +GB Britain (UK) +GD Grenada +GE Georgia +GF French Guiana +GG Guernsey +GH Ghana +GI Gibraltar +GL Greenland +GM Gambia +GN Guinea +GP Guadeloupe +GQ Equatorial Guinea +GR Greece +GS South Georgia & the South Sandwich Islands +GT Guatemala +GU Guam +GW Guinea-Bissau +GY Guyana +HK Hong Kong +HM Heard Island & McDonald Islands +HN Honduras +HR Croatia +HT Haiti +HU Hungary +ID Indonesia +IE Ireland +IL Israel +IM Isle of Man +IN India +IO British Indian Ocean Territory +IQ Iraq +IR Iran +IS Iceland +IT Italy +JE Jersey +JM Jamaica +JO Jordan +JP Japan +KE Kenya +KG Kyrgyzstan +KH Cambodia +KI Kiribati +KM Comoros +KN St Kitts & Nevis +KP Korea (North) +KR Korea (South) +KW Kuwait +KY Cayman Islands +KZ Kazakhstan +LA Laos +LB Lebanon +LC St Lucia +LI Liechtenstein +LK Sri Lanka +LR Liberia +LS Lesotho +LT Lithuania +LU Luxembourg +LV Latvia +LY Libya +MA Morocco +MC Monaco +MD Moldova +ME Montenegro +MF St Martin (French) +MG Madagascar +MH Marshall Islands +MK North Macedonia +ML Mali +MM Myanmar (Burma) +MN Mongolia +MO Macau +MP Northern Mariana Islands +MQ Martinique +MR Mauritania +MS Montserrat +MT Malta +MU Mauritius +MV Maldives +MW Malawi +MX Mexico +MY Malaysia +MZ Mozambique +NA Namibia +NC New Caledonia +NE Niger +NF Norfolk Island +NG Nigeria +NI Nicaragua +NL Netherlands +NO Norway +NP Nepal +NR Nauru +NU Niue +NZ New Zealand +OM Oman +PA Panama +PE Peru +PF French Polynesia +PG Papua New Guinea +PH Philippines +PK Pakistan +PL Poland +PM St Pierre & Miquelon +PN Pitcairn +PR Puerto Rico +PS Palestine +PT Portugal +PW Palau +PY Paraguay +QA Qatar +RE Réunion +RO Romania +RS Serbia +RU Russia +RW Rwanda +SA Saudi Arabia +SB Solomon Islands +SC Seychelles +SD Sudan +SE Sweden +SG Singapore +SH St Helena +SI Slovenia +SJ Svalbard & Jan Mayen +SK Slovakia +SL Sierra Leone +SM San Marino +SN Senegal +SO Somalia +SR Suriname +SS South Sudan +ST Sao Tome & Principe +SV El Salvador +SX St Maarten (Dutch) +SY Syria +SZ Eswatini (Swaziland) +TC Turks & Caicos Is +TD Chad +TF French S. Terr. +TG Togo +TH Thailand +TJ Tajikistan +TK Tokelau +TL East Timor +TM Turkmenistan +TN Tunisia +TO Tonga +TR Turkey +TT Trinidad & Tobago +TV Tuvalu +TW Taiwan +TZ Tanzania +UA Ukraine +UG Uganda +UM US minor outlying islands +US United States +UY Uruguay +UZ Uzbekistan +VA Vatican City +VC St Vincent +VE Venezuela +VG Virgin Islands (UK) +VI Virgin Islands (US) +VN Vietnam +VU Vanuatu +WF Wallis & Futuna +WS Samoa (western) +YE Yemen +YT Mayotte +ZA South Africa +ZM Zambia +ZW Zimbabwe diff --git a/testdata/zoneinfo/zone1970.tab b/testdata/zoneinfo/zone1970.tab new file mode 100644 index 000000000..cd43e3d2e --- /dev/null +++ b/testdata/zoneinfo/zone1970.tab @@ -0,0 +1,375 @@ +# tzdb timezone descriptions +# +# This file is in the public domain. +# +# From Paul Eggert (2025-05-15): +# This file contains a table where each row stands for a timezone where +# civil timestamps have agreed since 1970. Columns are separated by +# a single tab. Lines beginning with ‘#’ are comments. All text uses +# UTF-8 encoding. The columns of the table are as follows: +# +# 1. The countries that overlap the timezone, as a comma-separated list +# of ISO 3166 2-character country codes. +# 2. Latitude and longitude of the timezone’s principal location +# in ISO 6709 sign-degrees-minutes-seconds format, +# either ±DDMM±DDDMM or ±DDMMSS±DDDMMSS, +# first latitude (+ is north), then longitude (+ is east). +# 3. Timezone name used in value of TZ environment variable. +# Please see the theory.html file for how these names are chosen. +# If multiple timezones overlap a country, each has a row in the +# table, with each column 1 containing the country code. +# 4. Comments; present if and only if countries have multiple timezones, +# and useful only for those countries. For example, the comments +# for the row with countries CH,DE,LI and name Europe/Zurich +# are useful only for DE, since CH and LI have no other timezones. +# +# If a timezone covers multiple countries, the most-populous city is used, +# and that country is listed first in column 1; any other countries +# are listed alphabetically by country code. The table is sorted +# first by country code, then (if possible) by an order within the +# country that (1) makes some geographical sense, and (2) puts the +# most populous timezones first, where that does not contradict (1). +# +# This table is intended as an aid for users, to help them select timezones +# appropriate for their practical needs. It is not intended to take or +# endorse any position on legal or territorial claims. +# +#country- +#codes coordinates TZ comments +AD +4230+00131 Europe/Andorra +AE,OM,RE,SC,TF +2518+05518 Asia/Dubai Crozet +AF +3431+06912 Asia/Kabul +AL +4120+01950 Europe/Tirane +AM +4011+04430 Asia/Yerevan +AQ -6617+11031 Antarctica/Casey Casey +AQ -6835+07758 Antarctica/Davis Davis +AQ -6736+06253 Antarctica/Mawson Mawson +AQ -6448-06406 Antarctica/Palmer Palmer +AQ -6734-06808 Antarctica/Rothera Rothera +AQ -720041+0023206 Antarctica/Troll Troll +AQ -7824+10654 Antarctica/Vostok Vostok +AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF) +AR -3124-06411 America/Argentina/Cordoba most areas: CB, CC, CN, ER, FM, MN, SE, SF +AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN) +AR -2411-06518 America/Argentina/Jujuy Jujuy (JY) +AR -2649-06513 America/Argentina/Tucuman Tucumán (TM) +AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH) +AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR) +AR -3132-06831 America/Argentina/San_Juan San Juan (SJ) +AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ) +AR -3319-06621 America/Argentina/San_Luis San Luis (SL) +AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC) +AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF) +AS,UM -1416-17042 Pacific/Pago_Pago Midway +AT +4813+01620 Europe/Vienna +AU -3133+15905 Australia/Lord_Howe Lord Howe Island +AU -5430+15857 Antarctica/Macquarie Macquarie Island +AU -4253+14719 Australia/Hobart Tasmania +AU -3749+14458 Australia/Melbourne Victoria +AU -3352+15113 Australia/Sydney New South Wales (most areas) +AU -3157+14127 Australia/Broken_Hill New South Wales (Yancowinna) +AU -2728+15302 Australia/Brisbane Queensland (most areas) +AU -2016+14900 Australia/Lindeman Queensland (Whitsunday Islands) +AU -3455+13835 Australia/Adelaide South Australia +AU -1228+13050 Australia/Darwin Northern Territory +AU -3157+11551 Australia/Perth Western Australia (most areas) +AU -3143+12852 Australia/Eucla Western Australia (Eucla) +AZ +4023+04951 Asia/Baku +BB +1306-05937 America/Barbados +BD +2343+09025 Asia/Dhaka +BE,LU,NL +5050+00420 Europe/Brussels +BG +4241+02319 Europe/Sofia +BM +3217-06446 Atlantic/Bermuda +BO -1630-06809 America/La_Paz +BR -0351-03225 America/Noronha Atlantic islands +BR -0127-04829 America/Belem Pará (east), Amapá +BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB) +BR -0803-03454 America/Recife Pernambuco +BR -0712-04812 America/Araguaina Tocantins +BR -0940-03543 America/Maceio Alagoas, Sergipe +BR -1259-03831 America/Bahia Bahia +BR -2332-04637 America/Sao_Paulo Brazil (southeast: GO, DF, MG, ES, RJ, SP, PR, SC, RS) +BR -2027-05437 America/Campo_Grande Mato Grosso do Sul +BR -1535-05605 America/Cuiaba Mato Grosso +BR -0226-05452 America/Santarem Pará (west) +BR -0846-06354 America/Porto_Velho Rondônia +BR +0249-06040 America/Boa_Vista Roraima +BR -0308-06001 America/Manaus Amazonas (east) +BR -0640-06952 America/Eirunepe Amazonas (west) +BR -0958-06748 America/Rio_Branco Acre +BT +2728+08939 Asia/Thimphu +BY +5354+02734 Europe/Minsk +BZ +1730-08812 America/Belize +CA +4734-05243 America/St_Johns Newfoundland, Labrador (SE) +CA +4439-06336 America/Halifax Atlantic - NS (most areas), PE +CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton) +CA +4606-06447 America/Moncton Atlantic - New Brunswick +CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas) +CA,BS +4339-07923 America/Toronto Eastern - ON & QC (most areas) +CA +6344-06828 America/Iqaluit Eastern - NU (most areas) +CA +4953-09709 America/Winnipeg Central - ON (west), Manitoba +CA +744144-0944945 America/Resolute Central - NU (Resolute) +CA +624900-0920459 America/Rankin_Inlet Central - NU (central) +CA +5024-10439 America/Regina CST - SK (most areas) +CA +5017-10750 America/Swift_Current CST - SK (midwest) +CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W) +CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west) +CA +682059-1334300 America/Inuvik Mountain - NT (west) +CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John) +CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson) +CA +6043-13503 America/Whitehorse MST - Yukon (east) +CA +6404-13925 America/Dawson MST - Yukon (west) +CA +4916-12307 America/Vancouver Pacific - BC (most areas) +CH,DE,LI +4723+00832 Europe/Zurich Büsingen +CI,BF,GH,GM,GN,IS,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan +CK -2114-15946 Pacific/Rarotonga +CL -3327-07040 America/Santiago most of Chile +CL -4534-07204 America/Coyhaique Aysén Region +CL -5309-07055 America/Punta_Arenas Magallanes Region +CL -2709-10926 Pacific/Easter Easter Island +CN +3114+12128 Asia/Shanghai Beijing Time +CN +4348+08735 Asia/Urumqi Xinjiang Time +CO +0436-07405 America/Bogota +CR +0956-08405 America/Costa_Rica +CU +2308-08222 America/Havana +CV +1455-02331 Atlantic/Cape_Verde +CY +3510+03322 Asia/Nicosia most of Cyprus +CY +3507+03357 Asia/Famagusta Northern Cyprus +CZ,SK +5005+01426 Europe/Prague +DE,DK,NO,SE,SJ +5230+01322 Europe/Berlin most of Germany +DO +1828-06954 America/Santo_Domingo +DZ +3647+00303 Africa/Algiers +EC -0210-07950 America/Guayaquil Ecuador (mainland) +EC -0054-08936 Pacific/Galapagos Galápagos Islands +EE +5925+02445 Europe/Tallinn +EG +3003+03115 Africa/Cairo +EH +2709-01312 Africa/El_Aaiun +ES +4024-00341 Europe/Madrid Spain (mainland) +ES +3553-00519 Africa/Ceuta Ceuta, Melilla +ES +2806-01524 Atlantic/Canary Canary Islands +FI,AX +6010+02458 Europe/Helsinki +FJ -1808+17825 Pacific/Fiji +FK -5142-05751 Atlantic/Stanley +FM +0519+16259 Pacific/Kosrae Kosrae +FO +6201-00646 Atlantic/Faroe +FR,MC +4852+00220 Europe/Paris +GB,GG,IM,JE +513030-0000731 Europe/London +GE +4143+04449 Asia/Tbilisi +GF +0456-05220 America/Cayenne +GI +3608-00521 Europe/Gibraltar +GL +6411-05144 America/Nuuk most of Greenland +GL +7646-01840 America/Danmarkshavn National Park (east coast) +GL +7029-02158 America/Scoresbysund Scoresbysund/Ittoqqortoormiit +GL +7634-06847 America/Thule Thule/Pituffik +GR +3758+02343 Europe/Athens +GS -5416-03632 Atlantic/South_Georgia +GT +1438-09031 America/Guatemala +GU,MP +1328+14445 Pacific/Guam +GW +1151-01535 Africa/Bissau +GY +0648-05810 America/Guyana +HK +2217+11409 Asia/Hong_Kong +HN +1406-08713 America/Tegucigalpa +HT +1832-07220 America/Port-au-Prince +HU +4730+01905 Europe/Budapest +ID -0610+10648 Asia/Jakarta Java, Sumatra +ID -0002+10920 Asia/Pontianak Borneo (west, central) +ID -0507+11924 Asia/Makassar Borneo (east, south), Sulawesi/Celebes, Bali, Nusa Tengarra, Timor (west) +ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya), Malukus/Moluccas +IE +5320-00615 Europe/Dublin +IL +314650+0351326 Asia/Jerusalem +IN +2232+08822 Asia/Kolkata +IO -0720+07225 Indian/Chagos +IQ +3321+04425 Asia/Baghdad +IR +3540+05126 Asia/Tehran +IT,SM,VA +4154+01229 Europe/Rome +JM +175805-0764736 America/Jamaica +JO +3157+03556 Asia/Amman +JP,AU +353916+1394441 Asia/Tokyo Eyre Bird Observatory +KE,DJ,ER,ET,KM,MG,SO,TZ,UG,YT -0117+03649 Africa/Nairobi +KG +4254+07436 Asia/Bishkek +KI,MH,TV,UM,WF +0125+17300 Pacific/Tarawa Gilberts, Marshalls, Wake +KI -0247-17143 Pacific/Kanton Phoenix Islands +KI +0152-15720 Pacific/Kiritimati Line Islands +KP +3901+12545 Asia/Pyongyang +KR +3733+12658 Asia/Seoul +KZ +4315+07657 Asia/Almaty most of Kazakhstan +KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda +KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay +KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe +KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau +KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur’yev +KZ +5113+05121 Asia/Oral West Kazakhstan +LB +3353+03530 Asia/Beirut +LK +0656+07951 Asia/Colombo +LR +0618-01047 Africa/Monrovia +LT +5441+02519 Europe/Vilnius +LV +5657+02406 Europe/Riga +LY +3254+01311 Africa/Tripoli +MA +3339-00735 Africa/Casablanca +MD +4700+02850 Europe/Chisinau +MH +0905+16720 Pacific/Kwajalein Kwajalein +MM,CC +1647+09610 Asia/Yangon +MN +4755+10653 Asia/Ulaanbaatar most of Mongolia +MN +4801+09139 Asia/Hovd Bayan-Ölgii, Hovd, Uvs +MO +221150+1133230 Asia/Macau +MQ +1436-06105 America/Martinique +MT +3554+01431 Europe/Malta +MU -2010+05730 Indian/Mauritius +MV,TF +0410+07330 Indian/Maldives Kerguelen, St Paul I, Amsterdam I +MX +1924-09909 America/Mexico_City Central Mexico +MX +2105-08646 America/Cancun Quintana Roo +MX +2058-08937 America/Merida Campeche, Yucatán +MX +2540-10019 America/Monterrey Durango; Coahuila, Nuevo León, Tamaulipas (most areas) +MX +2550-09730 America/Matamoros Coahuila, Nuevo León, Tamaulipas (US border) +MX +2838-10605 America/Chihuahua Chihuahua (most areas) +MX +3144-10629 America/Ciudad_Juarez Chihuahua (US border - west) +MX +2934-10425 America/Ojinaga Chihuahua (US border - east) +MX +2313-10625 America/Mazatlan Baja California Sur, Nayarit (most areas), Sinaloa +MX +2048-10515 America/Bahia_Banderas Bahía de Banderas +MX +2904-11058 America/Hermosillo Sonora +MX +3232-11701 America/Tijuana Baja California +MY,BN +0133+11020 Asia/Kuching Sabah, Sarawak +MZ,BI,BW,CD,MW,RW,ZM,ZW -2558+03235 Africa/Maputo Central Africa Time +NA -2234+01706 Africa/Windhoek +NC -2216+16627 Pacific/Noumea +NF -2903+16758 Pacific/Norfolk +NG,AO,BJ,CD,CF,CG,CM,GA,GQ,NE +0627+00324 Africa/Lagos West Africa Time +NI +1209-08617 America/Managua +NP +2743+08519 Asia/Kathmandu +NR -0031+16655 Pacific/Nauru +NU -1901-16955 Pacific/Niue +NZ,AQ -3652+17446 Pacific/Auckland New Zealand time +NZ -4357-17633 Pacific/Chatham Chatham Islands +PA,CA,KY +0858-07932 America/Panama EST - ON (Atikokan), NU (Coral H) +PE -1203-07703 America/Lima +PF -1732-14934 Pacific/Tahiti Society Islands +PF -0900-13930 Pacific/Marquesas Marquesas Islands +PF -2308-13457 Pacific/Gambier Gambier Islands +PG,AQ,FM -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas), Chuuk, Yap, Dumont d’Urville +PG -0613+15534 Pacific/Bougainville Bougainville +PH +143512+1205804 Asia/Manila +PK +2452+06703 Asia/Karachi +PL +5215+02100 Europe/Warsaw +PM +4703-05620 America/Miquelon +PN -2504-13005 Pacific/Pitcairn +PR,AG,CA,AI,AW,BL,BQ,CW,DM,GD,GP,KN,LC,MF,MS,SX,TT,VC,VG,VI +182806-0660622 America/Puerto_Rico AST - QC (Lower North Shore) +PS +3130+03428 Asia/Gaza Gaza Strip +PS +313200+0350542 Asia/Hebron West Bank +PT +3843-00908 Europe/Lisbon Portugal (mainland) +PT +3238-01654 Atlantic/Madeira Madeira Islands +PT +3744-02540 Atlantic/Azores Azores +PW +0720+13429 Pacific/Palau +PY -2516-05740 America/Asuncion +QA,BH +2517+05132 Asia/Qatar +RO +4426+02606 Europe/Bucharest +RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade +RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad +RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area +# Mention RU and UA alphabetically. See “territorial claims” above. +RU,UA +4457+03406 Europe/Simferopol Crimea +RU +5836+04939 Europe/Kirov MSK+00 - Kirov +RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd +RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan +RU +5134+04602 Europe/Saratov MSK+01 - Saratov +RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk +RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia +RU +5651+06036 Asia/Yekaterinburg MSK+02 - Urals +RU +5500+07324 Asia/Omsk MSK+03 - Omsk +RU +5502+08255 Asia/Novosibirsk MSK+04 - Novosibirsk +RU +5322+08345 Asia/Barnaul MSK+04 - Altai +RU +5630+08458 Asia/Tomsk MSK+04 - Tomsk +RU +5345+08707 Asia/Novokuznetsk MSK+04 - Kemerovo +RU +5601+09250 Asia/Krasnoyarsk MSK+04 - Krasnoyarsk area +RU +5216+10420 Asia/Irkutsk MSK+05 - Irkutsk, Buryatia +RU +5203+11328 Asia/Chita MSK+06 - Zabaykalsky +RU +6200+12940 Asia/Yakutsk MSK+06 - Lena River +RU +623923+1353314 Asia/Khandyga MSK+06 - Tomponsky, Ust-Maysky +RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River +RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky +RU +5934+15048 Asia/Magadan MSK+08 - Magadan +RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island +RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E), N Kuril Is +RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka +RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea +SA,AQ,KW,YE +2438+04643 Asia/Riyadh Syowa +SB,FM -0932+16012 Pacific/Guadalcanal Pohnpei +SD +1536+03232 Africa/Khartoum +SG,AQ,MY +0117+10351 Asia/Singapore peninsular Malaysia, Concordia +SR +0550-05510 America/Paramaribo +SS +0451+03137 Africa/Juba +ST +0020+00644 Africa/Sao_Tome +SV +1342-08912 America/El_Salvador +SY +3330+03618 Asia/Damascus +TC +2128-07108 America/Grand_Turk +TD +1207+01503 Africa/Ndjamena +TH,CX,KH,LA,VN +1345+10031 Asia/Bangkok north Vietnam +TJ +3835+06848 Asia/Dushanbe +TK -0922-17114 Pacific/Fakaofo +TL -0833+12535 Asia/Dili +TM +3757+05823 Asia/Ashgabat +TN +3648+01011 Africa/Tunis +TO -210800-1751200 Pacific/Tongatapu +TR +4101+02858 Europe/Istanbul +TW +2503+12130 Asia/Taipei +UA +5026+03031 Europe/Kyiv most of Ukraine +US +404251-0740023 America/New_York Eastern (most areas) +US +421953-0830245 America/Detroit Eastern - MI (most areas) +US +381515-0854534 America/Kentucky/Louisville Eastern - KY (Louisville area) +US +364947-0845057 America/Kentucky/Monticello Eastern - KY (Wayne) +US +394606-0860929 America/Indiana/Indianapolis Eastern - IN (most areas) +US +384038-0873143 America/Indiana/Vincennes Eastern - IN (Da, Du, K, Mn) +US +410305-0863611 America/Indiana/Winamac Eastern - IN (Pulaski) +US +382232-0862041 America/Indiana/Marengo Eastern - IN (Crawford) +US +382931-0871643 America/Indiana/Petersburg Eastern - IN (Pike) +US +384452-0850402 America/Indiana/Vevay Eastern - IN (Switzerland) +US +415100-0873900 America/Chicago Central (most areas) +US +375711-0864541 America/Indiana/Tell_City Central - IN (Perry) +US +411745-0863730 America/Indiana/Knox Central - IN (Starke) +US +450628-0873651 America/Menominee Central - MI (Wisconsin border) +US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver) +US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural) +US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer) +US +394421-1045903 America/Denver Mountain (most areas) +US +433649-1161209 America/Boise Mountain - ID (south), OR (east) +US,CA +332654-1120424 America/Phoenix MST - AZ (most areas), Creston BC +US +340308-1181434 America/Los_Angeles Pacific +US +611305-1495401 America/Anchorage Alaska (most areas) +US +581807-1342511 America/Juneau Alaska - Juneau area +US +571035-1351807 America/Sitka Alaska - Sitka area +US +550737-1313435 America/Metlakatla Alaska - Annette Island +US +593249-1394338 America/Yakutat Alaska - Yakutat +US +643004-1652423 America/Nome Alaska (west) +US +515248-1763929 America/Adak Alaska - western Aleutians +US +211825-1575130 Pacific/Honolulu Hawaii +UY -345433-0561245 America/Montevideo +UZ +3940+06648 Asia/Samarkand Uzbekistan (west) +UZ +4120+06918 Asia/Tashkent Uzbekistan (east) +VE +1030-06656 America/Caracas +VN +1045+10640 Asia/Ho_Chi_Minh south Vietnam +VU -1740+16825 Pacific/Efate +WS -1350-17144 Pacific/Apia +ZA,LS,SZ -2615+02800 Africa/Johannesburg +# +# The next section contains experimental tab-separated comments for +# use by user agents like tzselect that identify continents and oceans. +# +# For example, the comment ‘#@AQAntarctica/’ means the country code +# AQ is in the continent Antarctica regardless of the Zone name, +# so Pacific/Auckland should be listed under Antarctica as well as +# under the Pacific because its line’s country codes include AQ. +# +# If more than one country code is affected each is listed separated +# by commas, e.g., ‘#@IS,SHAtlantic/’. If a country code is in +# more than one continent or ocean, each is listed separated by +# commas, e.g., the second column of ‘#@CY,TRAsia/,Europe/’. +# +# These experimental comments are present only for country codes where +# the continent or ocean is not already obvious from the Zone name. +# For example, there is no such comment for RU since it already +# corresponds to Zone names starting with both ‘Europe/’ and ‘Asia/’. +# +#@AQ Antarctica/ +#@IS,SH Atlantic/ +#@CY,TR Asia/,Europe/ +#@SJ Arctic/ +#@CC,CX,KM,MG,YT Indian/ diff --git a/testdata/zoneinfo/zonenow.tab b/testdata/zoneinfo/zonenow.tab new file mode 100644 index 000000000..aa3a64f3d --- /dev/null +++ b/testdata/zoneinfo/zonenow.tab @@ -0,0 +1,293 @@ +# tzdb timezone descriptions, for users who do not care about old timestamps +# +# This file is in the public domain. +# +# From Paul Eggert (2023-12-18): +# This file contains a table where each row stands for a timezone +# where civil timestamps are predicted to agree from now on. +# This file is like zone1970.tab (see zone1970.tab’s comments), +# but with the following changes: +# +# 1. Each timezone corresponds to a set of clocks that are planned +# to agree from now on. This is a larger set of clocks than in +# zone1970.tab, where each timezone’s clocks must agree from 1970 on. +# 2. The first column is irrelevant and ignored. +# 3. The table is sorted in a different way: +# first by standard time UTC offset; +# then, if DST is used, by daylight saving UTC offset; +# then by time zone abbreviation. +# 4. Every timezone has a nonempty comments column, with wording +# distinguishing the timezone only from other timezones with the +# same UTC offset at some point during the year. +# +# The format of this table is experimental, and may change in future versions. +# +# This table is intended as an aid for users, to help them select timezones +# appropriate for their practical needs. It is not intended to take or +# endorse any position on legal or territorial claims. +# +#XX coordinates TZ comments +# +# -11 - SST +XX -1416-17042 Pacific/Pago_Pago Midway; Samoa (SST) +# +# -11 +XX -1901-16955 Pacific/Niue Niue +# +# -10 - HST +XX +211825-1575130 Pacific/Honolulu Hawaii (HST) +# +# -10 +XX -1732-14934 Pacific/Tahiti Tahiti; Cook Islands +# +# -10/-09 - HST / HDT (North America DST) +XX +515248-1763929 America/Adak western Aleutians in Alaska (HST/HDT) +# +# -09:30 +XX -0900-13930 Pacific/Marquesas Marquesas +# +# -09 +XX -2308-13457 Pacific/Gambier Gambier +# +# -09/-08 - AKST/AKDT (North America DST) +XX +611305-1495401 America/Anchorage most of Alaska (AKST/AKDT) +# +# -08 +XX -2504-13005 Pacific/Pitcairn Pitcairn +# +# -08/-07 - PST/PDT (North America DST) +XX +340308-1181434 America/Los_Angeles Pacific (PST/PDT) - US & Canada; Mexico near US border +# +# -07 - MST +XX +332654-1120424 America/Phoenix Mountain Standard (MST) - Arizona; western Mexico; Yukon +# +# -07/-06 - MST/MDT (North America DST) +XX +394421-1045903 America/Denver Mountain (MST/MDT) - US & Canada; Mexico near US border +# +# -06 +XX -0054-08936 Pacific/Galapagos Galápagos +# +# -06 - CST +XX +1924-09909 America/Mexico_City Central Standard (CST) - Saskatchewan; central Mexico; Central America +# +# -06/-05 (Chile DST) +XX -2709-10926 Pacific/Easter Easter Island +# +# -06/-05 - CST/CDT (North America DST) +XX +415100-0873900 America/Chicago Central (CST/CDT) - US & Canada; Mexico near US border +# +# -05 +XX -1203-07703 America/Lima eastern South America +# +# -05 - EST +XX +175805-0764736 America/Jamaica Eastern Standard (EST) - Caymans; Jamaica; eastern Mexico; Panama +# +# -05/-04 - CST/CDT (Cuba DST) +XX +2308-08222 America/Havana Cuba +# +# -05/-04 - EST/EDT (North America DST) +XX +404251-0740023 America/New_York Eastern (EST/EDT) - US & Canada +# +# -04 +XX +1030-06656 America/Caracas western South America +# +# -04 - AST +XX +1828-06954 America/Santo_Domingo Atlantic Standard (AST) - eastern Caribbean +# +# -04/-03 (Chile DST) +XX -3327-07040 America/Santiago most of Chile +# +# -04/-03 - AST/ADT (North America DST) +XX +4439-06336 America/Halifax Atlantic (AST/ADT) - Canada; Bermuda +# +# -03:30/-02:30 - NST/NDT (North America DST) +XX +4734-05243 America/St_Johns Newfoundland (NST/NDT) +# +# -03 +XX -2332-04637 America/Sao_Paulo eastern and southern South America +# +# -03/-02 (North America DST) +XX +4703-05620 America/Miquelon St Pierre & Miquelon +# +# -02 +XX -0351-03225 America/Noronha Fernando de Noronha; South Georgia +# +# -02/-01 (EU DST) +XX +6411-05144 America/Nuuk most of Greenland +# +# -01 +XX +1455-02331 Atlantic/Cape_Verde Cape Verde +# +# -01/+00 (EU DST) +XX +3744-02540 Atlantic/Azores Azores +# +# +00 - GMT +XX +0519-00402 Africa/Abidjan far western Africa; Iceland (GMT) +# +# +00/+01 - GMT/BST (EU DST) +XX +513030-0000731 Europe/London United Kingdom (GMT/BST) +# +# +00/+01 - WET/WEST (EU DST) +XX +3843-00908 Europe/Lisbon western Europe (WET/WEST) +# +# +00/+02 - Troll DST +XX -720041+0023206 Antarctica/Troll Troll Station in Antarctica +# +# +01 - CET +XX +3647+00303 Africa/Algiers Algeria, Tunisia (CET) +# +# +01 - WAT +XX +0627+00324 Africa/Lagos western Africa (WAT) +# +# +01/+00 - IST/GMT (EU DST in reverse) +XX +5320-00615 Europe/Dublin Ireland (IST/GMT) +# +# +01/+00 - (Morocco DST) +XX +3339-00735 Africa/Casablanca Morocco +# +# +01/+02 - CET/CEST (EU DST) +XX +4852+00220 Europe/Paris central Europe (CET/CEST) +# +# +02 - CAT +XX -2558+03235 Africa/Maputo central Africa (CAT) +# +# +02 - EET +XX +3254+01311 Africa/Tripoli Libya; Kaliningrad (EET) +# +# +02 - SAST +XX -2615+02800 Africa/Johannesburg southern Africa (SAST) +# +# +02/+03 - EET/EEST (EU DST) +XX +3758+02343 Europe/Athens eastern Europe (EET/EEST) +# +# +02/+03 - EET/EEST (Egypt DST) +XX +3003+03115 Africa/Cairo Egypt +# +# +02/+03 - EET/EEST (Lebanon DST) +XX +3353+03530 Asia/Beirut Lebanon +# +# +02/+03 - EET/EEST (Palestine DST) +XX +3130+03428 Asia/Gaza Palestine +# +# +02/+03 - IST/IDT (Israel DST) +XX +314650+0351326 Asia/Jerusalem Israel +# +# +03 +XX +4101+02858 Europe/Istanbul Near East; Belarus +# +# +03 - EAT +XX -0117+03649 Africa/Nairobi eastern Africa (EAT) +# +# +03 - MSK +XX +554521+0373704 Europe/Moscow Moscow (MSK) +# +# +03:30 +XX +3540+05126 Asia/Tehran Iran +# +# +04 +XX +2518+05518 Asia/Dubai Russia; Caucasus; Persian Gulf; Seychelles; Réunion +# +# +04:30 +XX +3431+06912 Asia/Kabul Afghanistan +# +# +05 +XX +4120+06918 Asia/Tashkent Russia; Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives +# +# +05 - PKT +XX +2452+06703 Asia/Karachi Pakistan (PKT) +# +# +05:30 +XX +0656+07951 Asia/Colombo Sri Lanka +# +# +05:30 - IST +XX +2232+08822 Asia/Kolkata India (IST) +# +# +05:45 +XX +2743+08519 Asia/Kathmandu Nepal +# +# +06 +XX +2343+09025 Asia/Dhaka Russia; Kyrgyzstan; Bhutan; Bangladesh; Chagos +# +# +06:30 +XX +1647+09610 Asia/Yangon Myanmar; Cocos +# +# +07 +XX +1345+10031 Asia/Bangkok Russia; Indochina; Christmas Island +# +# +07 - WIB +XX -0610+10648 Asia/Jakarta Indonesia (WIB) +# +# +08 +XX +0117+10351 Asia/Singapore Russia; Brunei; Malaysia; Singapore; Concordia +# +# +08 - AWST +XX -3157+11551 Australia/Perth Western Australia (AWST) +# +# +08 - CST +XX +3114+12128 Asia/Shanghai China (CST) +# +# +08 - HKT +XX +2217+11409 Asia/Hong_Kong Hong Kong (HKT) +# +# +08 - PHT +XX +143512+1205804 Asia/Manila Philippines (PHT) +# +# +08 - WITA +XX -0507+11924 Asia/Makassar Indonesia (WITA) +# +# +08:45 +XX -3143+12852 Australia/Eucla Eucla +# +# +09 +XX +5203+11328 Asia/Chita Russia; Palau; East Timor +# +# +09 - JST +XX +353916+1394441 Asia/Tokyo Japan (JST); Eyre Bird Observatory +# +# +09 - KST +XX +3733+12658 Asia/Seoul Korea (KST) +# +# +09 - WIT +XX -0232+14042 Asia/Jayapura Indonesia (WIT) +# +# +09:30 - ACST +XX -1228+13050 Australia/Darwin Northern Territory (ACST) +# +# +09:30/+10:30 - ACST/ACDT (Australia DST) +XX -3455+13835 Australia/Adelaide South Australia (ACST/ACDT) +# +# +10 +XX +4310+13156 Asia/Vladivostok Russia; Yap; Chuuk; Papua New Guinea; Dumont d’Urville +# +# +10 - AEST +XX -2728+15302 Australia/Brisbane Queensland (AEST) +# +# +10 - ChST +XX +1328+14445 Pacific/Guam Mariana Islands (ChST) +# +# +10/+11 - AEST/AEDT (Australia DST) +XX -3352+15113 Australia/Sydney southeast Australia (AEST/AEDT) +# +# +10:30/+11 +XX -3133+15905 Australia/Lord_Howe Lord Howe Island +# +# +11 +XX -0613+15534 Pacific/Bougainville Russia; Kosrae; Bougainville; Solomons +# +# +11/+12 (Australia DST) +XX -2903+16758 Pacific/Norfolk Norfolk Island +# +# +12 +XX +5301+15839 Asia/Kamchatka Russia; Tuvalu; Fiji; etc. +# +# +12/+13 (New Zealand DST) +XX -3652+17446 Pacific/Auckland New Zealand (NZST/NZDT) +# +# +12:45/+13:45 (Chatham DST) +XX -4357-17633 Pacific/Chatham Chatham Islands +# +# +13 +XX -210800-1751200 Pacific/Tongatapu Kanton; Tokelau; Samoa (western); Tonga +# +# +14 +XX +0152-15720 Pacific/Kiritimati Kiritimati From 079ab7254cf2446ab0c2670a70c72f963818f7c7 Mon Sep 17 00:00:00 2001 From: Bruno Tremblay Date: Wed, 25 Mar 2026 13:34:40 -0400 Subject: [PATCH 2/6] push handoff --- HANDOFF_CCTZ_UPDATE.md | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 HANDOFF_CCTZ_UPDATE.md diff --git a/HANDOFF_CCTZ_UPDATE.md b/HANDOFF_CCTZ_UPDATE.md new file mode 100644 index 000000000..42bb97538 --- /dev/null +++ b/HANDOFF_CCTZ_UPDATE.md @@ -0,0 +1,72 @@ +# Handoff: cctz vendor update in odbc + +## Goal completed so far +- Updated vendored cctz under src/cctz to latest upstream google/cctz. +- Traced original cctz import in this repo and identified local odbc-specific deltas. +- Verified package can be built and installed from source in this environment (with a vignette caveat noted below). + +## Historical trace +- Original cctz subtree import commit in this repo: + - 293ed5c2 Add src/cctz from upstream split commit 182b96ca6e09527e18fcd0a6ca3e156ea7997099 +- Upstream target used for update: + - 00fc77b843504f231f89c13eff86327c444094e8 (google/cctz master) + - Subject: Update zoneinfo files to 2026a (#339) + +## Commits created in this branch +- ade9b422 Update vendored cctz to upstream 00fc77b8 + - Includes the subtree update and conflict resolutions. +- 8fd5ec29 Squashed src/cctz changes from 182b96ca..00fc77b8 + - Subtree internal squash commit from git subtree pull. + +## Working tree status (not yet committed) +- Modified: src/cctz/Makefile + - Added Windows-specific object time_zone_name_win.o for static libcctz build. +- Untracked artifact: odbc_1.6.4.9000.tar.gz + +## Why src/cctz/Makefile changed after subtree update +- The upstream update introduced src/time_zone_name_win.cc. +- Windows link failed without it: + - undefined reference to cctz::GetWindowsLocalTimeZone[abi:cxx11]() +- Fix applied locally in src/cctz/Makefile: + - ifeq ($(OS),Windows_NT) + - CCTZ_OBJS += time_zone_name_win.o + - endif + +## Local odbc-specific cctz deltas retained +These differ from upstream on purpose: +- src/cctz/src/time_zone_fixed.cc + - Keeps Etc/GMT fixed-offset naming behavior used by odbc timestamp offset logic. +- src/cctz/src/time_zone_format.cc + - Retains historical odbc patches from earlier Windows/Mingw compatibility work. + +## Build/test evidence +- R CMD build . + - Failed only because Pandoc is missing for vignettes in this environment. +- R CMD build --no-build-vignettes . + - Succeeded and produced odbc_1.6.4.9000.tar.gz +- Source install validation via Rscript::install.packages(..., type='source', lib=temp) + - Succeeded after Makefile Windows object fix. + +## Exact commands used for successful package build/install checks +```bash +R CMD build --no-build-vignettes . +Rscript -e "install.packages('odbc_1.6.4.9000.tar.gz', repos=NULL, type='source', lib=Sys.getenv('TMPDIR'))" +``` + +## Suggested next steps on Linux machine +1. Pull this branch. +2. Commit remaining Makefile fix: + - git add src/cctz/Makefile + - git commit -m "cctz: include time_zone_name_win.o in Makefile" +3. Remove or ignore build artifact before push: + - rm odbc_1.6.4.9000.tar.gz +4. Run full build/check with Pandoc available: + - R CMD build . + - R CMD check odbc_1.6.4.9000.tar.gz +5. Push to fork: + - git push meztez HEAD + +## New chat bootstrap prompt +Copy/paste this into a new Copilot chat: + +"Continue from HANDOFF_CCTZ_UPDATE.md in repo root. We updated vendored src/cctz to google/cctz 00fc77b8 and committed ade9b422. There is one uncommitted fix in src/cctz/Makefile adding time_zone_name_win.o on Windows. Please verify current git status, commit that fix if present, run R CMD build and R CMD check on Linux, and prepare a concise PR summary of cctz update plus retained odbc-specific patches." From a72180e9b7a961bf068ca68bb33c60686feb8463 Mon Sep 17 00:00:00 2001 From: Bruno Tremblay Date: Wed, 25 Mar 2026 14:16:07 -0400 Subject: [PATCH 3/6] remove testdata and .github directory --- HANDOFF_CCTZ_UPDATE.md | 72 ---- src/cctz/.github/workflows/ci.yaml | 167 -------- src/cctz/.github/workflows/cifuzz.yml | 24 -- src/cctz/testdata/README.zoneinfo | 38 -- src/cctz/testdata/version | 1 - src/cctz/testdata/zoneinfo/Africa/Abidjan | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Accra | Bin 700 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Addis_Ababa | Bin 151 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Algiers | Bin 470 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Asmara | Bin 170 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Asmera | Bin 170 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Bamako | Bin 158 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Bangui | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Banjul | Bin 168 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Bissau | Bin 149 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Blantyre | Bin 165 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Brazzaville | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Bujumbura | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Cairo | Bin 1309 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Casablanca | Bin 1919 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Ceuta | Bin 562 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Conakry | Bin 158 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Dakar | Bin 149 -> 0 bytes .../testdata/zoneinfo/Africa/Dar_es_Salaam | Bin 161 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Djibouti | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Douala | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/El_Aaiun | Bin 1830 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Freetown | Bin 324 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Gaborone | Bin 180 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Harare | Bin 131 -> 0 bytes .../testdata/zoneinfo/Africa/Johannesburg | Bin 190 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Juba | Bin 458 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Kampala | Bin 182 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Khartoum | Bin 458 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Kigali | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Kinshasa | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Lagos | Bin 180 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Libreville | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Lome | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Luanda | Bin 146 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Lubumbashi | Bin 150 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Lusaka | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Malabo | Bin 150 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Maputo | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Maseru | Bin 157 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Mbabane | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Mogadishu | Bin 161 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Monrovia | Bin 164 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Nairobi | Bin 191 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Ndjamena | Bin 160 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Niamey | Bin 169 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Nouakchott | Bin 158 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Ouagadougou | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Porto-Novo | Bin 150 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Sao_Tome | Bin 173 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Timbuktu | Bin 158 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Tripoli | Bin 431 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Tunis | Bin 449 -> 0 bytes src/cctz/testdata/zoneinfo/Africa/Windhoek | Bin 638 -> 0 bytes src/cctz/testdata/zoneinfo/America/Adak | Bin 969 -> 0 bytes src/cctz/testdata/zoneinfo/America/Anchorage | Bin 977 -> 0 bytes src/cctz/testdata/zoneinfo/America/Anguilla | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/Antigua | Bin 149 -> 0 bytes src/cctz/testdata/zoneinfo/America/Araguaina | Bin 592 -> 0 bytes .../zoneinfo/America/Argentina/Buenos_Aires | Bin 708 -> 0 bytes .../zoneinfo/America/Argentina/Catamarca | Bin 708 -> 0 bytes .../zoneinfo/America/Argentina/ComodRivadavia | Bin 708 -> 0 bytes .../zoneinfo/America/Argentina/Cordoba | Bin 708 -> 0 bytes .../testdata/zoneinfo/America/Argentina/Jujuy | Bin 690 -> 0 bytes .../zoneinfo/America/Argentina/La_Rioja | Bin 717 -> 0 bytes .../zoneinfo/America/Argentina/Mendoza | Bin 708 -> 0 bytes .../zoneinfo/America/Argentina/Rio_Gallegos | Bin 708 -> 0 bytes .../testdata/zoneinfo/America/Argentina/Salta | Bin 690 -> 0 bytes .../zoneinfo/America/Argentina/San_Juan | Bin 717 -> 0 bytes .../zoneinfo/America/Argentina/San_Luis | Bin 717 -> 0 bytes .../zoneinfo/America/Argentina/Tucuman | Bin 726 -> 0 bytes .../zoneinfo/America/Argentina/Ushuaia | Bin 708 -> 0 bytes src/cctz/testdata/zoneinfo/America/Aruba | Bin 151 -> 0 bytes src/cctz/testdata/zoneinfo/America/Asuncion | Bin 1085 -> 0 bytes src/cctz/testdata/zoneinfo/America/Atikokan | Bin 224 -> 0 bytes src/cctz/testdata/zoneinfo/America/Atka | Bin 969 -> 0 bytes src/cctz/testdata/zoneinfo/America/Bahia | Bin 682 -> 0 bytes .../testdata/zoneinfo/America/Bahia_Banderas | Bin 700 -> 0 bytes src/cctz/testdata/zoneinfo/America/Barbados | Bin 278 -> 0 bytes src/cctz/testdata/zoneinfo/America/Belem | Bin 394 -> 0 bytes src/cctz/testdata/zoneinfo/America/Belize | Bin 1045 -> 0 bytes .../testdata/zoneinfo/America/Blanc-Sablon | Bin 205 -> 0 bytes src/cctz/testdata/zoneinfo/America/Boa_Vista | Bin 430 -> 0 bytes src/cctz/testdata/zoneinfo/America/Bogota | Bin 179 -> 0 bytes src/cctz/testdata/zoneinfo/America/Boise | Bin 999 -> 0 bytes .../testdata/zoneinfo/America/Buenos_Aires | Bin 708 -> 0 bytes .../testdata/zoneinfo/America/Cambridge_Bay | Bin 883 -> 0 bytes .../testdata/zoneinfo/America/Campo_Grande | Bin 952 -> 0 bytes src/cctz/testdata/zoneinfo/America/Cancun | Bin 538 -> 0 bytes src/cctz/testdata/zoneinfo/America/Caracas | Bin 190 -> 0 bytes src/cctz/testdata/zoneinfo/America/Catamarca | Bin 708 -> 0 bytes src/cctz/testdata/zoneinfo/America/Cayenne | Bin 151 -> 0 bytes src/cctz/testdata/zoneinfo/America/Cayman | Bin 149 -> 0 bytes src/cctz/testdata/zoneinfo/America/Chicago | Bin 1754 -> 0 bytes src/cctz/testdata/zoneinfo/America/Chihuahua | Bin 691 -> 0 bytes .../testdata/zoneinfo/America/Ciudad_Juarez | Bin 718 -> 0 bytes .../testdata/zoneinfo/America/Coral_Harbour | Bin 224 -> 0 bytes src/cctz/testdata/zoneinfo/America/Cordoba | Bin 708 -> 0 bytes src/cctz/testdata/zoneinfo/America/Costa_Rica | Bin 232 -> 0 bytes src/cctz/testdata/zoneinfo/America/Coyhaique | Bin 1362 -> 0 bytes src/cctz/testdata/zoneinfo/America/Creston | Bin 158 -> 0 bytes src/cctz/testdata/zoneinfo/America/Cuiaba | Bin 934 -> 0 bytes src/cctz/testdata/zoneinfo/America/Curacao | Bin 151 -> 0 bytes .../testdata/zoneinfo/America/Danmarkshavn | Bin 447 -> 0 bytes src/cctz/testdata/zoneinfo/America/Dawson | Bin 1029 -> 0 bytes .../testdata/zoneinfo/America/Dawson_Creek | Bin 683 -> 0 bytes src/cctz/testdata/zoneinfo/America/Denver | Bin 1042 -> 0 bytes src/cctz/testdata/zoneinfo/America/Detroit | Bin 899 -> 0 bytes src/cctz/testdata/zoneinfo/America/Dominica | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/Edmonton | Bin 970 -> 0 bytes src/cctz/testdata/zoneinfo/America/Eirunepe | Bin 436 -> 0 bytes .../testdata/zoneinfo/America/El_Salvador | Bin 176 -> 0 bytes src/cctz/testdata/zoneinfo/America/Ensenada | Bin 1367 -> 0 bytes .../testdata/zoneinfo/America/Fort_Nelson | Bin 1448 -> 0 bytes src/cctz/testdata/zoneinfo/America/Fort_Wayne | Bin 531 -> 0 bytes src/cctz/testdata/zoneinfo/America/Fortaleza | Bin 484 -> 0 bytes src/cctz/testdata/zoneinfo/America/Glace_Bay | Bin 880 -> 0 bytes src/cctz/testdata/zoneinfo/America/Godthab | Bin 965 -> 0 bytes src/cctz/testdata/zoneinfo/America/Goose_Bay | Bin 1580 -> 0 bytes src/cctz/testdata/zoneinfo/America/Grand_Turk | Bin 853 -> 0 bytes src/cctz/testdata/zoneinfo/America/Grenada | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/Guadeloupe | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/Guatemala | Bin 212 -> 0 bytes src/cctz/testdata/zoneinfo/America/Guayaquil | Bin 179 -> 0 bytes src/cctz/testdata/zoneinfo/America/Guyana | Bin 181 -> 0 bytes src/cctz/testdata/zoneinfo/America/Halifax | Bin 1672 -> 0 bytes src/cctz/testdata/zoneinfo/America/Havana | Bin 1117 -> 0 bytes src/cctz/testdata/zoneinfo/America/Hermosillo | Bin 258 -> 0 bytes .../zoneinfo/America/Indiana/Indianapolis | Bin 531 -> 0 bytes .../testdata/zoneinfo/America/Indiana/Knox | Bin 1016 -> 0 bytes .../testdata/zoneinfo/America/Indiana/Marengo | Bin 567 -> 0 bytes .../zoneinfo/America/Indiana/Petersburg | Bin 683 -> 0 bytes .../zoneinfo/America/Indiana/Tell_City | Bin 522 -> 0 bytes .../testdata/zoneinfo/America/Indiana/Vevay | Bin 369 -> 0 bytes .../zoneinfo/America/Indiana/Vincennes | Bin 558 -> 0 bytes .../testdata/zoneinfo/America/Indiana/Winamac | Bin 603 -> 0 bytes .../testdata/zoneinfo/America/Indianapolis | Bin 531 -> 0 bytes src/cctz/testdata/zoneinfo/America/Inuvik | Bin 817 -> 0 bytes src/cctz/testdata/zoneinfo/America/Iqaluit | Bin 855 -> 0 bytes src/cctz/testdata/zoneinfo/America/Jamaica | Bin 339 -> 0 bytes src/cctz/testdata/zoneinfo/America/Jujuy | Bin 690 -> 0 bytes src/cctz/testdata/zoneinfo/America/Juneau | Bin 966 -> 0 bytes .../zoneinfo/America/Kentucky/Louisville | Bin 1242 -> 0 bytes .../zoneinfo/America/Kentucky/Monticello | Bin 972 -> 0 bytes src/cctz/testdata/zoneinfo/America/Knox_IN | Bin 1016 -> 0 bytes src/cctz/testdata/zoneinfo/America/Kralendijk | Bin 151 -> 0 bytes src/cctz/testdata/zoneinfo/America/La_Paz | Bin 170 -> 0 bytes src/cctz/testdata/zoneinfo/America/Lima | Bin 283 -> 0 bytes .../testdata/zoneinfo/America/Los_Angeles | Bin 1294 -> 0 bytes src/cctz/testdata/zoneinfo/America/Louisville | Bin 1242 -> 0 bytes .../testdata/zoneinfo/America/Lower_Princes | Bin 151 -> 0 bytes src/cctz/testdata/zoneinfo/America/Maceio | Bin 502 -> 0 bytes src/cctz/testdata/zoneinfo/America/Managua | Bin 295 -> 0 bytes src/cctz/testdata/zoneinfo/America/Manaus | Bin 412 -> 0 bytes src/cctz/testdata/zoneinfo/America/Marigot | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/Martinique | Bin 178 -> 0 bytes src/cctz/testdata/zoneinfo/America/Matamoros | Bin 437 -> 0 bytes src/cctz/testdata/zoneinfo/America/Mazatlan | Bin 690 -> 0 bytes src/cctz/testdata/zoneinfo/America/Mendoza | Bin 708 -> 0 bytes src/cctz/testdata/zoneinfo/America/Menominee | Bin 917 -> 0 bytes src/cctz/testdata/zoneinfo/America/Merida | Bin 654 -> 0 bytes src/cctz/testdata/zoneinfo/America/Metlakatla | Bin 586 -> 0 bytes .../testdata/zoneinfo/America/Mexico_City | Bin 773 -> 0 bytes src/cctz/testdata/zoneinfo/America/Miquelon | Bin 550 -> 0 bytes src/cctz/testdata/zoneinfo/America/Moncton | Bin 1493 -> 0 bytes src/cctz/testdata/zoneinfo/America/Monterrey | Bin 709 -> 0 bytes src/cctz/testdata/zoneinfo/America/Montevideo | Bin 969 -> 0 bytes src/cctz/testdata/zoneinfo/America/Montreal | Bin 1717 -> 0 bytes src/cctz/testdata/zoneinfo/America/Montserrat | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/Nassau | Bin 1006 -> 0 bytes src/cctz/testdata/zoneinfo/America/New_York | Bin 1744 -> 0 bytes src/cctz/testdata/zoneinfo/America/Nipigon | Bin 1717 -> 0 bytes src/cctz/testdata/zoneinfo/America/Nome | Bin 975 -> 0 bytes src/cctz/testdata/zoneinfo/America/Noronha | Bin 484 -> 0 bytes .../zoneinfo/America/North_Dakota/Beulah | Bin 1043 -> 0 bytes .../zoneinfo/America/North_Dakota/Center | Bin 990 -> 0 bytes .../zoneinfo/America/North_Dakota/New_Salem | Bin 990 -> 0 bytes src/cctz/testdata/zoneinfo/America/Nuuk | Bin 965 -> 0 bytes src/cctz/testdata/zoneinfo/America/Ojinaga | Bin 718 -> 0 bytes src/cctz/testdata/zoneinfo/America/Panama | Bin 149 -> 0 bytes .../testdata/zoneinfo/America/Pangnirtung | Bin 855 -> 0 bytes src/cctz/testdata/zoneinfo/America/Paramaribo | Bin 187 -> 0 bytes src/cctz/testdata/zoneinfo/America/Phoenix | Bin 240 -> 0 bytes .../testdata/zoneinfo/America/Port-au-Prince | Bin 565 -> 0 bytes .../testdata/zoneinfo/America/Port_of_Spain | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/Porto_Acre | Bin 418 -> 0 bytes .../testdata/zoneinfo/America/Porto_Velho | Bin 394 -> 0 bytes .../testdata/zoneinfo/America/Puerto_Rico | Bin 177 -> 0 bytes .../testdata/zoneinfo/America/Punta_Arenas | Bin 1218 -> 0 bytes .../testdata/zoneinfo/America/Rainy_River | Bin 1294 -> 0 bytes .../testdata/zoneinfo/America/Rankin_Inlet | Bin 807 -> 0 bytes src/cctz/testdata/zoneinfo/America/Recife | Bin 484 -> 0 bytes src/cctz/testdata/zoneinfo/America/Regina | Bin 638 -> 0 bytes src/cctz/testdata/zoneinfo/America/Resolute | Bin 807 -> 0 bytes src/cctz/testdata/zoneinfo/America/Rio_Branco | Bin 418 -> 0 bytes src/cctz/testdata/zoneinfo/America/Rosario | Bin 708 -> 0 bytes .../testdata/zoneinfo/America/Santa_Isabel | Bin 1367 -> 0 bytes src/cctz/testdata/zoneinfo/America/Santarem | Bin 409 -> 0 bytes src/cctz/testdata/zoneinfo/America/Santiago | Bin 1354 -> 0 bytes .../testdata/zoneinfo/America/Santo_Domingo | Bin 317 -> 0 bytes src/cctz/testdata/zoneinfo/America/Sao_Paulo | Bin 952 -> 0 bytes .../testdata/zoneinfo/America/Scoresbysund | Bin 984 -> 0 bytes src/cctz/testdata/zoneinfo/America/Shiprock | Bin 1042 -> 0 bytes src/cctz/testdata/zoneinfo/America/Sitka | Bin 956 -> 0 bytes .../testdata/zoneinfo/America/St_Barthelemy | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/St_Johns | Bin 1878 -> 0 bytes src/cctz/testdata/zoneinfo/America/St_Kitts | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/St_Lucia | Bin 149 -> 0 bytes src/cctz/testdata/zoneinfo/America/St_Thomas | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/St_Vincent | Bin 149 -> 0 bytes .../testdata/zoneinfo/America/Swift_Current | Bin 368 -> 0 bytes .../testdata/zoneinfo/America/Tegucigalpa | Bin 194 -> 0 bytes src/cctz/testdata/zoneinfo/America/Thule | Bin 455 -> 0 bytes .../testdata/zoneinfo/America/Thunder_Bay | Bin 1717 -> 0 bytes src/cctz/testdata/zoneinfo/America/Tijuana | Bin 1367 -> 0 bytes src/cctz/testdata/zoneinfo/America/Toronto | Bin 1717 -> 0 bytes src/cctz/testdata/zoneinfo/America/Tortola | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/Vancouver | Bin 1330 -> 0 bytes src/cctz/testdata/zoneinfo/America/Virgin | Bin 130 -> 0 bytes src/cctz/testdata/zoneinfo/America/Whitehorse | Bin 1029 -> 0 bytes src/cctz/testdata/zoneinfo/America/Winnipeg | Bin 1294 -> 0 bytes src/cctz/testdata/zoneinfo/America/Yakutat | Bin 946 -> 0 bytes .../testdata/zoneinfo/America/Yellowknife | Bin 970 -> 0 bytes src/cctz/testdata/zoneinfo/Antarctica/Casey | Bin 287 -> 0 bytes src/cctz/testdata/zoneinfo/Antarctica/Davis | Bin 197 -> 0 bytes .../zoneinfo/Antarctica/DumontDUrville | Bin 152 -> 0 bytes .../testdata/zoneinfo/Antarctica/Macquarie | Bin 976 -> 0 bytes src/cctz/testdata/zoneinfo/Antarctica/Mawson | Bin 152 -> 0 bytes src/cctz/testdata/zoneinfo/Antarctica/McMurdo | Bin 768 -> 0 bytes src/cctz/testdata/zoneinfo/Antarctica/Palmer | Bin 887 -> 0 bytes src/cctz/testdata/zoneinfo/Antarctica/Rothera | Bin 132 -> 0 bytes .../testdata/zoneinfo/Antarctica/South_Pole | Bin 768 -> 0 bytes src/cctz/testdata/zoneinfo/Antarctica/Syowa | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Antarctica/Troll | Bin 158 -> 0 bytes src/cctz/testdata/zoneinfo/Antarctica/Vostok | Bin 170 -> 0 bytes .../testdata/zoneinfo/Arctic/Longyearbyen | Bin 676 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Aden | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Almaty | Bin 618 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Amman | Bin 928 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Anadyr | Bin 743 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Aqtau | Bin 606 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Aqtobe | Bin 615 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Ashgabat | Bin 375 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Ashkhabad | Bin 375 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Atyrau | Bin 616 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Baghdad | Bin 630 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Bahrain | Bin 173 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Baku | Bin 744 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Bangkok | Bin 152 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Barnaul | Bin 753 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Beirut | Bin 732 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Bishkek | Bin 618 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Brunei | Bin 154 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Calcutta | Bin 220 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Chita | Bin 750 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Choibalsan | Bin 594 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Chongqing | Bin 393 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Chungking | Bin 393 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Colombo | Bin 247 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Dacca | Bin 231 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Damascus | Bin 1234 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Dhaka | Bin 231 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Dili | Bin 170 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Dubai | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Dushanbe | Bin 366 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Famagusta | Bin 940 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Gaza | Bin 2950 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Harbin | Bin 393 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Hebron | Bin 2968 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh | Bin 236 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Hong_Kong | Bin 775 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Hovd | Bin 594 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Irkutsk | Bin 760 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Istanbul | Bin 1200 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Jakarta | Bin 248 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Jayapura | Bin 171 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Jerusalem | Bin 1074 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Kabul | Bin 159 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Kamchatka | Bin 727 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Karachi | Bin 266 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Kashgar | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Kathmandu | Bin 161 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Katmandu | Bin 161 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Khandyga | Bin 775 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Kolkata | Bin 220 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Krasnoyarsk | Bin 741 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur | Bin 256 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Kuching | Bin 320 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Kuwait | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Macao | Bin 791 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Macau | Bin 791 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Magadan | Bin 751 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Makassar | Bin 190 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Manila | Bin 274 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Muscat | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Nicosia | Bin 597 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Novokuznetsk | Bin 726 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Novosibirsk | Bin 753 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Omsk | Bin 741 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Oral | Bin 625 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Phnom_Penh | Bin 200 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Pontianak | Bin 247 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Pyongyang | Bin 183 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Qatar | Bin 152 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Qostanay | Bin 624 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Qyzylorda | Bin 624 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Rangoon | Bin 187 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Riyadh | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Saigon | Bin 236 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Sakhalin | Bin 755 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Samarkand | Bin 366 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Seoul | Bin 415 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Shanghai | Bin 393 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Singapore | Bin 256 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Srednekolymsk | Bin 742 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Taipei | Bin 511 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Tashkent | Bin 366 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Tbilisi | Bin 620 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Tehran | Bin 812 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Tel_Aviv | Bin 1074 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Thimbu | Bin 154 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Thimphu | Bin 154 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Tokyo | Bin 213 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Tomsk | Bin 753 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Ujung_Pandang | Bin 190 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Ulaanbaatar | Bin 594 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Ulan_Bator | Bin 594 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Urumqi | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Ust-Nera | Bin 771 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Vientiane | Bin 218 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Vladivostok | Bin 742 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Yakutsk | Bin 741 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Yangon | Bin 187 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Yekaterinburg | Bin 760 -> 0 bytes src/cctz/testdata/zoneinfo/Asia/Yerevan | Bin 708 -> 0 bytes src/cctz/testdata/zoneinfo/Atlantic/Azores | Bin 1401 -> 0 bytes src/cctz/testdata/zoneinfo/Atlantic/Bermuda | Bin 1024 -> 0 bytes src/cctz/testdata/zoneinfo/Atlantic/Canary | Bin 478 -> 0 bytes .../testdata/zoneinfo/Atlantic/Cape_Verde | Bin 175 -> 0 bytes src/cctz/testdata/zoneinfo/Atlantic/Faeroe | Bin 441 -> 0 bytes src/cctz/testdata/zoneinfo/Atlantic/Faroe | Bin 441 -> 0 bytes src/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen | Bin 676 -> 0 bytes src/cctz/testdata/zoneinfo/Atlantic/Madeira | Bin 1372 -> 0 bytes src/cctz/testdata/zoneinfo/Atlantic/Reykjavik | Bin 753 -> 0 bytes .../testdata/zoneinfo/Atlantic/South_Georgia | Bin 132 -> 0 bytes src/cctz/testdata/zoneinfo/Atlantic/St_Helena | Bin 149 -> 0 bytes src/cctz/testdata/zoneinfo/Atlantic/Stanley | Bin 789 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/ACT | Bin 904 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Adelaide | Bin 921 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Brisbane | Bin 289 -> 0 bytes .../testdata/zoneinfo/Australia/Broken_Hill | Bin 941 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Canberra | Bin 904 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Currie | Bin 1003 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Darwin | Bin 234 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Eucla | Bin 314 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Hobart | Bin 1003 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/LHI | Bin 692 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Lindeman | Bin 325 -> 0 bytes .../testdata/zoneinfo/Australia/Lord_Howe | Bin 692 -> 0 bytes .../testdata/zoneinfo/Australia/Melbourne | Bin 904 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/NSW | Bin 904 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/North | Bin 234 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Perth | Bin 306 -> 0 bytes .../testdata/zoneinfo/Australia/Queensland | Bin 289 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/South | Bin 921 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Sydney | Bin 904 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Tasmania | Bin 1003 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/Victoria | Bin 904 -> 0 bytes src/cctz/testdata/zoneinfo/Australia/West | Bin 306 -> 0 bytes .../testdata/zoneinfo/Australia/Yancowinna | Bin 941 -> 0 bytes src/cctz/testdata/zoneinfo/Brazil/Acre | Bin 418 -> 0 bytes src/cctz/testdata/zoneinfo/Brazil/DeNoronha | Bin 484 -> 0 bytes src/cctz/testdata/zoneinfo/Brazil/East | Bin 952 -> 0 bytes src/cctz/testdata/zoneinfo/Brazil/West | Bin 412 -> 0 bytes src/cctz/testdata/zoneinfo/CET | Bin 1103 -> 0 bytes src/cctz/testdata/zoneinfo/CST6CDT | Bin 1754 -> 0 bytes src/cctz/testdata/zoneinfo/Canada/Atlantic | Bin 1672 -> 0 bytes src/cctz/testdata/zoneinfo/Canada/Central | Bin 1294 -> 0 bytes src/cctz/testdata/zoneinfo/Canada/Eastern | Bin 1717 -> 0 bytes src/cctz/testdata/zoneinfo/Canada/Mountain | Bin 970 -> 0 bytes .../testdata/zoneinfo/Canada/Newfoundland | Bin 1878 -> 0 bytes src/cctz/testdata/zoneinfo/Canada/Pacific | Bin 1330 -> 0 bytes .../testdata/zoneinfo/Canada/Saskatchewan | Bin 638 -> 0 bytes src/cctz/testdata/zoneinfo/Canada/Yukon | Bin 1029 -> 0 bytes src/cctz/testdata/zoneinfo/Chile/Continental | Bin 1354 -> 0 bytes src/cctz/testdata/zoneinfo/Chile/EasterIsland | Bin 1174 -> 0 bytes src/cctz/testdata/zoneinfo/Cuba | Bin 1117 -> 0 bytes src/cctz/testdata/zoneinfo/EET | Bin 682 -> 0 bytes src/cctz/testdata/zoneinfo/EST | Bin 149 -> 0 bytes src/cctz/testdata/zoneinfo/EST5EDT | Bin 1744 -> 0 bytes src/cctz/testdata/zoneinfo/Egypt | Bin 1309 -> 0 bytes src/cctz/testdata/zoneinfo/Eire | Bin 1496 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+0 | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+1 | Bin 113 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+10 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+11 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+12 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+2 | Bin 113 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+3 | Bin 113 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+4 | Bin 113 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+5 | Bin 113 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+6 | Bin 113 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+7 | Bin 113 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+8 | Bin 113 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT+9 | Bin 113 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-0 | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-1 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-10 | Bin 115 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-11 | Bin 115 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-12 | Bin 115 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-13 | Bin 115 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-14 | Bin 115 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-2 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-3 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-4 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-5 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-6 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-7 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-8 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT-9 | Bin 114 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/GMT0 | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/Greenwich | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/UCT | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/UTC | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/Universal | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Etc/Zulu | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Amsterdam | Bin 1071 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Andorra | Bin 389 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Astrakhan | Bin 726 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Athens | Bin 682 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Belfast | Bin 1599 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Belgrade | Bin 478 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Berlin | Bin 705 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Bratislava | Bin 723 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Brussels | Bin 1103 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Bucharest | Bin 661 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Budapest | Bin 766 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Busingen | Bin 497 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Chisinau | Bin 1207 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Copenhagen | Bin 623 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Dublin | Bin 1496 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Gibraltar | Bin 1220 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Guernsey | Bin 1611 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Helsinki | Bin 481 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Isle_of_Man | Bin 1599 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Istanbul | Bin 1200 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Jersey | Bin 1611 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Kaliningrad | Bin 904 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Kiev | Bin 558 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Kirov | Bin 735 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Kyiv | Bin 558 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Lisbon | Bin 1463 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Ljubljana | Bin 478 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/London | Bin 1599 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Luxembourg | Bin 1087 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Madrid | Bin 897 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Malta | Bin 928 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Mariehamn | Bin 481 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Minsk | Bin 808 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Monaco | Bin 1114 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Moscow | Bin 908 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Nicosia | Bin 597 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Oslo | Bin 676 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Paris | Bin 1105 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Podgorica | Bin 478 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Prague | Bin 723 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Riga | Bin 694 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Rome | Bin 947 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Samara | Bin 732 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/San_Marino | Bin 947 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Sarajevo | Bin 478 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Saratov | Bin 726 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Simferopol | Bin 865 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Skopje | Bin 478 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Sofia | Bin 592 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Stockholm | Bin 497 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Tallinn | Bin 675 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Tirane | Bin 604 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Tiraspol | Bin 1207 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Ulyanovsk | Bin 760 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Uzhgorod | Bin 558 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Vaduz | Bin 478 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Vatican | Bin 947 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Vienna | Bin 658 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Vilnius | Bin 676 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Volgograd | Bin 753 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Warsaw | Bin 923 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Zagreb | Bin 478 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Zaporozhye | Bin 558 -> 0 bytes src/cctz/testdata/zoneinfo/Europe/Zurich | Bin 497 -> 0 bytes src/cctz/testdata/zoneinfo/Factory | Bin 113 -> 0 bytes src/cctz/testdata/zoneinfo/GB | Bin 1599 -> 0 bytes src/cctz/testdata/zoneinfo/GB-Eire | Bin 1599 -> 0 bytes src/cctz/testdata/zoneinfo/GMT | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/GMT+0 | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/GMT-0 | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/GMT0 | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Greenwich | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/HST | Bin 221 -> 0 bytes src/cctz/testdata/zoneinfo/Hongkong | Bin 775 -> 0 bytes src/cctz/testdata/zoneinfo/Iceland | Bin 753 -> 0 bytes .../testdata/zoneinfo/Indian/Antananarivo | Bin 160 -> 0 bytes src/cctz/testdata/zoneinfo/Indian/Chagos | Bin 152 -> 0 bytes src/cctz/testdata/zoneinfo/Indian/Christmas | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Indian/Cocos | Bin 140 -> 0 bytes src/cctz/testdata/zoneinfo/Indian/Comoro | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Indian/Kerguelen | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Indian/Mahe | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Indian/Maldives | Bin 152 -> 0 bytes src/cctz/testdata/zoneinfo/Indian/Mauritius | Bin 179 -> 0 bytes src/cctz/testdata/zoneinfo/Indian/Mayotte | Bin 131 -> 0 bytes src/cctz/testdata/zoneinfo/Indian/Reunion | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Iran | Bin 812 -> 0 bytes src/cctz/testdata/zoneinfo/Israel | Bin 1074 -> 0 bytes src/cctz/testdata/zoneinfo/Jamaica | Bin 339 -> 0 bytes src/cctz/testdata/zoneinfo/Japan | Bin 213 -> 0 bytes src/cctz/testdata/zoneinfo/Kwajalein | Bin 219 -> 0 bytes src/cctz/testdata/zoneinfo/Libya | Bin 431 -> 0 bytes src/cctz/testdata/zoneinfo/MET | Bin 1103 -> 0 bytes src/cctz/testdata/zoneinfo/MST | Bin 240 -> 0 bytes src/cctz/testdata/zoneinfo/MST7MDT | Bin 1042 -> 0 bytes src/cctz/testdata/zoneinfo/Mexico/BajaNorte | Bin 1367 -> 0 bytes src/cctz/testdata/zoneinfo/Mexico/BajaSur | Bin 690 -> 0 bytes src/cctz/testdata/zoneinfo/Mexico/General | Bin 773 -> 0 bytes src/cctz/testdata/zoneinfo/NZ | Bin 1043 -> 0 bytes src/cctz/testdata/zoneinfo/NZ-CHAT | Bin 808 -> 0 bytes src/cctz/testdata/zoneinfo/Navajo | Bin 1042 -> 0 bytes src/cctz/testdata/zoneinfo/PRC | Bin 393 -> 0 bytes src/cctz/testdata/zoneinfo/PST8PDT | Bin 1294 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Apia | Bin 407 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Auckland | Bin 1043 -> 0 bytes .../testdata/zoneinfo/Pacific/Bougainville | Bin 201 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Chatham | Bin 808 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Chuuk | Bin 195 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Easter | Bin 1174 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Efate | Bin 342 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Enderbury | Bin 172 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Fakaofo | Bin 153 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Fiji | Bin 396 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Funafuti | Bin 134 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Galapagos | Bin 175 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Gambier | Bin 132 -> 0 bytes .../testdata/zoneinfo/Pacific/Guadalcanal | Bin 134 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Guam | Bin 350 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Honolulu | Bin 221 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Johnston | Bin 221 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Kanton | Bin 172 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Kiritimati | Bin 174 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Kosrae | Bin 242 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Kwajalein | Bin 219 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Majuro | Bin 218 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Marquesas | Bin 139 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Midway | Bin 169 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Nauru | Bin 183 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Niue | Bin 154 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Norfolk | Bin 237 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Noumea | Bin 198 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Pago_Pago | Bin 146 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Palau | Bin 148 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Pitcairn | Bin 153 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Pohnpei | Bin 214 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Ponape | Bin 214 -> 0 bytes .../testdata/zoneinfo/Pacific/Port_Moresby | Bin 154 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Rarotonga | Bin 406 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Saipan | Bin 341 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Samoa | Bin 146 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Tahiti | Bin 133 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Tarawa | Bin 134 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Tongatapu | Bin 237 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Truk | Bin 195 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Wake | Bin 134 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Wallis | Bin 134 -> 0 bytes src/cctz/testdata/zoneinfo/Pacific/Yap | Bin 195 -> 0 bytes src/cctz/testdata/zoneinfo/Poland | Bin 923 -> 0 bytes src/cctz/testdata/zoneinfo/Portugal | Bin 1463 -> 0 bytes src/cctz/testdata/zoneinfo/ROC | Bin 511 -> 0 bytes src/cctz/testdata/zoneinfo/ROK | Bin 415 -> 0 bytes src/cctz/testdata/zoneinfo/Singapore | Bin 256 -> 0 bytes src/cctz/testdata/zoneinfo/Turkey | Bin 1200 -> 0 bytes src/cctz/testdata/zoneinfo/UCT | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/US/Alaska | Bin 977 -> 0 bytes src/cctz/testdata/zoneinfo/US/Aleutian | Bin 969 -> 0 bytes src/cctz/testdata/zoneinfo/US/Arizona | Bin 240 -> 0 bytes src/cctz/testdata/zoneinfo/US/Central | Bin 1754 -> 0 bytes src/cctz/testdata/zoneinfo/US/East-Indiana | Bin 531 -> 0 bytes src/cctz/testdata/zoneinfo/US/Eastern | Bin 1744 -> 0 bytes src/cctz/testdata/zoneinfo/US/Hawaii | Bin 221 -> 0 bytes src/cctz/testdata/zoneinfo/US/Indiana-Starke | Bin 1016 -> 0 bytes src/cctz/testdata/zoneinfo/US/Michigan | Bin 899 -> 0 bytes src/cctz/testdata/zoneinfo/US/Mountain | Bin 1042 -> 0 bytes src/cctz/testdata/zoneinfo/US/Pacific | Bin 1294 -> 0 bytes src/cctz/testdata/zoneinfo/US/Samoa | Bin 146 -> 0 bytes src/cctz/testdata/zoneinfo/UTC | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/Universal | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/W-SU | Bin 908 -> 0 bytes src/cctz/testdata/zoneinfo/WET | Bin 1463 -> 0 bytes src/cctz/testdata/zoneinfo/Zulu | Bin 111 -> 0 bytes src/cctz/testdata/zoneinfo/iso3166.tab | 279 ------------- src/cctz/testdata/zoneinfo/zone1970.tab | 375 ------------------ src/cctz/testdata/zoneinfo/zonenow.tab | 293 -------------- 606 files changed, 1249 deletions(-) delete mode 100644 HANDOFF_CCTZ_UPDATE.md delete mode 100644 src/cctz/.github/workflows/ci.yaml delete mode 100644 src/cctz/.github/workflows/cifuzz.yml delete mode 100644 src/cctz/testdata/README.zoneinfo delete mode 100644 src/cctz/testdata/version delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Abidjan delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Accra delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Addis_Ababa delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Algiers delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Asmara delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Asmera delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Bamako delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Bangui delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Banjul delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Bissau delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Blantyre delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Brazzaville delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Bujumbura delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Cairo delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Casablanca delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Ceuta delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Conakry delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Dakar delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Djibouti delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Douala delete mode 100644 src/cctz/testdata/zoneinfo/Africa/El_Aaiun delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Freetown delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Gaborone delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Harare delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Johannesburg delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Juba delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Kampala delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Khartoum delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Kigali delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Kinshasa delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Lagos delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Libreville delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Lome delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Luanda delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Lubumbashi delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Lusaka delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Malabo delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Maputo delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Maseru delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Mbabane delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Mogadishu delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Monrovia delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Nairobi delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Ndjamena delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Niamey delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Nouakchott delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Ouagadougou delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Porto-Novo delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Sao_Tome delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Timbuktu delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Tripoli delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Tunis delete mode 100644 src/cctz/testdata/zoneinfo/Africa/Windhoek delete mode 100644 src/cctz/testdata/zoneinfo/America/Adak delete mode 100644 src/cctz/testdata/zoneinfo/America/Anchorage delete mode 100644 src/cctz/testdata/zoneinfo/America/Anguilla delete mode 100644 src/cctz/testdata/zoneinfo/America/Antigua delete mode 100644 src/cctz/testdata/zoneinfo/America/Araguaina delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/Catamarca delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/Cordoba delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/Jujuy delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/La_Rioja delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/Mendoza delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/Salta delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/San_Juan delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/San_Luis delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/Tucuman delete mode 100644 src/cctz/testdata/zoneinfo/America/Argentina/Ushuaia delete mode 100644 src/cctz/testdata/zoneinfo/America/Aruba delete mode 100644 src/cctz/testdata/zoneinfo/America/Asuncion delete mode 100644 src/cctz/testdata/zoneinfo/America/Atikokan delete mode 100644 src/cctz/testdata/zoneinfo/America/Atka delete mode 100644 src/cctz/testdata/zoneinfo/America/Bahia delete mode 100644 src/cctz/testdata/zoneinfo/America/Bahia_Banderas delete mode 100644 src/cctz/testdata/zoneinfo/America/Barbados delete mode 100644 src/cctz/testdata/zoneinfo/America/Belem delete mode 100644 src/cctz/testdata/zoneinfo/America/Belize delete mode 100644 src/cctz/testdata/zoneinfo/America/Blanc-Sablon delete mode 100644 src/cctz/testdata/zoneinfo/America/Boa_Vista delete mode 100644 src/cctz/testdata/zoneinfo/America/Bogota delete mode 100644 src/cctz/testdata/zoneinfo/America/Boise delete mode 100644 src/cctz/testdata/zoneinfo/America/Buenos_Aires delete mode 100644 src/cctz/testdata/zoneinfo/America/Cambridge_Bay delete mode 100644 src/cctz/testdata/zoneinfo/America/Campo_Grande delete mode 100644 src/cctz/testdata/zoneinfo/America/Cancun delete mode 100644 src/cctz/testdata/zoneinfo/America/Caracas delete mode 100644 src/cctz/testdata/zoneinfo/America/Catamarca delete mode 100644 src/cctz/testdata/zoneinfo/America/Cayenne delete mode 100644 src/cctz/testdata/zoneinfo/America/Cayman delete mode 100644 src/cctz/testdata/zoneinfo/America/Chicago delete mode 100644 src/cctz/testdata/zoneinfo/America/Chihuahua delete mode 100644 src/cctz/testdata/zoneinfo/America/Ciudad_Juarez delete mode 100644 src/cctz/testdata/zoneinfo/America/Coral_Harbour delete mode 100644 src/cctz/testdata/zoneinfo/America/Cordoba delete mode 100644 src/cctz/testdata/zoneinfo/America/Costa_Rica delete mode 100644 src/cctz/testdata/zoneinfo/America/Coyhaique delete mode 100644 src/cctz/testdata/zoneinfo/America/Creston delete mode 100644 src/cctz/testdata/zoneinfo/America/Cuiaba delete mode 100644 src/cctz/testdata/zoneinfo/America/Curacao delete mode 100644 src/cctz/testdata/zoneinfo/America/Danmarkshavn delete mode 100644 src/cctz/testdata/zoneinfo/America/Dawson delete mode 100644 src/cctz/testdata/zoneinfo/America/Dawson_Creek delete mode 100644 src/cctz/testdata/zoneinfo/America/Denver delete mode 100644 src/cctz/testdata/zoneinfo/America/Detroit delete mode 100644 src/cctz/testdata/zoneinfo/America/Dominica delete mode 100644 src/cctz/testdata/zoneinfo/America/Edmonton delete mode 100644 src/cctz/testdata/zoneinfo/America/Eirunepe delete mode 100644 src/cctz/testdata/zoneinfo/America/El_Salvador delete mode 100644 src/cctz/testdata/zoneinfo/America/Ensenada delete mode 100644 src/cctz/testdata/zoneinfo/America/Fort_Nelson delete mode 100644 src/cctz/testdata/zoneinfo/America/Fort_Wayne delete mode 100644 src/cctz/testdata/zoneinfo/America/Fortaleza delete mode 100644 src/cctz/testdata/zoneinfo/America/Glace_Bay delete mode 100644 src/cctz/testdata/zoneinfo/America/Godthab delete mode 100644 src/cctz/testdata/zoneinfo/America/Goose_Bay delete mode 100644 src/cctz/testdata/zoneinfo/America/Grand_Turk delete mode 100644 src/cctz/testdata/zoneinfo/America/Grenada delete mode 100644 src/cctz/testdata/zoneinfo/America/Guadeloupe delete mode 100644 src/cctz/testdata/zoneinfo/America/Guatemala delete mode 100644 src/cctz/testdata/zoneinfo/America/Guayaquil delete mode 100644 src/cctz/testdata/zoneinfo/America/Guyana delete mode 100644 src/cctz/testdata/zoneinfo/America/Halifax delete mode 100644 src/cctz/testdata/zoneinfo/America/Havana delete mode 100644 src/cctz/testdata/zoneinfo/America/Hermosillo delete mode 100644 src/cctz/testdata/zoneinfo/America/Indiana/Indianapolis delete mode 100644 src/cctz/testdata/zoneinfo/America/Indiana/Knox delete mode 100644 src/cctz/testdata/zoneinfo/America/Indiana/Marengo delete mode 100644 src/cctz/testdata/zoneinfo/America/Indiana/Petersburg delete mode 100644 src/cctz/testdata/zoneinfo/America/Indiana/Tell_City delete mode 100644 src/cctz/testdata/zoneinfo/America/Indiana/Vevay delete mode 100644 src/cctz/testdata/zoneinfo/America/Indiana/Vincennes delete mode 100644 src/cctz/testdata/zoneinfo/America/Indiana/Winamac delete mode 100644 src/cctz/testdata/zoneinfo/America/Indianapolis delete mode 100644 src/cctz/testdata/zoneinfo/America/Inuvik delete mode 100644 src/cctz/testdata/zoneinfo/America/Iqaluit delete mode 100644 src/cctz/testdata/zoneinfo/America/Jamaica delete mode 100644 src/cctz/testdata/zoneinfo/America/Jujuy delete mode 100644 src/cctz/testdata/zoneinfo/America/Juneau delete mode 100644 src/cctz/testdata/zoneinfo/America/Kentucky/Louisville delete mode 100644 src/cctz/testdata/zoneinfo/America/Kentucky/Monticello delete mode 100644 src/cctz/testdata/zoneinfo/America/Knox_IN delete mode 100644 src/cctz/testdata/zoneinfo/America/Kralendijk delete mode 100644 src/cctz/testdata/zoneinfo/America/La_Paz delete mode 100644 src/cctz/testdata/zoneinfo/America/Lima delete mode 100644 src/cctz/testdata/zoneinfo/America/Los_Angeles delete mode 100644 src/cctz/testdata/zoneinfo/America/Louisville delete mode 100644 src/cctz/testdata/zoneinfo/America/Lower_Princes delete mode 100644 src/cctz/testdata/zoneinfo/America/Maceio delete mode 100644 src/cctz/testdata/zoneinfo/America/Managua delete mode 100644 src/cctz/testdata/zoneinfo/America/Manaus delete mode 100644 src/cctz/testdata/zoneinfo/America/Marigot delete mode 100644 src/cctz/testdata/zoneinfo/America/Martinique delete mode 100644 src/cctz/testdata/zoneinfo/America/Matamoros delete mode 100644 src/cctz/testdata/zoneinfo/America/Mazatlan delete mode 100644 src/cctz/testdata/zoneinfo/America/Mendoza delete mode 100644 src/cctz/testdata/zoneinfo/America/Menominee delete mode 100644 src/cctz/testdata/zoneinfo/America/Merida delete mode 100644 src/cctz/testdata/zoneinfo/America/Metlakatla delete mode 100644 src/cctz/testdata/zoneinfo/America/Mexico_City delete mode 100644 src/cctz/testdata/zoneinfo/America/Miquelon delete mode 100644 src/cctz/testdata/zoneinfo/America/Moncton delete mode 100644 src/cctz/testdata/zoneinfo/America/Monterrey delete mode 100644 src/cctz/testdata/zoneinfo/America/Montevideo delete mode 100644 src/cctz/testdata/zoneinfo/America/Montreal delete mode 100644 src/cctz/testdata/zoneinfo/America/Montserrat delete mode 100644 src/cctz/testdata/zoneinfo/America/Nassau delete mode 100644 src/cctz/testdata/zoneinfo/America/New_York delete mode 100644 src/cctz/testdata/zoneinfo/America/Nipigon delete mode 100644 src/cctz/testdata/zoneinfo/America/Nome delete mode 100644 src/cctz/testdata/zoneinfo/America/Noronha delete mode 100644 src/cctz/testdata/zoneinfo/America/North_Dakota/Beulah delete mode 100644 src/cctz/testdata/zoneinfo/America/North_Dakota/Center delete mode 100644 src/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem delete mode 100644 src/cctz/testdata/zoneinfo/America/Nuuk delete mode 100644 src/cctz/testdata/zoneinfo/America/Ojinaga delete mode 100644 src/cctz/testdata/zoneinfo/America/Panama delete mode 100644 src/cctz/testdata/zoneinfo/America/Pangnirtung delete mode 100644 src/cctz/testdata/zoneinfo/America/Paramaribo delete mode 100644 src/cctz/testdata/zoneinfo/America/Phoenix delete mode 100644 src/cctz/testdata/zoneinfo/America/Port-au-Prince delete mode 100644 src/cctz/testdata/zoneinfo/America/Port_of_Spain delete mode 100644 src/cctz/testdata/zoneinfo/America/Porto_Acre delete mode 100644 src/cctz/testdata/zoneinfo/America/Porto_Velho delete mode 100644 src/cctz/testdata/zoneinfo/America/Puerto_Rico delete mode 100644 src/cctz/testdata/zoneinfo/America/Punta_Arenas delete mode 100644 src/cctz/testdata/zoneinfo/America/Rainy_River delete mode 100644 src/cctz/testdata/zoneinfo/America/Rankin_Inlet delete mode 100644 src/cctz/testdata/zoneinfo/America/Recife delete mode 100644 src/cctz/testdata/zoneinfo/America/Regina delete mode 100644 src/cctz/testdata/zoneinfo/America/Resolute delete mode 100644 src/cctz/testdata/zoneinfo/America/Rio_Branco delete mode 100644 src/cctz/testdata/zoneinfo/America/Rosario delete mode 100644 src/cctz/testdata/zoneinfo/America/Santa_Isabel delete mode 100644 src/cctz/testdata/zoneinfo/America/Santarem delete mode 100644 src/cctz/testdata/zoneinfo/America/Santiago delete mode 100644 src/cctz/testdata/zoneinfo/America/Santo_Domingo delete mode 100644 src/cctz/testdata/zoneinfo/America/Sao_Paulo delete mode 100644 src/cctz/testdata/zoneinfo/America/Scoresbysund delete mode 100644 src/cctz/testdata/zoneinfo/America/Shiprock delete mode 100644 src/cctz/testdata/zoneinfo/America/Sitka delete mode 100644 src/cctz/testdata/zoneinfo/America/St_Barthelemy delete mode 100644 src/cctz/testdata/zoneinfo/America/St_Johns delete mode 100644 src/cctz/testdata/zoneinfo/America/St_Kitts delete mode 100644 src/cctz/testdata/zoneinfo/America/St_Lucia delete mode 100644 src/cctz/testdata/zoneinfo/America/St_Thomas delete mode 100644 src/cctz/testdata/zoneinfo/America/St_Vincent delete mode 100644 src/cctz/testdata/zoneinfo/America/Swift_Current delete mode 100644 src/cctz/testdata/zoneinfo/America/Tegucigalpa delete mode 100644 src/cctz/testdata/zoneinfo/America/Thule delete mode 100644 src/cctz/testdata/zoneinfo/America/Thunder_Bay delete mode 100644 src/cctz/testdata/zoneinfo/America/Tijuana delete mode 100644 src/cctz/testdata/zoneinfo/America/Toronto delete mode 100644 src/cctz/testdata/zoneinfo/America/Tortola delete mode 100644 src/cctz/testdata/zoneinfo/America/Vancouver delete mode 100644 src/cctz/testdata/zoneinfo/America/Virgin delete mode 100644 src/cctz/testdata/zoneinfo/America/Whitehorse delete mode 100644 src/cctz/testdata/zoneinfo/America/Winnipeg delete mode 100644 src/cctz/testdata/zoneinfo/America/Yakutat delete mode 100644 src/cctz/testdata/zoneinfo/America/Yellowknife delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/Casey delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/Davis delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/DumontDUrville delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/Macquarie delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/Mawson delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/McMurdo delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/Palmer delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/Rothera delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/South_Pole delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/Syowa delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/Troll delete mode 100644 src/cctz/testdata/zoneinfo/Antarctica/Vostok delete mode 100644 src/cctz/testdata/zoneinfo/Arctic/Longyearbyen delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Aden delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Almaty delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Amman delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Anadyr delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Aqtau delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Aqtobe delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Ashgabat delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Ashkhabad delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Atyrau delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Baghdad delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Bahrain delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Baku delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Bangkok delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Barnaul delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Beirut delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Bishkek delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Brunei delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Calcutta delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Chita delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Choibalsan delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Chongqing delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Chungking delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Colombo delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Dacca delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Damascus delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Dhaka delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Dili delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Dubai delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Dushanbe delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Famagusta delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Gaza delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Harbin delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Hebron delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Hong_Kong delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Hovd delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Irkutsk delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Istanbul delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Jakarta delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Jayapura delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Jerusalem delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Kabul delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Kamchatka delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Karachi delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Kashgar delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Kathmandu delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Katmandu delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Khandyga delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Kolkata delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Krasnoyarsk delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Kuching delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Kuwait delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Macao delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Macau delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Magadan delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Makassar delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Manila delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Muscat delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Nicosia delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Novokuznetsk delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Novosibirsk delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Omsk delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Oral delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Phnom_Penh delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Pontianak delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Pyongyang delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Qatar delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Qostanay delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Qyzylorda delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Rangoon delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Riyadh delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Saigon delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Sakhalin delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Samarkand delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Seoul delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Shanghai delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Singapore delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Srednekolymsk delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Taipei delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Tashkent delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Tbilisi delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Tehran delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Tel_Aviv delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Thimbu delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Thimphu delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Tokyo delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Tomsk delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Ujung_Pandang delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Ulaanbaatar delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Ulan_Bator delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Urumqi delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Ust-Nera delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Vientiane delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Vladivostok delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Yakutsk delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Yangon delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Yekaterinburg delete mode 100644 src/cctz/testdata/zoneinfo/Asia/Yerevan delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/Azores delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/Bermuda delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/Canary delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/Cape_Verde delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/Faeroe delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/Faroe delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/Madeira delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/Reykjavik delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/South_Georgia delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/St_Helena delete mode 100644 src/cctz/testdata/zoneinfo/Atlantic/Stanley delete mode 100644 src/cctz/testdata/zoneinfo/Australia/ACT delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Adelaide delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Brisbane delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Broken_Hill delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Canberra delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Currie delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Darwin delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Eucla delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Hobart delete mode 100644 src/cctz/testdata/zoneinfo/Australia/LHI delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Lindeman delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Lord_Howe delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Melbourne delete mode 100644 src/cctz/testdata/zoneinfo/Australia/NSW delete mode 100644 src/cctz/testdata/zoneinfo/Australia/North delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Perth delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Queensland delete mode 100644 src/cctz/testdata/zoneinfo/Australia/South delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Sydney delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Tasmania delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Victoria delete mode 100644 src/cctz/testdata/zoneinfo/Australia/West delete mode 100644 src/cctz/testdata/zoneinfo/Australia/Yancowinna delete mode 100644 src/cctz/testdata/zoneinfo/Brazil/Acre delete mode 100644 src/cctz/testdata/zoneinfo/Brazil/DeNoronha delete mode 100644 src/cctz/testdata/zoneinfo/Brazil/East delete mode 100644 src/cctz/testdata/zoneinfo/Brazil/West delete mode 100644 src/cctz/testdata/zoneinfo/CET delete mode 100644 src/cctz/testdata/zoneinfo/CST6CDT delete mode 100644 src/cctz/testdata/zoneinfo/Canada/Atlantic delete mode 100644 src/cctz/testdata/zoneinfo/Canada/Central delete mode 100644 src/cctz/testdata/zoneinfo/Canada/Eastern delete mode 100644 src/cctz/testdata/zoneinfo/Canada/Mountain delete mode 100644 src/cctz/testdata/zoneinfo/Canada/Newfoundland delete mode 100644 src/cctz/testdata/zoneinfo/Canada/Pacific delete mode 100644 src/cctz/testdata/zoneinfo/Canada/Saskatchewan delete mode 100644 src/cctz/testdata/zoneinfo/Canada/Yukon delete mode 100644 src/cctz/testdata/zoneinfo/Chile/Continental delete mode 100644 src/cctz/testdata/zoneinfo/Chile/EasterIsland delete mode 100644 src/cctz/testdata/zoneinfo/Cuba delete mode 100644 src/cctz/testdata/zoneinfo/EET delete mode 100644 src/cctz/testdata/zoneinfo/EST delete mode 100644 src/cctz/testdata/zoneinfo/EST5EDT delete mode 100644 src/cctz/testdata/zoneinfo/Egypt delete mode 100644 src/cctz/testdata/zoneinfo/Eire delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+0 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+1 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+10 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+11 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+12 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+2 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+3 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+4 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+5 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+6 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+7 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+8 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT+9 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-0 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-1 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-10 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-11 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-12 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-13 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-14 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-2 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-3 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-4 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-5 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-6 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-7 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-8 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT-9 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/GMT0 delete mode 100644 src/cctz/testdata/zoneinfo/Etc/Greenwich delete mode 100644 src/cctz/testdata/zoneinfo/Etc/UCT delete mode 100644 src/cctz/testdata/zoneinfo/Etc/UTC delete mode 100644 src/cctz/testdata/zoneinfo/Etc/Universal delete mode 100644 src/cctz/testdata/zoneinfo/Etc/Zulu delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Amsterdam delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Andorra delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Astrakhan delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Athens delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Belfast delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Belgrade delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Berlin delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Bratislava delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Brussels delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Bucharest delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Budapest delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Busingen delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Chisinau delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Copenhagen delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Dublin delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Gibraltar delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Guernsey delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Helsinki delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Isle_of_Man delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Istanbul delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Jersey delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Kaliningrad delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Kiev delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Kirov delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Kyiv delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Lisbon delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Ljubljana delete mode 100644 src/cctz/testdata/zoneinfo/Europe/London delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Luxembourg delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Madrid delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Malta delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Mariehamn delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Minsk delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Monaco delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Moscow delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Nicosia delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Oslo delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Paris delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Podgorica delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Prague delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Riga delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Rome delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Samara delete mode 100644 src/cctz/testdata/zoneinfo/Europe/San_Marino delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Sarajevo delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Saratov delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Simferopol delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Skopje delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Sofia delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Stockholm delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Tallinn delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Tirane delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Tiraspol delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Ulyanovsk delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Uzhgorod delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Vaduz delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Vatican delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Vienna delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Vilnius delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Volgograd delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Warsaw delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Zagreb delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Zaporozhye delete mode 100644 src/cctz/testdata/zoneinfo/Europe/Zurich delete mode 100644 src/cctz/testdata/zoneinfo/Factory delete mode 100644 src/cctz/testdata/zoneinfo/GB delete mode 100644 src/cctz/testdata/zoneinfo/GB-Eire delete mode 100644 src/cctz/testdata/zoneinfo/GMT delete mode 100644 src/cctz/testdata/zoneinfo/GMT+0 delete mode 100644 src/cctz/testdata/zoneinfo/GMT-0 delete mode 100644 src/cctz/testdata/zoneinfo/GMT0 delete mode 100644 src/cctz/testdata/zoneinfo/Greenwich delete mode 100644 src/cctz/testdata/zoneinfo/HST delete mode 100644 src/cctz/testdata/zoneinfo/Hongkong delete mode 100644 src/cctz/testdata/zoneinfo/Iceland delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Antananarivo delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Chagos delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Christmas delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Cocos delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Comoro delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Kerguelen delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Mahe delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Maldives delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Mauritius delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Mayotte delete mode 100644 src/cctz/testdata/zoneinfo/Indian/Reunion delete mode 100644 src/cctz/testdata/zoneinfo/Iran delete mode 100644 src/cctz/testdata/zoneinfo/Israel delete mode 100644 src/cctz/testdata/zoneinfo/Jamaica delete mode 100644 src/cctz/testdata/zoneinfo/Japan delete mode 100644 src/cctz/testdata/zoneinfo/Kwajalein delete mode 100644 src/cctz/testdata/zoneinfo/Libya delete mode 100644 src/cctz/testdata/zoneinfo/MET delete mode 100644 src/cctz/testdata/zoneinfo/MST delete mode 100644 src/cctz/testdata/zoneinfo/MST7MDT delete mode 100644 src/cctz/testdata/zoneinfo/Mexico/BajaNorte delete mode 100644 src/cctz/testdata/zoneinfo/Mexico/BajaSur delete mode 100644 src/cctz/testdata/zoneinfo/Mexico/General delete mode 100644 src/cctz/testdata/zoneinfo/NZ delete mode 100644 src/cctz/testdata/zoneinfo/NZ-CHAT delete mode 100644 src/cctz/testdata/zoneinfo/Navajo delete mode 100644 src/cctz/testdata/zoneinfo/PRC delete mode 100644 src/cctz/testdata/zoneinfo/PST8PDT delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Apia delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Auckland delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Bougainville delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Chatham delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Chuuk delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Easter delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Efate delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Enderbury delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Fakaofo delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Fiji delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Funafuti delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Galapagos delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Gambier delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Guadalcanal delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Guam delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Honolulu delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Johnston delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Kanton delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Kiritimati delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Kosrae delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Kwajalein delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Majuro delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Marquesas delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Midway delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Nauru delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Niue delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Norfolk delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Noumea delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Pago_Pago delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Palau delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Pitcairn delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Pohnpei delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Ponape delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Port_Moresby delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Rarotonga delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Saipan delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Samoa delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Tahiti delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Tarawa delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Tongatapu delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Truk delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Wake delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Wallis delete mode 100644 src/cctz/testdata/zoneinfo/Pacific/Yap delete mode 100644 src/cctz/testdata/zoneinfo/Poland delete mode 100644 src/cctz/testdata/zoneinfo/Portugal delete mode 100644 src/cctz/testdata/zoneinfo/ROC delete mode 100644 src/cctz/testdata/zoneinfo/ROK delete mode 100644 src/cctz/testdata/zoneinfo/Singapore delete mode 100644 src/cctz/testdata/zoneinfo/Turkey delete mode 100644 src/cctz/testdata/zoneinfo/UCT delete mode 100644 src/cctz/testdata/zoneinfo/US/Alaska delete mode 100644 src/cctz/testdata/zoneinfo/US/Aleutian delete mode 100644 src/cctz/testdata/zoneinfo/US/Arizona delete mode 100644 src/cctz/testdata/zoneinfo/US/Central delete mode 100644 src/cctz/testdata/zoneinfo/US/East-Indiana delete mode 100644 src/cctz/testdata/zoneinfo/US/Eastern delete mode 100644 src/cctz/testdata/zoneinfo/US/Hawaii delete mode 100644 src/cctz/testdata/zoneinfo/US/Indiana-Starke delete mode 100644 src/cctz/testdata/zoneinfo/US/Michigan delete mode 100644 src/cctz/testdata/zoneinfo/US/Mountain delete mode 100644 src/cctz/testdata/zoneinfo/US/Pacific delete mode 100644 src/cctz/testdata/zoneinfo/US/Samoa delete mode 100644 src/cctz/testdata/zoneinfo/UTC delete mode 100644 src/cctz/testdata/zoneinfo/Universal delete mode 100644 src/cctz/testdata/zoneinfo/W-SU delete mode 100644 src/cctz/testdata/zoneinfo/WET delete mode 100644 src/cctz/testdata/zoneinfo/Zulu delete mode 100644 src/cctz/testdata/zoneinfo/iso3166.tab delete mode 100644 src/cctz/testdata/zoneinfo/zone1970.tab delete mode 100644 src/cctz/testdata/zoneinfo/zonenow.tab diff --git a/HANDOFF_CCTZ_UPDATE.md b/HANDOFF_CCTZ_UPDATE.md deleted file mode 100644 index 42bb97538..000000000 --- a/HANDOFF_CCTZ_UPDATE.md +++ /dev/null @@ -1,72 +0,0 @@ -# Handoff: cctz vendor update in odbc - -## Goal completed so far -- Updated vendored cctz under src/cctz to latest upstream google/cctz. -- Traced original cctz import in this repo and identified local odbc-specific deltas. -- Verified package can be built and installed from source in this environment (with a vignette caveat noted below). - -## Historical trace -- Original cctz subtree import commit in this repo: - - 293ed5c2 Add src/cctz from upstream split commit 182b96ca6e09527e18fcd0a6ca3e156ea7997099 -- Upstream target used for update: - - 00fc77b843504f231f89c13eff86327c444094e8 (google/cctz master) - - Subject: Update zoneinfo files to 2026a (#339) - -## Commits created in this branch -- ade9b422 Update vendored cctz to upstream 00fc77b8 - - Includes the subtree update and conflict resolutions. -- 8fd5ec29 Squashed src/cctz changes from 182b96ca..00fc77b8 - - Subtree internal squash commit from git subtree pull. - -## Working tree status (not yet committed) -- Modified: src/cctz/Makefile - - Added Windows-specific object time_zone_name_win.o for static libcctz build. -- Untracked artifact: odbc_1.6.4.9000.tar.gz - -## Why src/cctz/Makefile changed after subtree update -- The upstream update introduced src/time_zone_name_win.cc. -- Windows link failed without it: - - undefined reference to cctz::GetWindowsLocalTimeZone[abi:cxx11]() -- Fix applied locally in src/cctz/Makefile: - - ifeq ($(OS),Windows_NT) - - CCTZ_OBJS += time_zone_name_win.o - - endif - -## Local odbc-specific cctz deltas retained -These differ from upstream on purpose: -- src/cctz/src/time_zone_fixed.cc - - Keeps Etc/GMT fixed-offset naming behavior used by odbc timestamp offset logic. -- src/cctz/src/time_zone_format.cc - - Retains historical odbc patches from earlier Windows/Mingw compatibility work. - -## Build/test evidence -- R CMD build . - - Failed only because Pandoc is missing for vignettes in this environment. -- R CMD build --no-build-vignettes . - - Succeeded and produced odbc_1.6.4.9000.tar.gz -- Source install validation via Rscript::install.packages(..., type='source', lib=temp) - - Succeeded after Makefile Windows object fix. - -## Exact commands used for successful package build/install checks -```bash -R CMD build --no-build-vignettes . -Rscript -e "install.packages('odbc_1.6.4.9000.tar.gz', repos=NULL, type='source', lib=Sys.getenv('TMPDIR'))" -``` - -## Suggested next steps on Linux machine -1. Pull this branch. -2. Commit remaining Makefile fix: - - git add src/cctz/Makefile - - git commit -m "cctz: include time_zone_name_win.o in Makefile" -3. Remove or ignore build artifact before push: - - rm odbc_1.6.4.9000.tar.gz -4. Run full build/check with Pandoc available: - - R CMD build . - - R CMD check odbc_1.6.4.9000.tar.gz -5. Push to fork: - - git push meztez HEAD - -## New chat bootstrap prompt -Copy/paste this into a new Copilot chat: - -"Continue from HANDOFF_CCTZ_UPDATE.md in repo root. We updated vendored src/cctz to google/cctz 00fc77b8 and committed ade9b422. There is one uncommitted fix in src/cctz/Makefile adding time_zone_name_win.o on Windows. Please verify current git status, commit that fix if present, run R CMD build and R CMD check on Linux, and prepare a concise PR summary of cctz update plus retained odbc-specific patches." diff --git a/src/cctz/.github/workflows/ci.yaml b/src/cctz/.github/workflows/ci.yaml deleted file mode 100644 index bf1f06ce2..000000000 --- a/src/cctz/.github/workflows/ci.yaml +++ /dev/null @@ -1,167 +0,0 @@ -name: ci - -on: - push: - pull_request: - -env: - BAZEL_CXXOPTS: -std=c++17 - USE_BAZEL_VERSION: 8.5.1 - -jobs: - Linux-GCC: - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Tests - run: > - bazel test ... - --build_tag_filters=-fuzztest - --copt=-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1 - --copt=-Werror - --cxxopt=-Wall - --cxxopt=-Wextra - --cxxopt=-Wcast-qual - --cxxopt=-Wconversion-null - --cxxopt=-Wformat-security - --cxxopt=-Wmissing-declarations - --cxxopt=-Wnon-virtual-dtor - --cxxopt=-Woverlength-strings - --cxxopt=-Wpointer-arith - --cxxopt=-Wundef - --cxxopt=-Wunused-local-typedefs - --cxxopt=-Wunused-result - --cxxopt=-Wvarargs - --cxxopt=-Wvla - --cxxopt=-Wwrite-strings - --cxxopt=-Wno-missing-declarations - --cxxopt=-Wno-undef - --features=external_include_paths - --keep_going - --show_timestamps - --test_env="TZDIR=${GITHUB_WORKSPACE}/testdata/zoneinfo" - --test_output=errors - --test_tag_filters=-benchmark,-fuzztest - - Linux-Clang: - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Tests - run: > - bazel test ... - --build_tag_filters=-fuzztest - --copt=-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1 - --copt=-Werror - --cxxopt=-Wall - --cxxopt=-Wextra - --cxxopt=-Wc++98-compat-extra-semi - --cxxopt=-Wcast-qual - --cxxopt=-Wconversion - --cxxopt=-Wdeprecated-pragma - --cxxopt=-Wfloat-overflow-conversion - --cxxopt=-Wfloat-zero-conversion - --cxxopt=-Wfor-loop-analysis - --cxxopt=-Wformat-security - --cxxopt=-Wgnu-redeclared-enum - --cxxopt=-Winfinite-recursion - --cxxopt=-Winvalid-constexpr - --cxxopt=-Wliteral-conversion - --cxxopt=-Wmissing-declarations - --cxxopt=-Woverlength-strings - --cxxopt=-Wpointer-arith - --cxxopt=-Wself-assign - --cxxopt=-Wshadow-all - --cxxopt=-Wshorten-64-to-32 - --cxxopt=-Wsign-conversion - --cxxopt=-Wstring-conversion - --cxxopt=-Wtautological-overlap-compare - --cxxopt=-Wtautological-unsigned-zero-compare - --cxxopt=-Wuninitialized - --cxxopt=-Wunreachable-code - --cxxopt=-Wunused-comparison - --cxxopt=-Wunused-local-typedefs - --cxxopt=-Wunused-result - --cxxopt=-Wvla - --cxxopt=-Wwrite-strings - --cxxopt=-Wno-unknown-warning-option - --cxxopt=-Wno-undef - --features=external_include_paths - --keep_going - --repo_env=CC=clang - --show_timestamps - --test_env="TZDIR=${GITHUB_WORKSPACE}/testdata/zoneinfo" - --test_output=errors - --test_tag_filters=-benchmark,-fuzztest - - Linux-FuzzTest: - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Configure Fuzztest - run: bazel run @fuzztest//bazel:setup_configs > fuzztest.bazelrc - - name: Fuzz - run: > - bazel --bazelrc=fuzztest.bazelrc test ... - --build_tag_filters=fuzztest - --config=fuzztest - --copt=-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1 - --define=absl=1 - --features=external_include_paths - --keep_going - --repo_env=CC=clang - --show_timestamps - --test_arg=--fuzz_for=30s - --test_env="TZDIR=${GITHUB_WORKSPACE}/testdata/zoneinfo" - --test_output=errors - --test_tag_filters=fuzztest - - macOS: - runs-on: macos-latest - steps: - - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Tests - run: > - bazel test ... - --build_tag_filters=-fuzztest - --cxxopt="-std=c++17" - --features=external_include_paths - --keep_going - --show_timestamps - --test_env="TZDIR=${GITHUB_WORKSPACE}/testdata/zoneinfo" - --test_output=errors - --test_tag_filters=-benchmark,-fuzztest - - Windows: - runs-on: windows-latest - steps: - - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Tests - run: > - bazel test ... - --build_tag_filters="-fuzztest" - --keep_going - --show_timestamps - --test_env="TZDIR=$env:GITHUB_WORKSPACE\testdata\zoneinfo" - --test_output=errors - --test_tag_filters="-benchmark,-fuzztest" diff --git a/src/cctz/.github/workflows/cifuzz.yml b/src/cctz/.github/workflows/cifuzz.yml deleted file mode 100644 index 56a2472cc..000000000 --- a/src/cctz/.github/workflows/cifuzz.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: CIFuzz -on: [pull_request] -jobs: - Fuzzing: - runs-on: ubuntu-latest - steps: - - name: Build Fuzzers - id: build - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master - with: - oss-fuzz-project-name: 'cctz' - dry-run: false - - name: Run Fuzzers - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master - with: - oss-fuzz-project-name: 'cctz' - fuzz-seconds: 300 - dry-run: false - - name: Upload Crash - uses: actions/upload-artifact@v4 - if: failure() && steps.build.outcome == 'success' - with: - name: artifacts - path: ./out/artifacts diff --git a/src/cctz/testdata/README.zoneinfo b/src/cctz/testdata/README.zoneinfo deleted file mode 100644 index 0fe558585..000000000 --- a/src/cctz/testdata/README.zoneinfo +++ /dev/null @@ -1,38 +0,0 @@ -testdata/zoneinfo contains time-zone data files that may be used with CCTZ. -Install them in a location referenced by the ${TZDIR} environment variable. -Symbolic and hard links have been eliminated for portability. - -On Linux systems the distribution's versions of these files can probably -already be found in the default ${TZDIR} location, /usr/share/zoneinfo. - -New versions can be generated using the following shell script. - - #!/bin/sh - - set -e - DESTDIR=$(mktemp -d) - trap "rm -fr ${DESTDIR}" 0 2 15 - ( - cd ${DESTDIR} - git clone https://github.com/eggert/tz.git - make --directory=tz \ - install DESTDIR=${DESTDIR} \ - DATAFORM=vanguard \ - TZDIR=/zoneinfo \ - REDO=posix_only \ - LOCALTIME=Factory \ - TZDATA_TEXT= \ - PACKRATDATA=backzone PACKRATLIST=zone.tab \ - ZONETABLES=zone1970.tab\ zonenow.tab - tar --create --dereference --hard-dereference --file tzfile.tar \ - --directory=tz tzfile.h - tar --create --dereference --hard-dereference --file zoneinfo.tar \ - --exclude=zoneinfo/posixrules zoneinfo \ - --directory=tz version - ) - tar --extract --directory src --file ${DESTDIR}/tzfile.tar - tar --extract --directory testdata --file ${DESTDIR}/zoneinfo.tar - exit 0 - -To run the CCTZ tests using the testdata/zoneinfo files, execute: - - bazel test --test_env=TZDIR=${PWD}/testdata/zoneinfo ... diff --git a/src/cctz/testdata/version b/src/cctz/testdata/version deleted file mode 100644 index 5d9126009..000000000 --- a/src/cctz/testdata/version +++ /dev/null @@ -1 +0,0 @@ -2026a diff --git a/src/cctz/testdata/zoneinfo/Africa/Abidjan b/src/cctz/testdata/zoneinfo/Africa/Abidjan deleted file mode 100644 index 8906e88c819d9ad3b794eb6356a240a74a95ffae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~>DeR?#{d8SSb#JG0gI1s2!lHia{&nh FE&z`x5Apy2 diff --git a/src/cctz/testdata/zoneinfo/Africa/Accra b/src/cctz/testdata/zoneinfo/Africa/Accra deleted file mode 100644 index c39ae382b5e8cf587c0fa38e729140aed60a222f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 700 zcmWHE%1kq2AP5+NDnJ+nLI`WI1uA0&Vv+wqFiUod35Z^JU`qp-{`BMnh+b?meF2!h znhEAF6+Nv0;xFAcw*W*h`}PkkzkK=yu>6V}Mqv4sl`LTSRlBx>`KzNl!TdF|UxC%H zwb=t!zphpeEWcj%16Y1TTp(C}!+&M4{3eHMVE(3uE5Q6MN?c&|TMpd;tKY_K3zpxu zgdZ%w{YfEMen+b_SbpcRZ(#ne^b=tI?iHF~^?N*igVpctj0MZ@)6xga@6Vb5mOsFq z1eQPOD+=ZxeES^CKdk2oR)6@sG+6yn{u;3S(G7lJ`C}h8faQ-*Yy!)lFysNtpDbYq z^G^vmfaOnzT7lJ{ZntRwh2y1%mn%T@?S;3&@^_q8OMv)yoB6={?I#~T<^KMYn1tfHhxd3yb75xAJ diff --git a/src/cctz/testdata/zoneinfo/Africa/Algiers b/src/cctz/testdata/zoneinfo/Africa/Algiers deleted file mode 100644 index 56a4dd2a19fac5cc1bb1951dedf3ae93e0b9e321..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 470 zcmWHE%1kq2AP5+NDnJ+nLI`V70xDwzVyXW?kbQEt3W%PV5a17@XS-K?0MplX3PALn zJrlw7+yfq9@p+y9!2J0Ow7~oY2}{BB!Ui5Ny+}_8OfRnT0nXvkI2VBE^OH;jK=g$!1_ls)u}BQezvQO^)_2959ZWwxcNr}IIcCELkbjvf z4uWZB=M!L>_xyE`FazIO7cif{A_~kG$cPjGF@(yT3qZ7Rno|Ra7KyI`i;MclGcYnU zp+Hs^AY^6*iGdhQ%&b8B?tpYL88WZ{?GRw(0Pz@j85m>~7zIHh3}QaMAq)XP9PSzn TB0?CPK@4Xgg9}LL8gc;uxvi~T diff --git a/src/cctz/testdata/zoneinfo/Africa/Asmara b/src/cctz/testdata/zoneinfo/Africa/Asmara deleted file mode 100644 index 194e98690fbbbc183de75088ea787c873040b44c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#V!{7F;QT_e2SjJKZRY{e2iAX@!N>$uqEZ4f l4oCu(s$?*5FfeEtF!1{LhA=pSunUlIbqrzP0us8$TmTfd9XbF2 diff --git a/src/cctz/testdata/zoneinfo/Africa/Asmera b/src/cctz/testdata/zoneinfo/Africa/Asmera deleted file mode 100644 index 194e98690fbbbc183de75088ea787c873040b44c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#V!{7F;QT_e2SjJKZRY{e2iAX@!N>$uqEZ4f l4oCu(s$?*5FfeEtF!1{LhA=pSunUlIbqrzP0us8$TmTfd9XbF2 diff --git a/src/cctz/testdata/zoneinfo/Africa/Bamako b/src/cctz/testdata/zoneinfo/Africa/Bamako deleted file mode 100644 index 3cb875fade2d5152ef734c9cdf2d6653c6e5ebe2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#p8r5F>De>}5WQ#8js_6@POx2ok%{sD{~rxN eB_P1^|NqAi3>-ebAq?(7tZQJ%zy)L&Z~*{nu^@#2 diff --git a/src/cctz/testdata/zoneinfo/Africa/Bangui b/src/cctz/testdata/zoneinfo/Africa/Bangui deleted file mode 100644 index 0021d2d7fd6174288e212222ed0328159881de03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~=~=A^P(UyTq?u2EfyKu+gdyB9gn4^f2O#lCXOkrREk{=jY YK%xvBKE5Fgx(0>}?m(IgNEmPd02-+k!vFvP diff --git a/src/cctz/testdata/zoneinfo/Africa/Blantyre b/src/cctz/testdata/zoneinfo/Africa/Blantyre deleted file mode 100644 index d7bca1e6032a8fd0f6bf73f9804037a376d51695..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#VxIp%FiA+q07OrpUi=C~ukrj)!pH5r0bS00!_gZ|T%(YMJJ2mCH46+nSoWw9<*%M#eTu88u6kiej;Z)WRWASVq`B z7zHWasI-e&mZ3rh<)v~NCMeVvk;_b%PQ~T2_dNXpe(a3x+3!5h3qw@r9VnEL1rLi^ z&^JBmg&Gk50gKhK<#ZOVF@ou40|>*2QzR`l;) zIpE$4g|PWf3H<()4(>a9FNZ#7OW2R+ZH^dt#J2?=>DOWZW7KJAw3C)hLU z8tj$E!G4inzmZ;eN6688kNKcydmcy6?vV zE_h3Isf93StJYwqx$UUdLNiUKfzx-U!14eW_8DRxoMAZ#XL8)&%%>dev+Q5t?DH+? zw-2&(ggJ`*HuQ?h-RKoJoaj}>8(~#LC3@9htB#oybwmaFf^56ajrD(D%zu-H{wAS_ sIwNAO?v83vUeh=NXaYu)452`D0tw+@&^k4 zy7H8O{Cfd-Jk0c-!sD0z$yI)Cz|I3j$X??EB?JFZDcz%OJ zl9UHF26QqbkBi{UT5yv2OXl!T$dCN1nTF4i+SPlRjju7i?~8(bbn(gHkF^JxmeZmjAN^b%b4ZjF{zQDl)N7fKSBY{hq_j=}r}!M;&0!b7 zn+NBCQ(dv()Mr`Xw5n!sntL{Kn@Nv;n`8#3$Mk^H^Fxt4f(__*#M!`~js_t!UV0OK zW`_lw`H;U~wrwH$?5+g#J2P)E?esUUd>3pq&^IUW9`PK&$M$diDUFi3@?dS_l zx50(=^t7xiMsLZlN55ZO%1or^fl}6x%%J8?r zmFe_6rn-y%SQI^v50_$IHI1GQrw{D7MbBz8-}mbJ%jhL7-*3r6&y(VJ=uhhDS>sEQ z1o@l_D@5wde)hOF|U*8*$}fI+>l4lGr{55KNGhBedAvP$fgi_ zHh08;n;+8i?BNmYpX~}n-;&1fQH!0P=T?lPKWCt4TVM_L+oI^%?$LldH1zCjYQ=u% zEid{Xty`Hb^z71J19z3t^WtLuU%06M8vP~T9Z8VS$k!VgG7=7W!+i{>eG`kThKC?6`KP80#k5!0HzPUF95lVBfF&m zOdrer0HV2H@PH@=o-lrOzTd$1*Y{{PJ?Ovl09JBAZ0C>HjKR~z{rFJGP7WVz<^=_ zIRglQG@k$?2Z&_gWnhp|U=;N64Pgj(1>xWj24^6{8N}cMvUCkWOdVfiJySgc9bZEO J5Up>_1pwDUjA#G= diff --git a/src/cctz/testdata/zoneinfo/Africa/Conakry b/src/cctz/testdata/zoneinfo/Africa/Conakry deleted file mode 100644 index c22c328b291f43ad3e7a70e16021bc35ed40fdab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#p8r5F>DlZU5WQ#8js_6@)-ebAq=_(h79gNnhQu6Z~*`Tlp7BK diff --git a/src/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam b/src/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam deleted file mode 100644 index b37c2b4464968a2d972b0cefff54310bfe2665c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 161 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#zW+e5ZSmzbAo|+e`U@cXy-?Z}Mkb(XDpx?p iX&ErEFfgdCVc_ub4PkI~3}MhVFfuV^-~uvrjky4T2_1a^ diff --git a/src/cctz/testdata/zoneinfo/Africa/Djibouti b/src/cctz/testdata/zoneinfo/Africa/Djibouti deleted file mode 100644 index e9bbc7ad9f3a4bbcea298b2e90dda7ffa96c5f3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@$)4fpnygRNVAp!1B;Ju2!pF*2m=?8 I&^6`)0ApPZ+5i9m diff --git a/src/cctz/testdata/zoneinfo/Africa/Douala b/src/cctz/testdata/zoneinfo/Africa/Douala deleted file mode 100644 index 65001f609d68d6efd398e1b8d54903deb9a49b34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~=~-(AP=Hecq?u2EfyKu+gdyB9gn6W>4=RD6J;C|fOoId?L-?z!9 z=_we}^RizTFC2}sp&KZb1 zqUPMH>HTWX^Q0b8Q@5f4oVe*1aAMCg@Rrw>sK;WR)q zz4_70=nvZXeI4weXQ5#Z`oao&7O%d5{bJ)N`p^Dc20j#JMSkucKyL}6=V8|Y^oKnT z^d;s;;F4x~S~r)Xw-z;{KPp8sQ|S5S1n-y9FnZehHeug3osGRRdn>qXfS%>KJJ6S( zre|gBKRB<p2vTB3H#OaH=wt7buq{3dE(e|@QEv>NXKrsB$RPfOoMA8 z-U8QT(X&?b7=3LFJx`64ZdzopX=dgAacsQP(BaiQ4e^mDj{e!Mz<~TjQwkKfkl>|vMbH;yt1P1)C9)ADt w%BS@ErzS;!^1nu>2^Q*T)hCVeJXa@zladW0a&5GTz_nJ)ep`7J8yP+OU-J-s*8l(j diff --git a/src/cctz/testdata/zoneinfo/Africa/Freetown b/src/cctz/testdata/zoneinfo/Africa/Freetown deleted file mode 100644 index 8431ed65b9a5e92f0516c62f24c5dc664a105114..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 324 zcmWHE%1kq2AP5+NDnJ+nLI`US1}b9(VzK`~5LLC}4Tzq)eSZ#!-evb-0+_y+m;j=8 zuaE}w_w1kY0L0(h=`R4H_boU9mfxS%1eQP0>U56E0m36LHc1qMzA1}y_dULW5OhG56w5C&&Q5C$^1fGk}jE&%F=A*BES diff --git a/src/cctz/testdata/zoneinfo/Africa/Harare b/src/cctz/testdata/zoneinfo/Africa/Harare deleted file mode 100644 index c4a502cfdecb5a3f831f8e375c49563f7a7e651d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iW=K=e-R@*mVKAS@Vn9nY+09MbT-~{G#G6aL=xfoQye6EM>V0rEbY+ydm z5gss~cmE48pKqx>SUvwr)&vG15NIm~%L{fq2lIu}mx1MlGfsl}B3{~HzNp7)FkehN z9;{wmqZiDV;F$!Lm*mI?^CjON1ItT&?0&!i1kxA0!F-vExnRER#yYTiiw0K(kbHu; yQ~(nr0m#h6z#zK>q+H8@5g3#*3JjbeHUqDZZwQ04V=#yaVQ>XvE+9kKhzkJma7J1H diff --git a/src/cctz/testdata/zoneinfo/Africa/Kampala b/src/cctz/testdata/zoneinfo/Africa/Kampala deleted file mode 100644 index 3021d844d9004a014759bd7562feab98fb47ba65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 182 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwk^exj@!fqH5WVHltP3Fe+T6AqAo_Wadk7;F xGtgMM6p*=E1|U7k8Vno^3~Fl__B-;Q0 diff --git a/src/cctz/testdata/zoneinfo/Africa/Khartoum b/src/cctz/testdata/zoneinfo/Africa/Khartoum deleted file mode 100644 index 3f8e44b8a6e171a0fde96736ed9d4fcde1bcd4a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 458 zcmWHE%1kq2AP5+NDnJ+nLI`V71}b9#V!{7Fux;@zkTwQ}dEyU16l0Z10ElL){rLby zGe@Ui0MRT7bq_!^tL+;wpUoiw%x9NZ0ITOva02r=8G^y`Tns8;KG(x`usrtzHZY&( z2oIRgyZ;54&$rYbte$@*YXSoh2(%T0c0XVM0_h9hV7|=7TrgjDV;xw%MT4sXNIvq% ylK>`00+5-BfkCbTq+H8@5g3#*3JjbeHUqDZZwQ04V=#yaVQ>XvE+9kKhzkHkp+^4z diff --git a/src/cctz/testdata/zoneinfo/Africa/Kigali b/src/cctz/testdata/zoneinfo/Africa/Kigali deleted file mode 100644 index b2eff5701e2340e51aac4685596bb37f9966996d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iWg?;~FTP(a22q*+FRfyKu+gu&S{gnOyMyBk$eIS TEIz&=4B?I;3|v4$*N_VUx;ql$ diff --git a/src/cctz/testdata/zoneinfo/Africa/Lubumbashi b/src/cctz/testdata/zoneinfo/Africa/Lubumbashi deleted file mode 100644 index 14e1ee1602e0fbb5d5199432309273cb141bf3c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%P~ofS0HPOlMSoxf%19mn$}sQ=Ft9K% Z$S5#y`1pn}ggb^XI0G>kkkB>a0stOe6h#04 diff --git a/src/cctz/testdata/zoneinfo/Africa/Lusaka b/src/cctz/testdata/zoneinfo/Africa/Lusaka deleted file mode 100644 index 18fcb1689fd6c46e70acbb86e74f0c51f9302a40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iW=<>WC{?lFfi~5 XFmU+zhA_ATakyg$0~e6cHRJ*SOiUFG diff --git a/src/cctz/testdata/zoneinfo/Africa/Maputo b/src/cctz/testdata/zoneinfo/Africa/Maputo deleted file mode 100644 index 581bb0e08b616a433d422ccb8f958cbebdae1770..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iW=>vXjYC?MAb(k!FEz~bW@!r<%}!oUS2 Hbd9(GSdtBU diff --git a/src/cctz/testdata/zoneinfo/Africa/Maseru b/src/cctz/testdata/zoneinfo/Africa/Maseru deleted file mode 100644 index 820d852155ef46868a0804a862c0f9fac44e33d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 157 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#&i_Erdf=7}VA<@cHDUAi{nmh^fsqNQgz*mp p!~g#uKY*1oFmNz1@Ch*R`1pn}=o%O@xC7~M#}EcCAfao>1pt!SAOZjY diff --git a/src/cctz/testdata/zoneinfo/Africa/Nouakchott b/src/cctz/testdata/zoneinfo/Africa/Nouakchott deleted file mode 100644 index faa6f324cbd026309645ff5f1d783f1e248ac99b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#p8r5F>Dk;85WQ#8js_6@?&*mMj7*IG|9|8G c83zO`K=ua)4jK%IO73>-ebAq?(79PSvxzy)L&Z~*|L=^B#& diff --git a/src/cctz/testdata/zoneinfo/Africa/Timbuktu b/src/cctz/testdata/zoneinfo/Africa/Timbuktu deleted file mode 100644 index 3cb875fade2d5152ef734c9cdf2d6653c6e5ebe2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#p8r5F>De>}5WQ#8js_6@POx2ok%{sD{~rxN eB_P1^|NqAi3>-ebAq?(7tZQJ%zy)L&Z~*{nu^@#2 diff --git a/src/cctz/testdata/zoneinfo/Africa/Tripoli b/src/cctz/testdata/zoneinfo/Africa/Tripoli deleted file mode 100644 index e0c89971aabea2c87842a9276b043d0fd946e34e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 431 zcmWHE%1kq2AP5+NDnJ+nLI`V704ievV!{7Fu<+AC6%c)Q_eKE_eNTC90*HQCaS6mo0*F>~*be3!`F#ZQja|&Z>P<|u9)RQn=FS9B41pmx8$fhW=9UH~MlfWC y(hweq1d4zV0|QSCNUe+lBQU)91Q<9$YzAH*-w+08*I*D4!r%(TTtGtChzkG|lxEie diff --git a/src/cctz/testdata/zoneinfo/Africa/Tunis b/src/cctz/testdata/zoneinfo/Africa/Tunis deleted file mode 100644 index ca324cb4cd26cc29529faaee4c0465ae0cecc8f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 449 zcmWHE%1kq2AP5+NDnJ+nLI`V70xDwxV!{7F5a}lT1w>Cw2=E8d$E-RYfav29^Af=H zZ6z@O)T0nEeR^%?2ax!g=iUM!`s_;a31Iq=7z3C-vjHrAZjmXNe}0k)n17-3FFmeE0F2KO+;~T;d0L0F&!5|`pfeT3J8gc;ufb)m! diff --git a/src/cctz/testdata/zoneinfo/Africa/Windhoek b/src/cctz/testdata/zoneinfo/Africa/Windhoek deleted file mode 100644 index 0edc52b9b783827a8ac1090fe350bfe13977f745..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 638 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1uA0$V)6e#kX!9t0iv7S&S!w=GwXU9K=j#p`2`^J z)Yz6k0MWWV#}h!bUZ#uyh}N%t38EMbJpO_ChUu&gAij~t12Es%?KzllBKT(lNZeHI zB$#jd@gA6O&bAuNH@|oQ%(r;f3+7vHTm(2x8 z?W39nKn#cc05IRtDizFk@`nVRvy?lS@1idPmUsE33Ff=;eFO8|ZgGS8?mvVYKms0z z)hB>x&+A_rK(yClPB7nl`!z7%r|C7A?>l`5nD3W#7R>iAp9SUzIIRcs0~59bbu%yo zDNO|PgB@mq`61lv1VD^Xg=#QA^z{TVKb#>J%nv_Z1m;IPum|%aSBD5NGBGo;vXBTF z7z8*#CWuNfurM&lC@^p_FlZSt0!cmrMt-n}u#ayDgSLU8u>nJ{V{iyVxMK)|GZ1qD I30)&D0E>-r5C8xG diff --git a/src/cctz/testdata/zoneinfo/America/Adak b/src/cctz/testdata/zoneinfo/America/Adak deleted file mode 100644 index b1497bda631efdcb6635ffb6b0ee6f7da9e2a280..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 969 zcmb8sT}V@57zgloA38U!R&8r8EjOz%UGtnxm-gk^nrPAL*iJ>eFc*Db5NSdbO?olJ9< z&oAKe*9H7uQJ9seKTplU^B)x81tZg#w_eV{3p3;JqLbI)#XZBYZO>`gzBvs$T2k;5 zUpMUZ45*B+N^=x;>G#5}dQT1YU0-B)=}ag~uF41D>Ipl%?5+)7eq$D{Io>YuG3FjD zz@A+`xc2aOf%+@LmrF*ScM_}n_@qHs_9%rc^-Clg(P5W=cv4)2# z_1j_@xb5pFNvAg$^(CeM`b_4s|N9ubJ;Ru$CHK*JKxRfw>+jZ;;jBQ%irPjeb86aP yudW((<<_{uwk7!9&9|(uD6gY2g+)4e(ZLG~FGPV?{&*-53<&o~)yl0u(`-5CoUZHL{FCdS_s%U>Hqtf9i&gJ(z=X374+=r7m(tA9> zmJJ=BphJ;Z{*weB6Zol8c{EQizNCEaiV~%q8*a=}&bxjjk-I|@6y>Ey$7IUt zojnr$kKKyMlyq0CVEv#6F6a+usBh?Q$x<%tsDzD*8#ejPu<80y*kYZBE$LaAk2B%x z3wXtc9NrhbnUko$GMk21P37R#cV}ekTgTGyn&C-!?U_-yxOW7$b@s#dy-9doFb=Qx z9)vfP_hlH5jh1@Yq3?hlH8v~t9p6H5$tQP;T$-{(jK(41EofxYkE!qxLhxaP@I*!SvMijT3a zw*uFL;|t+iz28v6Jy=`mF6Y zxbPF+{#?NPj@j4n&WyI-U5}^W-8Z!THjj_Pa-X(e_f0T6k0)xKL_^-!gG5_Dg*t6e^sp`NW?k;9f)uE)$jJt^UyO@1%{2b<|ou4Qn8cwiID%yCVwDC%yJ4p7$>coI3`C@**=ocm7FFwuL-T(jq diff --git a/src/cctz/testdata/zoneinfo/America/Anguilla b/src/cctz/testdata/zoneinfo/America/Anguilla deleted file mode 100644 index d0577350733f631c79ff70f6808f47f4178413cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~+1ylt@&ErL4;UE!|37|!fyKu+guyX5 LgnHq&@0t^iQ|L@$u b!1Dk9@dFGTKE5FguE8M;jzG)>Buuyf8A=^t diff --git a/src/cctz/testdata/zoneinfo/America/Araguaina b/src/cctz/testdata/zoneinfo/America/Araguaina deleted file mode 100644 index f66c9f79d6cd4790c54d01286660f8ea0807f1c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 592 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1}b9)VxIp%Fl|+d0f^qg@A&{s|8-aZqIZ5Y0gLat zSE2yo-?CT-=HGh#3rydUe7FH5erIPSSpM#BQLy;E+4sQw`*&x7`42*j!Tc}N|AWku>3EsOJMcCR{Q|V|9-;;mjBaTy8!5R2HBH+ z1|V9l;`#y*Ex*8Y1Bg~IKED7&D>i0=<(0TkfceT10$_RNM+FKXc~$dIV7}^=<6yo) zLnT`31TlMRJ<*iTr2g}>!^MU!cM<#;h?fgD~`2o$TV1A&2 f0VB)*|5q0kJUymkp4#Gv)#Sd3?{w diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires b/src/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires deleted file mode 100644 index d6f999b8605c9f73653a16e2ddbd5a49b96c0f56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcma)&O(?@*9LJwA%vxDdBx$mxO=`_%!ZhvRCA+X9CrU~waxf+2;-pquN?BvOI4E=Q z(l$1R;h@z>%3(!rgy!GO%j0>zE^a(ezrN4s|M@- z*%VN=MweFGd3xp@TAo`I9cG@}#iu@=JEacr&cz74zi=|lzxy}6@PX6@d~o3ke)swg zes5d~9|{z~hkG30eU}S-P#-}*G8IGrutb1A>J`HueQDsMO-A@=VjX-k73ro-j?Ke+k8AF%Hd_6<<3p8Qtkw+j4xo-(-^p-EKkdO z6|ruxnmmKmzB;fb5eHW;b}3km7=>fpuMKIC&Gy`%yqSh?NqfMp!9Im3BlDj-OZ;nR z;!NqOo)AhSF(Rfk8YU7-FJmGZrMC%@oS%uT-D)EiHdR_Zn`$;XB5h!&#%k#|fdER> diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/Catamarca b/src/cctz/testdata/zoneinfo/America/Argentina/Catamarca deleted file mode 100644 index 1dcc8d85434c9d016f170cb2f16811ebef327b77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcma)&-7AAp9LLYzm|0m-B#CTkL#^3Nm>%t7CA(oou3ShdMJ`MUxpAddT1stsyH%SD zFWJ}_h6}AWNx4{&J3{j`ug5uGe*ow7d%oxM`~1$ub6mZH119q4lCTM0e7XL}P#r@(W&^eo78r`!YHNsYko7EeZbe|K{YK9t>n4=-H7?_J-) z?~kkCBcT%bXs-u+;P-JF!i*jd#X&8+HKnTV=|om%Tv EKU&60&j0`b diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia b/src/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia deleted file mode 100644 index 1dcc8d85434c9d016f170cb2f16811ebef327b77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcma)&-7AAp9LLYzm|0m-B#CTkL#^3Nm>%t7CA(oou3ShdMJ`MUxpAddT1stsyH%SD zFWJ}_h6}AWNx4{&J3{j`ug5uGe*ow7d%oxM`~1$ub6mZH119q4lCTM0e7XL}P#r@(W&^eo78r`!YHNsYko7EeZbe|K{YK9t>n4=-H7?_J-) z?~kkCBcT%bXs-u+;P-JF!i*jd#X&8+HKnTV=|om%Tv EKU&60&j0`b diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/Cordoba b/src/cctz/testdata/zoneinfo/America/Argentina/Cordoba deleted file mode 100644 index 35a52e53d123b5ef5d293b3af19046630f02bb66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcma)&-7AAp9LLXIFiTlcB#CUTO=`_%^47EqFWC(%+7%_G6uB@ZhCZpmC= zZDV5?F7(tUDHkhpN76ja>v7I^f54p6@A>{d=kq%k&v7`128|@+lCTM0d^s{-X<}p9 ztO_YxW6RrKo*N5p1JC`*E-TN2l1rTX%G_XId=%baG!^FFzqbh=NbSN07jNMY?;hcg zCY11@KrwvS=>{LKtbk7%BAAa%3z$DG72(hN0YPeo(!A4wPdXRH?f zD`JNK4tB%;Y^C4pci9Z4^Cl~MTavTc;pM4NkF4>m^z4DvDi2s=c>`-+$HCf)d;_1; z3cX+*p;pd1Z#`I_h{0Da^_25-i+GOvbs;^n)s>sh`x*GQ&kb;Uu)ka)mHl&P$h(HLwa!R9NqM-CfkmOPNkdUZ&Px3nL4q{_fZ7{K_VPz!BM%FdgDE|PnyG!l> diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/Jujuy b/src/cctz/testdata/zoneinfo/America/Argentina/Jujuy deleted file mode 100644 index b275f27c0287415674d2ccc850c3d612f4a45b0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 690 zcma)&-7AAp9LLYtn6--)MUoU6lUjQ*d28B*lHIUUu3ShdMJ`Z6Zd^#Mw3H%mw_+~F z@;aLtF4k%!aj}p)OPZ&7Jg# zqbm60{Q`JjmlJ%lv;_9o2ha~pM9@DilHh~ga`@n{4nEXufe*#Dz~@sg_)GgL`j_!( z_^_SBhutsWXr&qc%GLu;G%Dc}%M$oq(GQjk8Y}&e^t_CIGS>#53`OBT5+m@R(Hi)# zfEoV#pacGABlTXti)JvNHCe^mvh4L%H>I*{V1=^O|Js0OV+q=6g?9ZbT4H`Pmzh9{rwRkaU zT%7({xs-Bg%4McpA8wH-H!@FU%FS#Sc=NIkek*;%NBb?$GQ2ms2ERRh4Zm}955GI4 zhu`yN!28-=;QhHd@Ij3qeg9|>{lhE;{-{F(fAnL54>Z`|1L0Nh$+#Q-%(006+0z94 zg@eOi$dBNV(F%WQ?*vEcbnuaR1^lM%0V@`RMBk%4%%dMowZlgPA^7*mApA$D68_U~ zh5y=ah5ufO{jZ-{E0|AKNaEkJgyklgQkUPmK$++Efb$J*aDnX=T<|;qF3L?YQ?KaU z11>Hsl!%S&1$(1hjlC%x0+-CR<&d{2$1-Kro(U;=V}0o=$w&Lf!9?sEZ^v>}aq53w zttNKk5Na(Y=lf2^IQIvchVy`r={Ua%s**Xs3#$zD%#xcOPG%QVX08xZF2=(2wc@G1 GT>lG4153pK diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/Mendoza b/src/cctz/testdata/zoneinfo/America/Argentina/Mendoza deleted file mode 100644 index 691c56978a033586e3302db2ef600e4b0ffd6366..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcma))-7AAp9LLYtnB`(cc}Y?TlhS6Um>%tdWH&5oS1v?KkqeZ!+_+LJEv2^RlKEL0^b9x-k-fkoLbE#MdFTNaqk62k- z3ad=Y)}Uuy&2wqiRmpR6v{m4_m3uDo+|GA_x331^ce2JMe!sJ^48I#&gWsFGf#1J< zgg+S3!TWc!;U%XFeCYLpk7{M~%M&5=ALl9XC!K2elY{|2&|rZNL{`CPQ*QX6eG&b^ zmudJ*JB7a#pTXfWGyIjU3mmm-;iEnU{I2N(D@MJ*zejoUp+A;kgO3Hm@E_4(_;|P) z{!=!?f9dUMS3^5*zyK0ejNgr+3 zjbZGtRwF5g6}b_bxB2^cp6@PhJWs#A&*%MopTqlD`-cW~*r9e5Bn7A4zV2&t{$QQOhd&(Z@OX zn1#Z}ybs`n+5mrHwt-V7Ief}3f?s9BU{R+O`2UFaZuHYdX83d@0soe=!@nmQ;XlF# z_|HHO{MUNsy}p+XU^=fC*xQm^Pp6lsyn1AXXO+_ju2wq1HO3ck&C@uzwz5#md$sXC zu$nxB)!t^XCYb=&E%jEg8ZnBexZf1iAO(M>FI?t_xbLv%;d{r;Oob#X`=47T{k5}Y zS&S$RstBPp94AsrBOxNE^fE3fp!7B=QSvh>=(1RenN7V`&!&Nmjwo8$sjWfr1Hu4G Av;Y7A diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/Salta b/src/cctz/testdata/zoneinfo/America/Argentina/Salta deleted file mode 100644 index 58863e0436d16ef8ff8ba3d96b452086e4ae8ff5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 690 zcma)&-7AAp9LLXN8?#nc6iFh}+N9QOCT~rkyA_WM zta%$V54%{aO;Rpa~iotD7_YW`pdmwe_{kaP&^gn-vfJ_@Q3ML_@l*J_~W}r z_>&0@{OMr{e9+?spRKHb&znN%ho)obUzEx4;XWmNIAemB+U)RBatC}h>w}ND*3pl= z%)v)p6h10GgX2aUe8SlePPM4vQ>!xgT{Q%jEjkDPANgq&{dA!dJ}t%JKT_lHpYeM5 zuaFJ?`=}fKXDj<&nPnT8&RZSqZAso{hsaZ{A70~G<=X@6bv|&l{S93GItDgW7MOX@ z5bFgS33YHbij81XG7ev})KkH~+vQ8#Z#Xp}+sE^>c|TJjG>8R tl!jtNNvRYhYD#Znf|k;Uq@d$xqV06KiIYvO*~+GljfH5M*{QWo^9#6+N67#H diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/San_Juan b/src/cctz/testdata/zoneinfo/America/Argentina/San_Juan deleted file mode 100644 index 7eba33c1c5b13cbd9b7566f450d524a45cf8b65e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 717 zcma)&-z$Sr7{||SW0ta_ND}$ENv$!HU%lFelHIUUu3ShdMJ`Z6Zd|FAmQpl7Zk5-? z(2R{?C|ZrAT&&0)p?RC1$9cZ~0G`v+_k5nu^Ip8i+1cA;VSkoNY*14<|Nf*=tR;)i z0EAkBT=75MGMI=p}O3V!GM4t{q; z4>uPR@P}O*_``1#e7MO5AC9eok0;&mr;a7;pFU2( zpF24Gx%>c*8m;gb_HJ;zK?fiADBxFZA6T&%B>Era-h=%_h8;c;j>5mihvDC&)$ku7 zEBvRw9sX0$gj!3Z$?T#l%vGW*MO&D@Ufdch F^*=7fOT_>H diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/San_Luis b/src/cctz/testdata/zoneinfo/America/Argentina/San_Luis deleted file mode 100644 index 0a81cbddfa2813041472b716baa91c35a8451379..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 717 zcma)&-7AAp9LLXW53_c$qP*tDG?ZGinZkOsi?Qs6UC5OSDW%8-N|YN{YQ=Iz8*-;i z-qtpZ#|)uqBzKD3Q8Z8UdYtq12k<-n`kv4E{LaNW?v9>r6Zx|gY=Sp0_up4+Y%G&? zE@d?^yRy!6Vaj9VxjE7*^4uys4)6??c)-ESe)v${Xq2CaHWuN-=~ej1%r*S>%{~0i zum*lNoDU!E@PPN`=D_=P66U3`1m+KlW%yX93O@E-2_J8?!pCn{z(?a=_!HMW=1-m` z;LlwY{ygvqPF7gpFYR66RD&8m<&(j$LN8c0=|uh>`N4hzSN!Fq>z*DX7^YbkAZh-YVFSyM50xtVn0vif`?-|Y{ zoR>R_qJ))IJ_Oh9RwBia580?RirhPfvcZn&Pd_->3T}EH6gfAqnZeGBc2SX`{O1x> ze6e9cDP#yLeodfs@01Wqr36t?8jlh+rB?}smeRXhg^uruw#DTpcGgu!GwW*BCZefl IJ6pBp2Vy!-;{X5v diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/Tucuman b/src/cctz/testdata/zoneinfo/America/Argentina/Tucuman deleted file mode 100644 index 10556d5d856a0f33afd8da2b07a2005e7be80fb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 726 zcmWHE%1kq2AP5+NDnJ+nLI`WI2P$I&Vv+wqP&8-V5)i#;QojL+-c}vt0HU``o!kJT zcgXdF`8%!@faQ0I*B$_g@7lT;EWi85MzH*zY1hH>dv87g%kQh;0?Y5;EdiE45Y-Rn zADlZE%s*s(7_9zq-374vBQoE>@<$U`!171`X@TXBJDP*#k3U!s=AUSs0+v7JyAZ7Y z)VnsY{5jwMVEJSmlVELb4%E9u#E}Mbne;+ml%m3LE43_`91`=NX=9q%{|9eavfMLtPzSwI6 zh~`kqUjU+&r)&lDRRpGh`Ksohz X!5N5k4NQR87>JD+xNLwdJ7X>YQUg#g diff --git a/src/cctz/testdata/zoneinfo/America/Argentina/Ushuaia b/src/cctz/testdata/zoneinfo/America/Argentina/Ushuaia deleted file mode 100644 index e0317502769271ad0c038493df2ad2b90ec402d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcma)&Pbh<79LJx{#*DI}ND|r7Cbc#*VS2U0O6I_doE)T-A_tU^iyYKSODP(5Rkj1> z@5V43v>Hh{tjLYfyv@Hop6Bc0HqX#7vE`ks1LgTiV3s~!|1?yr_aK(Ik39Avac!K*i0Uc7(hBNWqb~{lbk*57~%VmFd znq10=(m;X`N<$GMqcj{O3QDgcl59%vViFZUlk8@@gIL*A>Z{lo*%*kjo}C(u${*+O BOAY`4 diff --git a/src/cctz/testdata/zoneinfo/America/Aruba b/src/cctz/testdata/zoneinfo/America/Aruba deleted file mode 100644 index 6158ca50eb2bac7d57c5b3db88726c36dcb17899..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$V!r=CFj-FD0z`kC@y3IZ>Hq(I9t;fs{~y@F f!1Dk9@dFH8KE5Fgx&|i31`LkDAq-qV!h{O|LyH|x diff --git a/src/cctz/testdata/zoneinfo/America/Asuncion b/src/cctz/testdata/zoneinfo/America/Asuncion deleted file mode 100644 index f056047f058ee5983f113c9129cb7e3e87633de6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1085 zcmcK0-Aj{E90%~TshM-?)O1cWdtYgr&)k@^nLbO+Rde%YzO5HE-$87GM0GVH5+ZVx zWL=37bYbOEvb-oCyXl2$gIR$=Y)N0I&LubAEiz_xHPa=5%#;>5W&2S%^E~U(D`6k&GJn6odhGCPSpM)Y9Cvn= zWAE|TH9YGHE*)}3f3v`x*j553)eiB@$%kITn@lP=MZJRkRFzF&xiTgfxpLWqJndU6 za@D6v2=cA&3&^*%1d(sAiH3KSHo!X#X3X!h znBmWrKBNu&|d$p8O~5XDzvLU2cl;tPRn e6vg)eB4@WmZmVz-3q2anK#!it3h7;>m;D1;>)C<; diff --git a/src/cctz/testdata/zoneinfo/America/Atikokan b/src/cctz/testdata/zoneinfo/America/Atikokan deleted file mode 100644 index c82871528308b02a45d17b3973c108c20e561c40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I&Vu}AiQ1q@P1w_x=v9JL|&)@a407Reo5uN~| zPj~zSi(gXy0v5lN$oYYZk%^I+h4ugcRWb|=|NrmYz{v9d|LO${9AGvNm=pk!3?e?h ZAq>tgKpYIj;XoV^!r%&Ia{&ocE&%lkOIiQ` diff --git a/src/cctz/testdata/zoneinfo/America/Atka b/src/cctz/testdata/zoneinfo/America/Atka deleted file mode 100644 index b1497bda631efdcb6635ffb6b0ee6f7da9e2a280..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 969 zcmb8sT}V@57zgloA38U!R&8r8EjOz%UGtnxm-gk^nrPAL*iJ>eFc*Db5NSdbO?olJ9< z&oAKe*9H7uQJ9seKTplU^B)x81tZg#w_eV{3p3;JqLbI)#XZBYZO>`gzBvs$T2k;5 zUpMUZ45*B+N^=x;>G#5}dQT1YU0-B)=}ag~uF41D>Ipl%?5+)7eq$D{Io>YuG3FjD zz@A+`xc2aOf%+@LmrF*ScM_}n_@qHs_9%rc^-Clg(P5W=cv4)2# z_1j_@xb5pFNvAg$^(CeM`b_4s|N9ubJ;Ru$CHK*JKxRfw>+jZ;;jBQ%irPjeb86aP yudW((<<_{uwk7!9&9|(uD6gY2g+)4e(ZLG~FGPV?{&*-53<&HqU9HuZUE5=#^)D+XvM}%u)GrY2{2zdLI5nU{HQmUT?v4Fkjzo8JKU- zPzmN6%KC!U8-*)?^&7Kgf#ppsLcsDSKMsQVW(x9PzS;QcC>=!E$=@D z%Ukv9faR@E{0Gb1 diff --git a/src/cctz/testdata/zoneinfo/America/Bahia_Banderas b/src/cctz/testdata/zoneinfo/America/Bahia_Banderas deleted file mode 100644 index 882400bd33bdc23fc75b092a01ea935b02431715..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 700 zcmajXO(?@*90%~{KUg#iMu%3!HO+D{)mdUNoZvV zbnS&+XILJ879&GWi=FvYt%AccB^>@)jj;F2w^=)#C1n#HIZMTSmYZd{&IwnTVsK?a z8?013!c~byaCP<WSDxM}(tR(t$z z_R!oFgf-(XSX;UYw`fP;*3<=9m#>C(F`t}{5xqDM*5A*=?avapBW#8ZSLqSfXWTAi zK{^kkaMxlA+`WDW_c#jN?7=j32KTCyVcy_}%{lL|rNjmIkt?`Ab7zK*k^ZM+cp$n2 zTQ7X@;H?cF+CO4#WcZ{Bwyk;Lk*!?VJ~;}++gI1v6m+rT1G8RT2cz7^cS*pNfsf(S128?M=K_f4pUwd03zX!6`GRGSzuj!5Hf>F5bOW{6VeO}|NmdTz{v9d|M3G19RL5HJHg1~;~T=@=mNySAq=_( N#>NH=TtKD?7XY7HQF#CW diff --git a/src/cctz/testdata/zoneinfo/America/Belem b/src/cctz/testdata/zoneinfo/America/Belem deleted file mode 100644 index e0d7653c64c1e3b3e546d4c5e7644865b237f128..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%Fl|*y35edo@A&{s|8-aZqIZ5YF#yrK z?v*Hj=vx-+!2DaUe}U;ck`Fh4#P95k1k2z3EeaODH~Su#fB)_*F#kb_F_`~l`hT$c zudH!k{HqU9HuZUE5=#^)D+XvM}%u)GrYi3LoIc;Ns4mwFf&{{MgcfRW|@|Em`m XIDC9V7<3JcfY_LU%LYi=8FK*u>AtJ- diff --git a/src/cctz/testdata/zoneinfo/America/Belize b/src/cctz/testdata/zoneinfo/America/Belize deleted file mode 100644 index bfc19f4e587cadf6a2b05781860c21dccdf02961..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1045 zcmb8u|4S2b7zgm(=31^8At91PEQwMo#v&_%EM^c=aMj2w$j${){ZMLDLV^7t1yN8+ zl>X4vlx1rS*z4lW0+dkJ@0=&e2(Yy@H*bl=YBf#iL+%! z#iGT?32G|y;wu(8woL9dl3aBqK_^YCb+<^fasOd~W>fWAxOwY&j{LYpf?ISf+`1j+s1!9cd=z~SLzzvZ8!jThwC}YxmV@E?*6N=C$SQKVLb`=1ao=H^;Q?aFFh;Z zzEgU*|KSuoP@sYbtKP#yo7M@m_loO)hnF+3cV`{!jYVOfzFnl8&*z2x%stp|v%zm7 z7vZ;ehdIiP>|GBBa+2lb!0QT@=4kF5j~Oh&o{&Bc3!cqzFy04`)$8C;U<~(+S0&(2 zu3mV83&7#pN3ghWhNF8UmDl0V`j2q*hz0(_bi$LyLU=NAAC6_0^0XHlyaIonH^K3y z3`v*$qy&vVK|jz zhf{$Cj`n6%ci>sq1pFs@0iLTJfagbU^ORetZ06|y&{#q|rso4oGpn=$&a&@dmCO5yEoedy!egs;9`9F?d2Fw5AdH`1cYb6_4{`VUZu>7Cy?hPP+%ATC# z0HWn8o`U)E3!D#t_zK2%!F|xB>&i|NmDnFtPyI2N*bfd_x#?4UB=Fw7UQR diff --git a/src/cctz/testdata/zoneinfo/America/Bogota b/src/cctz/testdata/zoneinfo/America/Bogota deleted file mode 100644 index 85b903333eb6325aa8343f6e9aee38447495303f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 179 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwf&V}dH^<}yh@KGI^|Hq*3RTWfAp)7dYpO)VS^J7IZI2&ULgR#bFRoze=g zJmgI!)2$$ksI+d1K~16v`f;&tvcP`a6c!N`C{1^IpYK25P4D5^_xU{MeP9$`q?DRJoyKECFG#4`zOnYJu&N^(B$-1@z zg;F1xl_|69(y+lh2^;Pe!A3C&8*h(cU-)?qUhpxF_oj)*e4DX_$sTyo!#JFKGlu)( zl^%F;-#K{6$pi4xu68(YZv$-JUJvI7obWQ|YS>Z|l4($26kw~?0b75SDKxizHp2E) z4qQ0?4PHJr1sBC%!Ntc5vA^Q%UASbo3YQ*y$>^-C`UJ1qaR)9lKY<-C1$JaUpm7RE zVCUpG?3$9`HIJ^t?l;{s4b~2whduY3;qud+uy>#m_I37(bkBb@AFgQVfGeA4;3`KW zyw3j)t~R*f8rwAAVyxzi2@a$u;M!+D;Pvkl@P<)Ap=M(u3UBKF4sRYj1J@mT4R7fk zlxeVa=P10b{S+K5zXXSZ`{B^{5y^+8l9^4%PdD#Z^bkw w{POQQs<1rtmZq@8B0*leBo=Pr72!oap9#FF=8ZdC;qiOC?y%42@p-($KY$7DK>z>% diff --git a/src/cctz/testdata/zoneinfo/America/Buenos_Aires b/src/cctz/testdata/zoneinfo/America/Buenos_Aires deleted file mode 100644 index d6f999b8605c9f73653a16e2ddbd5a49b96c0f56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcma)&O(?@*9LJwA%vxDdBx$mxO=`_%!ZhvRCA+X9CrU~waxf+2;-pquN?BvOI4E=Q z(l$1R;h@z>%3(!rgy!GO%j0>zE^a(ezrN4s|M@- z*%VN=MweFGd3xp@TAo`I9cG@}#iu@=JEacr&cz74zi=|lzxy}6@PX6@d~o3ke)swg zes5d~9|{z~hkG30eU}S-P#-}*G8IGrutb1A>J`HueQDsMO-A@=VjX-k73ro-j?Ke+k8AF%Hd_6<<3p8Qtkw+j4xo-(-^p-EKkdO z6|ruxnmmKmzB;fb5eHW;b}3km7=>fpuMKIC&Gy`%yqSh?NqfMp!9Im3BlDj-OZ;nR z;!NqOo)AhSF(Rfk8YU7-FJmGZrMC%@oS%uT-D)EiHdR_Zn`$;XB5h!&#%k#|fdER> diff --git a/src/cctz/testdata/zoneinfo/America/Cambridge_Bay b/src/cctz/testdata/zoneinfo/America/Cambridge_Bay deleted file mode 100644 index 1092f4b61a1b203f7feabb586b51085bb72602dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 883 zcmbWwOGs2<6bJBcbezX^s+-U8m7|u^jN|pr`0k;WGil+_U^k*RBKSZzib3F_y1o{! zyyz;#aB3AnPP7ssmB@u=3tOe6(LN7`A<%=GTm!ndyViPKM!gZ^lJx#20<=`N3W|uDcnIZ)<`R9@fB# zw{O8o4neiP0NFT#!|8Mx2t znSitJ>u^r{7e;Zh_!oTX&O10a@e}NHYq0ZZ4UJ3af?cb#uzOR1^FF?YJ>NQ28sxtm zfTa)haKW=ySRN^Yy{-Ks?fD)j!G$#~a8dm}TzI1P|FYI zcc{5y{2fA_`-8o!D^qxWEh1>tT%Q_)D~7h=%F*X=RmWHOM*pZvgPV6FaCOsD*k3RV z2mB3i;O}QK+7K0OJl)R}V>TT-rEfB(>u<*mM*LfJeN1CE^rEg$MhpqmGduMxJztht m@PWdDA)fbm`W049$@>6Lfe%ah&=V|_e3I-5dcBfYl7;`ZnXHrm diff --git a/src/cctz/testdata/zoneinfo/America/Campo_Grande b/src/cctz/testdata/zoneinfo/America/Campo_Grande deleted file mode 100644 index 6855e4e9fe021cbbc392c76e1effef86dd53510c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 952 zcmcJ~-%C?r7zgloT0@o=K@eiI*$7*?d2|O|%k1dTWx3VrG^gvLA7F`6P*KuFSP}+a z1Sb8477=7uyAV<-c%eWBl2Y2ma6b^dPzE(99b0yKpYK25mCxZl51;q@-QcJlU7giz z-O-5#9U680p9DoMUz|cs%;WdBW!hug+J0fLdBe2F(~S!4iTFKLGA zJ@Q;?2lBszgJJqkW8|emyR>%^-W_srvdJEU%kJJ%$a}W@fX#tYPBt&xk!bIAFpfPt z2bY%_6>|BfH2M~%!It4?$oDUoaLNyKE66MOXXMt-Z^&(-w{T_iC@l32z*WW|`qgbV z&cxXDy~t(91%)hUrr{cs6|R}SiGJjsCp%eL`ND=b7tGnRCUtS@v z_x^*A3>CtPEeSUa=;6klYZ4RV^3A}m)dbw+InU|7DVamxy?q$D`@$^PpK6XP?vk)OJF20qO!u7@^Wxs!~nN1#NdtxDL5Fv!kL(}m%mDRx($0YZEA`!O`Dt1ZPK(!&I(#RDzi#< Nab#ww6YqN2@E`026-EF6 diff --git a/src/cctz/testdata/zoneinfo/America/Cancun b/src/cctz/testdata/zoneinfo/America/Cancun deleted file mode 100644 index 3110cdfd6e6f4ccd889447657dff43560d5aaee0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 538 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1}b9(Vv+wquyot41R$G1tm_$wVvs05a{)vfrk8;z z2BTt*0uXKN9s!~lOoCp4`KIdHA3%K5BMb>3+RW$-Slpal2E=8skbVJ{w|Mps%(wh~ z3e30q%F+N5u-Y?PnK&`40I9zfHng0J@w}OG;|Nqqs7+C)Q-?@Q-14J_N{QrOa0Hc79ZwP~Pa0r7d5Ieg7X&~kT Ha!k1Z4u)y) diff --git a/src/cctz/testdata/zoneinfo/America/Caracas b/src/cctz/testdata/zoneinfo/America/Caracas deleted file mode 100644 index 8dbe6ff74127e02577fdccd694af5a61580369e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190 zcmWHE%1kq2AP5+NDnJ+nLI`VN1uA0!Vxj*)kl8Nf0HP<$>DYkiZ!_L_fXs1^o>Ty$ z!&O%nFfuVSG5`O6(1C#gNV+hv{QrMo2Ls3d|Hlt7@cH%t7CA(oou3ShdMJ`MUxpAddT1stsyH%SD zFWJ}_h6}AWNx4{&J3{j`ug5uGe*ow7d%oxM`~1$ub6mZH119q4lCTM0e7XL}P#r@(W&^eo78r`!YHNsYko7EeZbe|K{YK9t>n4=-H7?_J-) z?~kkCBcT%bXs-u+;P-JF!i*jd#X&8+HKnTV=|om%Tv EKU&60&j0`b diff --git a/src/cctz/testdata/zoneinfo/America/Cayenne b/src/cctz/testdata/zoneinfo/America/Cayenne deleted file mode 100644 index cd49f0534438cc3bfa0e09bb5701552ce9a177cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%F!77_1Q7lEu;~FtrvLxXePCet|Nr;_ e2A2Q-uU=r_@bL{{&^0gtVq*p_8z5Hq)DTNoJr|KGvH b!1Dk9&J7G4KE5Fg-azac9Kyf_Buu#g6^|V* diff --git a/src/cctz/testdata/zoneinfo/America/Chicago b/src/cctz/testdata/zoneinfo/America/Chicago deleted file mode 100644 index b016880653929aa40dd5ac0e82e4094a9d787cdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1754 zcmb``YfzL`7{Kwv{UQjZBm$vHxgogR;v%kz!4Ba>SgseW(IHKuX<|#1ai+m_B26cw zG{@}1#anoxMK?ksVMQVaYbHU74c!*9l`v%$Qv}*=&;OI(^h4*J^FHVIT+aLH)vPF3 z8!zs=T$~+p%cZ&hh~C-e>D<8%=UVAzuavR;P_$0Qitp}fWvtvX5m$ZIi}#%^5;DL4 z-8(iJ52!n-A6#w1hZdWte-*Tc{_2EATx~Z{KQie{e8jvPA06I=k2MwJnyx(jb$Kq< z8`5!Y$y|K=i&Z-L-4prCwK5vsS%AOEOvQCCN8oQ2VYpu9flqqcaYN`8++elfMh|x( z?`dpn!QWrD;!}FFP3D_g+i`Q55gS)@~%Uh-)mflFPit@ONT$w%DlO0BmRBc+t^b667DO|;Qo?%_>Zh4 ze0k+G{O2;2P0m|0RYJxq$>DfF5sv?wBJiM>z=OB@@l|U-{=2&sUu$c{*PHva@}42R zMJJ=J;tak~)`D+tI*5l058zv?w&H(sw&2_I3-Fzo*YL=b@7d%%cLNsUQSW>_I+8DB zerzBMkN0HZf7_$5{bUq&RQucH|0F*3C%9}K!mhJ2I~3R_@C5d$*)Q9Luk8~&!Lp0GpQ+X+^Zv&5cw)m&9B_E2OpCz1Mfjm@Mfl;3 zOYx+FrFe2~3J%Ij!H>)d!BZkbaPW*|tvpQi9>*cBQ*p@6V4X~a_Ko4NbEEjt)0c4g z@r!s`RWqKxAwaf^$2M2t8B1>9h}TcqVA zC!FjRhEqZZZ1Rv|wc|Ns9XPekg6H-g!z%r_PA29xeu$qgGvoQ6YjIkk5icm+p_P5l z z>)xjU%H6kkq_?}SoxE?%g?(BB?E9H~rSB*A3{x=uVBi2{ip5UBQmdcgwAd0I*`U91 zQlnesqQ<4Ym8yAV%vgiBfsFf1Q%S-Zee@qhLbMrcgJwU`!w8mvI;j{ z_QB1YM>?8o*(--zr&i#$`6Rf#*9muw$u!0sRtMbKn#d%T;JEclT&M{wm zDRU!I;k>waBFlTw!ug+9aKT%QpN7KF8C(?9z?OpmTs-#-mn==erNbw%b$ZE57iA4W zxV&!?wxut?6}B$8GI|WQCtG3r$GlEFW7X;;xcYJwuDJ_`YnRutUw7e#(!OB-O?8rWb9rt=26Xi^}rC`pZD7fwC2zIT#!0k61 zuzUI(?l_!PP!o={eqmnpZ z)-%R=z|Yj2Z?3XP`bt{P_k)tIPF9%QqOfw&vQ4CDjkw4a(94-dvoS+2n@mQNF+=kU D(_5Nj diff --git a/src/cctz/testdata/zoneinfo/America/Coral_Harbour b/src/cctz/testdata/zoneinfo/America/Coral_Harbour deleted file mode 100644 index c82871528308b02a45d17b3973c108c20e561c40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I&Vu}AiQ1q@P1w_x=v9JL|&)@a407Reo5uN~| zPj~zSi(gXy0v5lN$oYYZk%^I+h4ugcRWb|=|NrmYz{v9d|LO${9AGvNm=pk!3?e?h ZAq>tgKpYIj;XoV^!r%&Ia{&ocE&%lkOIiQ` diff --git a/src/cctz/testdata/zoneinfo/America/Cordoba b/src/cctz/testdata/zoneinfo/America/Cordoba deleted file mode 100644 index 35a52e53d123b5ef5d293b3af19046630f02bb66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcma)&-7AAp9LLXIFiTlcB#CUTO=`_%^47EqFWC(%+7%_G6uB@ZhCZpmC= zZDV5?F7(tUDHkhpN76ja>v7I^f54p6@A>{d=kq%k&v7`128|@+lCTM0d^s{-X<}p9 ztO_YxW6RrKo*N5p1JC`*E-TN2l1rTX%G_XId=%baG!^FFzqbh=NbSN07jNMY?;hcg zCY11@KrwvS=>{LKtbk7%BAAa%3z$DG72(hN0YPeo(!A4wPdXRH?f zD`JNK4tB%;Y^C4pci9Z4^Cl~MTavTc;pM4NkF4>m^z4DvDi2s=c>`-+$HCf)d;_1; z3cX+*p;pd1Z#`I_h{0Da^_25-i+GOvbs;^n)s>sh`x*GQ&kb;Uu)ka)mHl&P$h(HLwa!R9NqM-CfkmOPNkdUZ&Px3nL4q{_fZ7{K_VPz!BM%FdgDE|PnyG!l> diff --git a/src/cctz/testdata/zoneinfo/America/Costa_Rica b/src/cctz/testdata/zoneinfo/America/Costa_Rica deleted file mode 100644 index 08f0128ee681d8f7e1df186d93514f3f4cff2830..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232 zcmWHE%1kq2AP5+NDnJ+nLI`W&0xDwxV!{7FklC)~3!)dl5c37;7c}!s0Mpy^0zkB| zm^PR%JUsx+SD*d>%-6`S$+u2*F1Fd0wXgM6#oCe(U^e&OtSp{zjFg4=l}n! a7clVp_=Ye9djSb&7a$G}Vc-H1W?TTV6)k)K diff --git a/src/cctz/testdata/zoneinfo/America/Coyhaique b/src/cctz/testdata/zoneinfo/America/Coyhaique deleted file mode 100644 index 26354e89460e7c9e585d62ab477cd69a5559b554..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1362 zcmciASx8h-7zgk(i%TxK=9cDYX_i@|qdA(()igENa?GXCOvQ~z6Vr!;N?NRkEHNT1 z#E38ny=tYB;w36urgEUcq$DUaib!m;O>gJ?rDxyzF6Vsw?*BV?7&w}ovf==;Xi4Y< zTdXvTA2~|LOz5%~X_Xy!w`RRj85hfXi}r0A>#cRK@3P)T_6e->d9`qNZ8*o=6GcW@ z@6D=2e%&(==Wc{tMt)OPg1paV40+#V3-bOsEj%!yfOW2WF|XV64)f0(-@pb{2IdSk zP4JvP41K=o7telI)IApHe;}mlCC{25gfF&~6Y zUQNTM^LFr(VLfa%@eMX_|D>eHh{eztY}qghFTFSbTb1^}*2fG29V0gJ&9H58A8hAS z1KV#o4==N6;@O;o_W{^prW$rK&V`-yJ7DLjNZ6%Y4KIJHZQ6YsrLw>_6Qzqe6&J(bgnh1oJ*Uw?t`|}TY^>`cXGkXVKb9;zqb8E-0 zz`mDS;dOltuwVUQc>TF@ctb%UtUPp_BeeXZW8r}OGFTNpreyB}xkNa~JOO4jNK_X*1w0NVXm&6XYpr z^#Y-ldZ80}TJ$))t?o3u-S<1k@^oz#tTBHMX9iEL{_kTfii4Geh~m&KA{WI0o|uZ_h(IjZE}^?&RAS9` aVx5$%A?bAaDTC+=q)SE2!ss5MGW!eRxNk`S diff --git a/src/cctz/testdata/zoneinfo/America/Creston b/src/cctz/testdata/zoneinfo/America/Creston deleted file mode 100644 index 9d69a0ab819e936a1f4f8029e111a7b960db8b8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#p8r4)XIrobM9;qFT>zrz{j_FaWMcgPf6@^K hhX4QPPGDg9|G&S1fy2i)guypBgdqTkxqu9FE&!V~BHsW2 diff --git a/src/cctz/testdata/zoneinfo/America/Cuiaba b/src/cctz/testdata/zoneinfo/America/Cuiaba deleted file mode 100644 index c09a87558d53b031fca84a4c92165b01b37da360..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 934 zcmcJ~-Ahwp90%}cW?_HzCj zr}xX#UC1LDBi=_x6L2i@9*!$@@ShiX=>Of_1F!RbVUzzQ@{(VNIOWH?W#py&Gjen1cjRS(cW`;*1S|~>!xj2=^ebD+ zI1^*h4j{MMuF7O`#04{qVU!!r*%Hezst>k95S#53qS_xq7MC*LAJoem;zdj1eT6Mh1p9ejg+ z^UN*Sb$JMOzw*N8ngZybAG#?sF&={x`Gsqj;ET)zD~@Vd`PqoR*O(7`L&soWRtENs z>)_Uv2;BB40k=ncITO=y{hO4f*`Y^OzxFVus*CfQY*n4*ET`F}FtcP4$I5gy;Hq)zu?!6V{~y@F f!1Dk9@dFH8KE5Fgx&|i31`LkDAq-qV!h{O|LRTG6 diff --git a/src/cctz/testdata/zoneinfo/America/Danmarkshavn b/src/cctz/testdata/zoneinfo/America/Danmarkshavn deleted file mode 100644 index 8718efcce25cd28ff9fa0f48bba0a2a7e6be4ed0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 447 zcmWHE%1kq2AP5+NDnJ+nLI`V70xDwxVuAlaFuTDMq>Vw?wg0Mk;3CxU6|J$nT}`eoLv1Jkl|=7VXuo(W)DzNQgO zE94Y`X~mdiFsJhA`+F7z42pgFBGT1tbi(02vZWm;e9( diff --git a/src/cctz/testdata/zoneinfo/America/Dawson b/src/cctz/testdata/zoneinfo/America/Dawson deleted file mode 100644 index 07e4c5f4ac3852571b17cb33fe565a5ea2c49f0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1029 zcmb``-AmJ96bJBUOI;3yLB7nj*-xj6OCq?dJ5GC_ih zawO$NwSG!B(T%cje2On~;L)*UgnRmY1)S9X?Bh-z zun2tqGKHgjE>?`G`0p!fzeM?5)pK0nGcVYIeZI>N7u4I}LSr4QF7+W_l&yv}ax1J^ zu!xLm^@l=On=F8JkAK6(6N~Vg(HU3>R|ynnB?FJ((m*b(?|rM{`!efSxV-ftyf*(8 zY^aREhV;BhF=kXoVB_oyxbpKsxGFILuS@kud9FG(4A;c>!>0aIaP4q2y#DYNfnv;j zq72^PJPBKTS+La*fa}bkV4K1Y+qIc0ddBQ?8o2)N9Nh4132vNu4mXXfMT)VFQ+MG_ zLx14S*Dt|aj=h7o4&I6KTyuK@-qw8)c9=xC#c>pF`H>PR#+=m`@ZOo4gk8BuU{`zu zZk=y~x8I116ld-?y?F0Aa}{p8?}pn$r(y548hA%j5Z)P9!9Hyx?C)5B{YyGHV0{e- zJ~jx9YIpH>73Nbd989O+&f95t&+H@|8hj6TB}U-A-A~|svCucUjJ_2a@=SS_;(vcD z=`ZAFOp=BovJ6QY=wq~@dk#*OB;Ab4^7x$<;jZH+D{*`LEa;&2QSYMma?`>~3olI% JO(h*R36>8b2{hOQ;)gcYRO<>hrn-8(J+U9lE<$_ z@k)^SXeemUr5s;gu~SYsbQ0y3EfIDmzqgW|O(|N+z3LZ{a$oep2id#uA=`#sx+U1< znS+l)JLq$~Cc!7}Mfh}PR-!)c)e-p2HVAvhJK%F`D}2#a2Va&{!dDIX@O5eyd}FK? zsn2a(g_hE*&x5_MnXoT93HCX4@ZC)azF+u)A2vMjU|5p4#E&XrAiJ7uKsEGYyITiC{kFCT$_~lcinouj~eRN)v*ol1BtKpZeGUPrs^%XP$WA z^j$YBUo)`JBjl1^U`cT<%@R=_oq;nB>O^K$us~utvvyi!IjcGatLEg)8Y;y8vQxL= zqFpjvy#EY&1)-G5r>Wi8}n}UAzZg-}wcu>OKiqA9w+82zQIDv2jNX-qd&;_S!DMKJPx*_v4YE zRQ!1|RR7Aqt^bl`xu=WJ-}y#Fp`x`!G^lyJh3)z%dAeT N-QssRtPZQ4`wbnj4)_27 diff --git a/src/cctz/testdata/zoneinfo/America/Detroit b/src/cctz/testdata/zoneinfo/America/Detroit deleted file mode 100644 index 6eb3ac46ec56985b52488ae6a8d80247c2adcd4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 899 zcmb`_%TE(g6bA6qf`HSa6+sJ#k0Lfx>d=SfEud|~LmP<>G3sVCKvOnOG$C<=8o@`R zQ3D%dLPXGDTp+k23c*Lv#6(3F;3GP+FvN&X#FbUYdq4gFHlE43XMXp7cUB`Gj5Ygc z$uhA7Z(j1!SL#_TiM8Ee)iLTg#AkPT7xDT0ysq;3I``+|RN@-0`0H?K3*xw{^bh;CEG|a-eErS}d+8lTS=ha<>w`AOc zov!1s^Y3Go=R~0a7C+pCU0;ge{IPSedrDSVjJEc~VCh~VT+p@)_H^1|Z#1g&obT8# z*k4@>Z`=DG4mk7SLf;r%l$;6|XTQ~mRq^NVa7p|DTskocm%ZzO%Ll)yJh%P+DY)YD zE4cF75xDB;FubGvq{3pfb59o>Y&;By3R>ZCC8=oJZ_0zH^-t z4P)dkr5MK3ag!CR4Qu-Dh)ltKGKG2XXI;-aB$L240_?>d@k>6*Ih&Jn`j6jWEiiOmqpqmdH1$No29t?|!3JMIT@BE+kP3RlWobx;1IWP|+A82au zu{n={Pf*a2=U%DhW2rncbbihz#wRIv-5pdZUyGR(%G#9+uoiEFyU%@wdm?F!?t7b` zz13<-HQ2m!LJsYi`QkL|FY&2=3d#~(&sZ{UA9U& zweqh*IjwvKHhB`T+5Qf;h$FDThGF4*H#~nb3R@?J`8Hzdvo33$V!Z}7%9F?iFEpi;3p)(LMp{}tZaaSAR!JPvP*bSTu= zzHbQLQGWss7F~ox!Gmz<=R+~Yko3$mCL#IaKWbgStTFzZ-qH+4UGG$x8MPH}ac@{= g;UJG{9{YJz%1q!W;Z1kgFZm>oJM8sJUdbc;1G${^$p8QV diff --git a/src/cctz/testdata/zoneinfo/America/Eirunepe b/src/cctz/testdata/zoneinfo/America/Eirunepe deleted file mode 100644 index 7da4b98fe3c70a1aecae8e0f4264324eaf9e1fb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 436 zcmWHE%1kq2AP5+NDnJ+nLI`V71S(?zVxIp%Fl|*w1Bl+ipT+>D|Hd2u(K|l|1c2yW z_a-=i=vx-2!2DZp#K80&$-fss;&*nIg5~f2HUx{`oBa#SzkhcdnExQeAI$$ULmI69 zD{B>)|Ls5nSpGYo)d7$>KLS0#{2#|3g5`g4y#uTNwNeBu|ND&+SpHA<%mYBTGsvD? z6#$~;Dn1_o(eeudFMwzToA$r~B=3<>59SBevm9Vz w#0#03{{P?Cz`*eT|M3HiEWn`Iz`y}wGqCvhhA`+Fm;kXU1D6euv@_)b0F&sY)e9Ine0)O~oLzu8ID~- zy9J&qeGgBcYe#=&K0;>>-9>*VTt)wcT|{U7a?v@jI~;q@yv=@i!K?^gn7bfi=ZnMX z@KWb7`0vZz@N%;nHr)5-*zZWLOGGTZOO`PItOab8?WJYs#z(|DR+A(lY#MG33*@7) zpd=DD=ib8R4_}DrI1x_P!xnvYxNq6@hGXYeZDp|a(>mCux>m%_xf^Bhnqn<%o0kLI zWt@WTQ}@CS(Hht>Bp7y*1i{Yk$y!3!T61UEg&zpJOb6)Lxof`@?51~w*R{{X>l^0a z4Y#{tQLc}Oj+2dr&tdlzE7;@2XO5kF22Q}6VxGa99X`Nf?#L?SGJCB5%p z?~$XhPiq4#{g|(1bG}s-u&nVg?3aHAmRCf;isR)XI!2T^p0L0AG#rp@3I~c);2`BN z94t`5DmN33K1NhSE^x@=5WJ;h3EtZM3f@-ltfONjw50~#Ub+B>-7JB3WcI+}Mb%n1 z7m?5kN2Xndqx^L6&Zv{{E}QeP+A{%G&)pIcx}uF0aCB!O95Y}C$A;Dv@c2Bw5#QK^ zUjEmIZ!na{5n?b@YKgJIP+CCD*ms^KuJoTnzuU*fYe;;uh9t5bMfX0s6E#Fg4^;F( T8t*St%H+~`g+iu~$%X#_Z)Mmm diff --git a/src/cctz/testdata/zoneinfo/America/Fort_Nelson b/src/cctz/testdata/zoneinfo/America/Fort_Nelson deleted file mode 100644 index 2a49c6c50f4c21765232712d18a6cbbeedafc441..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1448 zcmd7R`%jH=90&04Io(giBb_>q@K8FPQqle5E;~y1PLWw;WHnYqu~{-1x%I@{MtS5H zjdj^smZes|G)AnNbSgh^DGxv*NQCPuaOHZzsgs_EsohrPd5mxK9*h&kMDU1|B5Pse{VPkPk83RlP)EgpPHWnPn+k#)01a; zw&zcO3Ov((0RH=88$4UBfenvbIrcrtZ8gu5{^KzKJ6=tm_NmdC$t>`K4t%t8;e>;RX2uY;!Ub zUYL3mwoQzO<)K>GF3=ygSNp+=6>$QgvB*LJE2X}$a@0p;^~JsRutSR-yrf|YURpT` zFMH4l^I2{@Z70jm)WRzgtYOEr4vy8Ge1E_z!=A&=@@81&S`4dZheg^()UsSy-TfAJ z9oPrE)m6f)T5|-}=U#jr_R#HxJ#&u3tFLc{*BrdY(>CIj=>&Ugj=?^0rm(Ln0rvCi zhyBe0-~a~`j*gLlJ|!IZrwuMgu>kFpg4R^1=8`HbsO?jmP z>)RYv2XEPb2@dfT;jJNu;jLq>JZ&Qy_luaIQpgs9J4kNj?LoWIEP?Z8$SwbXO@UkiPXrLUjN5qVlZ5uBE(=Q r5+ue3LqRSv$Ga77`coDO#5O!aOQJ*QiKAx+J<(bcLEmNc@|XPs-b?Lq diff --git a/src/cctz/testdata/zoneinfo/America/Fort_Wayne b/src/cctz/testdata/zoneinfo/America/Fort_Wayne deleted file mode 100644 index 6b08d15bdaba6cf94dcb2681887154f4d265d8ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 531 zcmWHE%1kq2AP5+NDnJ+nLI`V711e(&VwwLy5Xby)0f?TrOs4@v&)@a407Nfn;{)>- z&bkfep9)t3^H1Gy2lG#N`~&kZDSrX;FC}t*0O`A2`k4VlUvYR1=3foH3g%x^I1A=q zH{A~A-(Xk|=HC>Z3FhB?FcHkZ^>1qfNdN5v#bExOd(*-EyDKLYfW+_Zs|54!cNT&9 z59URK`42Ng!2CybwqX8aPctz8Nt`^G|KgL_2ax_(K%ax?e>-Hr{Qt}UKLCaW1H<%x zA3zji`@;ty+C{&t07SdGI46MV&nrGKF@hm83zPxjLP%C7RyGLy|9`y|$c~*G7+L=R zU%h~V1I*?DlL8=;LFE7c;|CZee0)O~oLzu87>L7xI3R?<707l4ig5uMra*>{ud$wy Po`H_9p`o6ko&gsCE#d-; diff --git a/src/cctz/testdata/zoneinfo/America/Fortaleza b/src/cctz/testdata/zoneinfo/America/Fortaleza deleted file mode 100644 index 092e40d70122f764fd2630957be1d3e32858f6f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 484 zcmWHE%1kq2AP5+NDnJ+nLI`V72P$I*VxIp%Fl|+~1c=_j@A&{s|8-aZqIZ5YF#yrK z?v*Hj=vx-+!2DaUe}U;ck`Fh4#P95k1k2z3EeaODH~Su#fB)_*F#kb_F_`~l`hT$c zudH!k{HqU9HuZUE5=#^)D+XvM}%u)GrY2{2zdLI5nU{HQ4AyV?$qUT4KJgzcZK`~3rKJd<= zpagGT^5#$KC>Bedq*L8q8F2F%8f#Pdd_J)t@%jG#S2&XO_ZoLZ`JwWuh03sx2E7vh zpHca#@EI#b;JETRINtFRHl>fkTg^SNz#hWFubc2T?FO9i<$=nm62k#_`}lQu$BPz? z@6Aun!aF+};9af7@a|v{oD@iflWQ#S9`8E5H)jprmuZn0)qc|woMKpmQ&v_LzPCh| z;MBQAIBj|wJ}?r75BB!K=`FuCinEM6ZE)t9PjJ?iUX|~&J+I+Ir|!aslOMy@+>5Yv z{gpy7W)rGm+u|cQ_nQqqGSv#(KUPURcQkY!7Dsd7yj!KPqg#NTmjW8an5+3aoL^l6 zyH9_BJ=Qe1z%>jP#_6!vGON-v=3S1$MgIoj;C^RhvyAEbXVqY&dzhJU lPrzxe^~C1_vec)(P8&HouX582pb*}&*=aF diff --git a/src/cctz/testdata/zoneinfo/America/Godthab b/src/cctz/testdata/zoneinfo/America/Godthab deleted file mode 100644 index 310774ea4fdd1798782a41f905d16e3548cd191e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 965 zcmcJ{-Ahw(9LMpq=17JYEAyc?GhJ&woXxWxpWCLk+^BYZJlT9$^I=NC@IoZIFf@`b zV#oRx1{66~wyy|!O{a)t{zu%W{y4l52 zhc20PgKV<+!=E%t*W#p|AWCaw;0Ad{C31Z=#1rgaftaNI1(Op$!xZ^q%$+wdHTn{s zTpfp}-amxu=@}JyubB+Nw9zqmIv~LGzPs>@zXxWtbihm(54Dy`c$O}NI*lHlOGt%! zgzfW{N0MRAhodkz{0GucH=!Z8291OBFt2wSGQJnk5C-~I78x^XWH z-Slb~-5gP(TgHz;Pk0Mn@85ym;1X>0Mqt~Wp8}cJUiKQ@;aNcY(udKV){r1O@?So= zTojiFC`uF~D^#2)M!(A9$w|e#IG!>vthCLP(juKUvvitlG{+hXj7*-vL~|wvzl`z# D+K#Hs diff --git a/src/cctz/testdata/zoneinfo/America/Goose_Bay b/src/cctz/testdata/zoneinfo/America/Goose_Bay deleted file mode 100644 index e2cc3eefc273c206ab9d88f94660f587932991fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1580 zcmb8veN4=890%~EDvFo zG4xl+<}jz|;h5QVDVI`LktFIQ!qxeH-hZ|E!}|XAz4zz!`F_5?ziz+u4Ou%Qxc@Gm zP0*&5{{Jf%*_e=RUkh8CqnFL4EK%p3p)7satfJJED6%Q5)M5!`b?(3|%BL6I;Afc) za81rITpLvh*KKuC(_FpBIanJz1V6XB8%X^ZK27k8t|Is)cOTZz`F?=T^~xSCWn;d~ zK>0e!I+3zzw?Et*^Z|a8D1Z(2^>9l-AKdb(9By^7%b!!F8m%W@Tr9DozKHU?i?%}JPJ=X=D-duMLLcx z$Er+t%7Y`YQ~6;d^_`0|V3&gRuxsuT*expxo|@?mPm_DW(jtKa5l|_mc+oKN(VSB&le6q z`xO@NiZ;_+#6carAYnGVaP?g{GJuB{MHIn{ZM$KK*X@3~C+Vq$qyC(Qm(<;am$n{) zmsQlLXfFEEI(T{E4LIhq1diRG4@*z2&8E4y)IIQu9gAUESTY+^Z^c{NjC*V+jl=kZe`|r=1Rnbd z%(C~|v9I4oj&D~%X6IyHuscgQAbGKN!jl6fVBArWF p!?uj=G`82Lb5d4ISx+isg^*PXStmrXKolVg4^fE4BC#l3_!o8Gf8788 diff --git a/src/cctz/testdata/zoneinfo/America/Grand_Turk b/src/cctz/testdata/zoneinfo/America/Grand_Turk deleted file mode 100644 index 9d90e745b04fae51493817b5ba1db5015a39bfda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 853 zcmb`;+e?#S90%}cbD~V8ELWZ~orm$x`R-uzP*zSi=G9@e-7_*!K$d|gO_ z)3t)1)k#KT6wXv8!I}TmLHl$2GKLQtN#$lbl3)Y>k26<0V`(WYVGpzqr4i_&C!iKQyXEjnX7J$XsGT8XW z4Vyygu(_in#(S2R|KU=n3%=F74_kG`aG7NZE>B2-E3$SYgiXcKU%2w*8+?0x8@{tQ z23Jk~3G&|EuYK^nw_EW2_w8`?iy7E9(CcS4QsW(kYac&??ZzJ1VXuW9#}hGDBhHex z2r@hjyHaehYxX%@AI*o|ABJ%6*{SyPzVx~iZkX4?-iH$0_)Y~kRT<&t?jyJ*I~A6F z-(mUW7;gO(jwzIJ7xby(C|ztMgwh2iQBnG3iX>9Hv8+huFS+cIWa4J)XklxYiH)V2 U!OCEeN=1ukGDv2#XckTCGwa!~+yDRo diff --git a/src/cctz/testdata/zoneinfo/America/Grenada b/src/cctz/testdata/zoneinfo/America/Grenada deleted file mode 100644 index a58e63a44f37936348cd9f49990b6d39dad32fab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@ry|c0;s5`uRTvol|KGWRkp;+Jz`)_-8^Yl1 O0>r@~3|v6Mj0*q+L?#pf diff --git a/src/cctz/testdata/zoneinfo/America/Guayaquil b/src/cctz/testdata/zoneinfo/America/Guayaquil deleted file mode 100644 index 381ae6c463260d85ce92d6585b6420fed0c096dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 179 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwf&V~|*{&7=qPHz^k^t$~7W;DnOcy?LU}R=u x{{Mfg1_J|7K7)bf|Nr9$7&-p`-?@Q-$HzB>ArOdl4NQR8l!40zNZOfl0RUr$BfbCt diff --git a/src/cctz/testdata/zoneinfo/America/Guyana b/src/cctz/testdata/zoneinfo/America/Guyana deleted file mode 100644 index bcc66881c17cebf8767b7a147b1fcf7ab29bbd9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 181 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwq5nWINtVAIM9;Wc?En;G;Hqcc1EMvrIvikR zVrKmR|70Zt!~g%s4=}L&|9{$rf#d)Gs}~sfe0)O~bPY^^*x1ArL^5#M0Qq(%TmZ0G BBpd($ diff --git a/src/cctz/testdata/zoneinfo/America/Halifax b/src/cctz/testdata/zoneinfo/America/Halifax deleted file mode 100644 index 9fa850a7d4c36dea84149bc0ea2fcd3581d61a8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1672 zcmb8uYfw~W9LMpqinMJecma&XKqUdgWf#E^G0-5!3wlNtjT-Ar(+!)Hn8>UKb;^>N zQX4A^6R+W|a5vB(0vE50c3D6P3YUX6KxDm~DXg)sn+zKjO<-6}TzP ziGPYO!p+il+!F96Zc+1btLF_x>|Z(jiY(Govl6!zF2`zdGH%aFz*h?<<7*3oaYuTn zD)u_ZO>~RwiZI|VZ$Iw#y@tE%Tk-E5XYqAs4fbv=QN&*F`a)UcjWwI`&8J?(e=l8y z|4Gik|HdrFw<2@c@AI?Ze&ZtCe`}#Co^!iv1|DdR#)EZ!c&K6w)((2z;{PD+=ut%& z-fhGq);8dgxjnL|`zU`YB1g#$*f*sf-(@Yw#;`JcxBti3Bz=TUJ+I+=)U|kY%ZF}B zKli$_@tDe2vESi*Rn+}IeGHE+T!F`}OT^=IX5$IjAvj=x83!f|;h@MtJaLLymh^L< zu?+_s263==KoNCwdm9d^_uxsjwfKIg3y1FAkHhkNRefBVym1qrl647BUA5OO>f!Mx z@B<6q!qWmi!4cD+#Suft6@5&KGNt1v&kj7jI|@Hovkpf$J}Qg38O2XvOIak2DVU3` z+fCT^e735ONwIm?@yzr&IBwYwI6h($o)zoB5BX|1!TgIlOy zUn6~nxiH)>_}_U=JEQ+}O}p$i_-NXBmt^GgXx{x7XV|5Asrt>-?+X3OcFCk8PA^7h S%(TQ>tkD@Zo5g0an*IaqsOC)o diff --git a/src/cctz/testdata/zoneinfo/America/Havana b/src/cctz/testdata/zoneinfo/America/Havana deleted file mode 100644 index e06629d36841463326ff3350bc2f94d0417c3cdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1117 zcmciB?@Lor9LMpqO--himAY(MD@|AFbhCvue_Zg_N;j`;5NU!$Ej6TwU{M$m*yb{^ zRfmF~ph?5I`YrAJSR9`zG9PUo{TTJ(@mE)d5(KfjZsf3ZTITc*bIdXP$RR zwC>M7iSz#cdidQ$5@G;7Ch6?vKcw0^J`it%Rdt2loGjEbx-I3;Ta3 z2jOK;E4(tsVA&g%_-|mWcOgJgcqS#P(mesI&MpY#xRx&>HQt;mQ4@sM@S1e1Ku**R zz=@Gd5?ReWu=+>4Ku(%(gOfjYN#wOsExc~L6<$AbA5Q7)6KH=!!?yr+qsu2zHyQnK zYV}<>t?4S9o)deX#&QDQoY0K@3~e=>u~-goS<=JWx5os=$JUS<&KxR(w_S9Iw7$JZ z2kRQm@QyP|cxOce&S%-b!r56x@Gip?oRfAP&ebePjE~$EFYebzX0g8eb2q$aZWP}8 z;xwG+y94Lnv%!Ym3vj{Z0=UrK2pdn;qNXDyXi-f*x=%PN((}xjAJF}#;aHb_Xt6f- z-ijB40XlbJ=@EKx>M3do-9$@lua1`<$@gYC@|jWACNv=MA_fTZ3~o zp9axGs%WfFMC>09hv3@&4z$i6!Mg2QH)?-rN9*15sCfIgs8A{Y(}({*ry1i{iN(qC u8%dEU%j3f=xz6TfRz52#`E)p$nqSNudA1^h$xv8Om}fH@4MzUWsQw4Ss79v% diff --git a/src/cctz/testdata/zoneinfo/America/Hermosillo b/src/cctz/testdata/zoneinfo/America/Hermosillo deleted file mode 100644 index ba7b14760d47d1e10241e78e976f0093ada6551b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 258 zcmWHE%1kq2AP5+NDnJ+nLI`W&1uA0!VuAlauyost0ua6aqc)h{mKK%(;%|4f1@m|C zn1T5_{- z&bkfep9)t3^H1Gy2lG#N`~&kZDSrX;FC}t*0O`A2`k4VlUvYR1=3foH3g%x^I1A=q zH{A~A-(Xk|=HC>Z3FhB?FcHkZ^>1qfNdN5v#bExOd(*-EyDKLYfW+_Zs|54!cNT&9 z59URK`42Ng!2CybwqX8aPctz8Nt`^G|KgL_2ax_(K%ax?e>-Hr{Qt}UKLCaW1H<%x zA3zji`@;ty+C{&t07SdGI46MV&nrGKF@hm83zPxjLP%C7RyGLy|9`y|$c~*G7+L=R zU%h~V1I*?DlL8=;LFE7c;|CZee0)O~oLzu87>L7xI3R?<707l4ig5uMra*>{ud$wy Po`H_9p`o6ko&gsCE#d-; diff --git a/src/cctz/testdata/zoneinfo/America/Indiana/Knox b/src/cctz/testdata/zoneinfo/America/Indiana/Knox deleted file mode 100644 index b187d5f8c75685af67913e9360b50ecad19fe6ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1016 zcmajdUr5tY6bJCTf6mQKS2>%jrfD_Iu{Og$fkDtD77dK1QjsA+v7UaF8NS4P$$W^) zg0cs<5kwND1!4xJl|&RlGc=cf+N^9?x}WBQscqf!?bY!9IQN{-`JH=Ten0mi&+!7b z;*#(Q3R>=!j~wA+NjwY*zN%$$Kjqdt7B6Mrlivbm|AkaIaBCQTdod38=gz_XH7b$j z1}X*^<-zQC@W;X~c!;&bA$k=U^W^ z^{Nk^?uiI=Ppm!cr7Zeh!ZVj&z;j0%;f47Vm|u)KaeisY3IBPW562(p!->0Ek-iVR zsYQ}B#$f5W7%V%b5vY*YqiSA}ji(Y$KUf0moh5L_4kNra&j=fGiUle% zlb2wlG!r(?8obn47g>bY2N&QC&qra?!x12 z58lu()!iYHCldGkEE%;1yN-62zR%@myB$0Z@TlTZ?q+4YR`W&?e_?TLw-#7!7MI;_ IwOeiKzt^*oeE- z&bkfepYHev=3i3&0_I;zTJRM$DU?j{*yR)F#oBh1epKK z-G%|A@41i(SpN%kIWYglCowSp70_iM`BxWzfcdYVJp%LJY`g{Lzdd#Y%zrm=519Xc z{euRO`hPoQ!2JKq|33iwje%kMzYidavHjr#5Y1Hn0L*7D_?H0Uvn2d20MV=g4-!B$ zo5OuDpWWaPn9trT3FdPOY=Y2hr+fgZ- z&bkfepYHev=3i3&0_I;zI8DFGIL=5E6P;y)KM0n5Komjm-(d=dlm zU$HZQ`L8bi0P|lzdj#gc*?0@ge|zi*nE!6#9x(s?`Uedl^FGW!TmYg!_8$WCKh-Y< z^FQY=0rS7aw}bg#{oBC&Z}ypB{&)QhF#i`v`UjByUq8|rK=khyo?!l;8=heP-xJzk z{=XgCVE+FVydOZ}$uNT#Ofj~<2lJWA--G$gg**iy21_D$1Bhk~cn9XQIlKk)*$pm$ z`Ru*wU_Ph7CNQ6K?P8E}2CffNz- z&bkfepYHev=3i3&0_I;zI8DFGIL=5E6P;y)KM0n5Komjm-(d=dlm zUjc0f$-lbz1I&N@>=Bs%X5%d||Lw6OVE(&_d%*nn>mM|L)PI^}tNf2v;! z=6}v#0_J~-ZwK?g`nQ4kzh8KQ_5Zoy$pF&#_k=c>|8IvjnE!wI{|CS@U|^X3?*oWp zY=8IwM7!vh6@X}0mp};pc{>9WBM>sPfGH3Y0a<};HdZ!PpveFK>sEriwsQj`%m4qY z7cg*u**suU07No~{QrOa0HcJDZwQ043lIkbaX1hMgfO@Q*{(n_E})- z&bkfepYHev=3i3&0_I;z- z&bkfepYHev=3i3&0_I;z z_Sg|H|K0wF1t4|r*FR_g(H{!uf#pB;9|H3~)h`9hf6iY5=6{KA2lK!Bw}JWpcF2I$ z|6l(90WfSB7^eUG0HPS%A3gxlF8XB!AllU>5JG?64&pMn>*ju7Vgy2F7BB^3qC-|T zAOs4s{{O%BBgi{DH!!mN|G#- z&bkfepYHev=3i3&0_I;z- z&bkfep9)t3^H1Gy2lG#N`~&kZDSrX;FC}t*0O`A2`k4VlUvYR1=3foH3g%x^I1A=q zH{A~A-(Xk|=HC>Z3FhB?FcHkZ^>1qfNdN5v#bExOd(*-EyDKLYfW+_Zs|54!cNT&9 z59URK`42Ng!2CybwqX8aPctz8Nt`^G|KgL_2ax_(K%ax?e>-Hr{Qt}UKLCaW1H<%x zA3zji`@;ty+C{&t07SdGI46MV&nrGKF@hm83zPxjLP%C7RyGLy|9`y|$c~*G7+L=R zU%h~V1I*?DlL8=;LFE7c;|CZee0)O~oLzu87>L7xI3R?<707l4ig5uMra*>{ud$wy Po`H_9p`o6ko&gsCE#d-; diff --git a/src/cctz/testdata/zoneinfo/America/Inuvik b/src/cctz/testdata/zoneinfo/America/Inuvik deleted file mode 100644 index 86639f6ecb4c424911e5bdbca81a9e39c86e850c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 817 zcmWHE%1kq2AP5+NDnJ+nLI`W|04iezVv+wq@PN&)0mx=xNmO3|qFDpECV*%*N6rNx zn%&?Hn9rf`8qDVuI0xo)F`NbSxjt+F^SK|a2lIJuo)rLUW8gh75zOb?xgN~tU%5^J zBrY&>BA74OIRVTUs!Rn5GYDsNNp7VhDmcMU;`Bul?f%(?AcZ2yh8zAv&yL&E}Z`TirSNqxZV7@~> zBwig`W;cKYoctm2>YP#w=DX-mng9}ab%_V_T|XZcU}8jpEX-s=khu&D|NqaOz{v9d ze}4l52Z+tU^Z)Bk;*(-Qd5Txk+N7PC8y{8-#iKZhi9Jm_ssJ$N>il8#}15% zHhA$U2VbeCH49a`L0P#o+QIwB>^~a1x~tPSW>)`dyvNq-D(`V+Utx><61HY8!SRkU zSYS_KA=(4m^lsR`{zPY#gvBs?c)klh@~kt;=Z>KkIPuXf_-I=td@ND{CtY{L$yFkJ zyu=Ql5N)tCOH>&p#kvWn#@OK0Z9(Jnv~Qbm`sy$E8xBYLp6}icoL^A|7hK(d{jMCi(6;~=SrXvlv`;#t6#v-cjg{;! zV}Ab4D*A=bBRZd7oZixSzx1L*=lycu2e@?jCR}!R4leI{pz`lm>IUIJ^9?wd*9wP% z0XXz~GHN!(9QwZ}Hg5kt`XR+I-Y%NVhA}_GtT@~8b{NLgW0u6{CTFfJvrxUlLJd?w es%r`h&^bV7frfq>dTR3}pCo%~y7fthJwzF=o6m@ic60p<&5 zx`X*5ky>EBsHY~FFJ{RD=8J1`gZUClnh6X*Aj$C-%$H)~PGDqW#sdHU-@(Md047=f i|KGWRf#d)G;|Cade0)O~yn)y?7>Hd$7`T88Q!W64fkAEn diff --git a/src/cctz/testdata/zoneinfo/America/Jujuy b/src/cctz/testdata/zoneinfo/America/Jujuy deleted file mode 100644 index b275f27c0287415674d2ccc850c3d612f4a45b0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 690 zcma)&-7AAp9LLYtn6--)MUoU6lUjQ*d28B*lHIUUu3ShdMJ`Z6Zd^#Mw3H%mw_+~F z@;aLtF4k%!aj}p)OPZ&7Jg# zqbm60{Q`JjmlJ%lv;_9o2ha~pM9@DilHh~ga`@n{4nEXufe*#Dz~@sg_)GgL`j_!( z_^_SBhutsWXr&qc%GLu;G%Dc}%M$oq(GQjk8Y}&e^t_CIGS>#53`OBT5+m@R(Hi)# zfEoV#pacGABlTXti)JvNHCe^mvh4L%H>I*{V1=^OXftATy^}~++4@AV^i0cO=nUzT5J?{CrM!!wGyI`LMtet z@<=y{6vw-Q(oq*BL52{5R*+sqM4va6bP;{s3_ZQizuQ2156}C5f6x0I&do{h?>wlo zMVE+{z{6E3A}s;UkwxUFDOr6P@hmv_jz>6nX;c5WV=tKTzJqTQ5rXcB7KKl z3rG~Ei%!^lvH;FIR;f|n((czO^Y;j_HRgbA%2(KSxe0cN&tb=%afy#J;ae6ict47J z=c{KT^_M&zfR~Pq!pm-rNYobx2jJy>8oc6E7hKqR9Co!GKo;#tBUeW2aK9>03%g5G z8slrV!wq}P5!h4Z!kp)OW0vlVKUV0J-kEZE&4dkJd)ErD8~y@IC!z|?mGn--rF)Cv zvcsPx>X%36;fkG8u&?MH><`|C{R_D)%>{%jaNzA5I5?Mqs~(NRq1j71A7krp48!uh zBXISZbFgwX35O5q3eBlqDqPcY7T%C@!4ZE4T&wulTMdT*h`_^SU@2}g6k;Ej_4 zyy^8zcyrd5rMWE+$Kb7+9c~yJg0~%=gJb9K>wJtg?tTh4bqvDs>Jhj(-VHbZ_@J1~ zc@}g2KOgJguFYZpzlX8eZpI9wH%EJa53?A?b(rPY|Oxy`($W$9Q}meeFFkQt?{FAYV*FJ@$#AEH7* zGFTdFNyM@Uvcjyy!k|*2Oij;LS(%qZMbX8b-uG{b-=z2Op6B^J@BgqHGwd}LXvv~W zL=$YYWmx=?5*icJ9VXC~=j>=?)zYf0VD-Z7A7)k?t9;<5hGDq5_&Z_qmOwwa*Lyq8 zdk6LKlamg(Kk6&opYOr5{6NV|yv{(g2j)YLo5&4!72|wlv>txlb_VC8on`P?O%cpl z_Q5uj0k)T?!Edq>;J0}Z@H>SR9@nQ5_PXyAWjw1NJ?Cuj4CZ+7_8xE-E+ z(G5@abi>p4Y-X05v2qox^0K-2_j@n}x!K3z9Gg3Cg~7rlfur9kA@vTP6;ZW~W7X*h z2RoY`MrIe|teI8U9L~t9TlyF*RzHBnr-ES*-|KVrY8}sV621!Op4tEgYF^hocTzIYQUU_-=UBmb38c zfL2%@T@1?|56vv6kmSOO(H1y*A`y=1tcH~X1|yA;H5L=Bx{(0KmT!gCwNhA9Sje-S zw&*7ur_X}d?i_*RFI;l4O`$;>$I8W((Y8i z>rX$2H=N%OryrjCT{l)9HPRT_w4)B^83*#=%-B*`mze?UzFg*=M1L=5m-+VJXui6- zEx1Gr`i1lV=mo*r!2T*7*F-LYaHWyBqxZtym)(iKAUx_4Nw;MiNJb{zyXf9ccaDMR bXs@F)32owOqs)#|X;o@vwnn4UsML}_4kxPc1&!$JkF@bNJr9S<$8N2XrkuLwNmA~=|0_;8eX1DFTp5R7o>Ab@s-N&^ z%qUae%$sIL`OkAVtlV?M>YzoY?_rlLNW$qUSkpZPYY&^_ROn(wNy-H+U*W>0FRKz1#)QIok!#J=O}( z>uiNf+k^K2F1q+;4c{llSnV+wb7T znaA*wLqBg>fl3}ie-T@c=_gjxVr2v?5yd5ok}iA8!ppc*!5uuu9=iz z_oIujXRISmeJfJkus9TkYmc|X-o9$scOXG+%zwlH*KOJfuiQ2X2b_)YD*r3EUhjZ| z6`y4)f}a$)VfqE!_%w&SdOS5j2WxKS?{)2iB)sl?{$AH#?SPvO(pXfFH1wH5PCjbBd diff --git a/src/cctz/testdata/zoneinfo/America/Knox_IN b/src/cctz/testdata/zoneinfo/America/Knox_IN deleted file mode 100644 index b187d5f8c75685af67913e9360b50ecad19fe6ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1016 zcmajdUr5tY6bJCTf6mQKS2>%jrfD_Iu{Og$fkDtD77dK1QjsA+v7UaF8NS4P$$W^) zg0cs<5kwND1!4xJl|&RlGc=cf+N^9?x}WBQscqf!?bY!9IQN{-`JH=Ten0mi&+!7b z;*#(Q3R>=!j~wA+NjwY*zN%$$Kjqdt7B6Mrlivbm|AkaIaBCQTdod38=gz_XH7b$j z1}X*^<-zQC@W;X~c!;&bA$k=U^W^ z^{Nk^?uiI=Ppm!cr7Zeh!ZVj&z;j0%;f47Vm|u)KaeisY3IBPW562(p!->0Ek-iVR zsYQ}B#$f5W7%V%b5vY*YqiSA}ji(Y$KUf0moh5L_4kNra&j=fGiUle% zlb2wlG!r(?8obn47g>bY2N&QC&qra?!x12 z58lu()!iYHCldGkEE%;1yN-62zR%@myB$0Z@TlTZ?q+4YR`W&?e_?TLw-#7!7MI;_ IwOeiKzt^*oeEHq)zu?!6V{~y@F f!1Dk9@dFH8KE5Fgx&|i31`LkDAq-qV!h{O|LRTG6 diff --git a/src/cctz/testdata/zoneinfo/America/La_Paz b/src/cctz/testdata/zoneinfo/America/La_Paz deleted file mode 100644 index 68ddaae768e665a8170ea1485aae51c686f5cfed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#VuAlakl8Ms0-|@wO?v{S-(9`J$i)2r{{a~W q1~AF;|Nl81Mvnjgj~`&*@$n5|a0X(h;1C8~0}}==8z5eoL>jbKmMQp0MHBuIf)|yV7fon0YuCH{C)vMD-=vP0HRgrJqGjD zL~Fo&T~%hVdfnM`92l9IP~iXn+mA3X0Le8V^7sKpmjC~EZeZZ>@eN_nH825UQwA;@ JAZcgH1pxMtQp*4U diff --git a/src/cctz/testdata/zoneinfo/America/Los_Angeles b/src/cctz/testdata/zoneinfo/America/Los_Angeles deleted file mode 100644 index aaf07787ad92b65eadae63b64bba290f9f961507..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1294 zcmci9*H2Sn9LDieD5GT^k!3}#fRvU}+Ol293PTAX6-Nw;QA|w?AV~B=#E63!iUt?{e^uDUh_zbTc#Chy5ydf$}g%hG-_ z7wo2OE3Uy@hxsMi*~H;~SN9$GbM*tXyYU?QrSu}&Q>jP4>T}WFqRr^H#I5M}%mDO< zJQ(eZPh#os^*g7b12W}8$Ai#88^?v3T+yF>W9U%*6gu2uLPrek=xFT-N8dM=*8u-2 z{{WAlY(^(?9-)(aZlk|bE~9@U&!AI*h3K^3EtbA##%TvUYg+=(PM?<2^SOa+c)slb z{P$G?Yr>C<-P8(r^yXo(L4jMte=KgRdvGB zLVqb4XI7tj4tr%dz}|;CSbFXgG77IrdItNteuQO;N?2wdHj*($E-r@U-S1(=;6B*D zu^v{o7IAbgpt1s1J>Clk79EAv716Nf;3X*;W3>4`a8P^!9Gq?qhsZMEQ0)L5W)lvF zds?yNF($lU0!PgC!)sgS;dPy_;q`SMMl!~1Xt)n=ET4rVub07_a=PHCl4_35MW-~v zG5asTv4KW7F7_}SH_{J~iCI}~o%H$xGR;5-ZYcwj2N-h2ezA3}w diff --git a/src/cctz/testdata/zoneinfo/America/Louisville b/src/cctz/testdata/zoneinfo/America/Louisville deleted file mode 100644 index f2136d6ed41bb7dc0646b91bab366efb46bacb78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1242 zcmb8uYe-XJ7zglo-lp@CmX~>(rPY|Oxy`($W$9Q}meeFFkQt?{FAYV*FJ@$#AEH7* zGFTdFNyM@Uvcjyy!k|*2Oij;LS(%qZMbX8b-uG{b-=z2Op6B^J@BgqHGwd}LXvv~W zL=$YYWmx=?5*icJ9VXC~=j>=?)zYf0VD-Z7A7)k?t9;<5hGDq5_&Z_qmOwwa*Lyq8 zdk6LKlamg(Kk6&opYOr5{6NV|yv{(g2j)YLo5&4!72|wlv>txlb_VC8on`P?O%cpl z_Q5uj0k)T?!Edq>;J0}Z@H>SR9@nQ5_PXyAWjw1NJ?Cuj4CZ+7_8xE-E+ z(G5@abi>p4Y-X05v2qox^0K-2_j@n}x!K3z9Gg3Cg~7rlfur9kA@vTP6;ZW~W7X*h z2RoY`MrIe|teI8U9L~t9TlyF*RzHBnr-ES*-|KVrY8}sV621!Op4tEgYF^hocTzIYQUU_-=UBmb38c zfL2%@T@1?|56vv6kmSOO(H1y*A`y=1tcH~X1|yA;H5L=Bx{(0KmT!gCwNhA9Sje-S zw&*7ur_X}d?i_*RFI;l4O`$;>$I8W((Y8i z>rX$2H=N%OryrjCT{l)9HPRT_w4)B^83*#=%-B*`mze?UzFg*=M1L=5m-+VJXui6- zEx1Gr`i1lV=mo*r!2T*7*F-LYaHWyBqxZtym)(iKAUx_4Nw;MiNJb{zyXf9ccaDMR bXs@F)32owOqs)#|X;o@vwnn4UsML}_4Hq)zu?!6V{~y@F f!1Dk9@dFH8KE5Fgx&|i31`LkDAq-qV!h{O|LRTG6 diff --git a/src/cctz/testdata/zoneinfo/America/Maceio b/src/cctz/testdata/zoneinfo/America/Maceio deleted file mode 100644 index dbb8d57d91d6640c1282fab3a063567d1f663f88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 502 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1S(?&VxIp%Fl|*v4T#>s@A&{s|8-aZqIZ5YF#yrK z?v*Hj=vx-+!2DaUe}U;ck`Fh4#P95k1k2z3EeaODH~Su#fB)_*F#kb_F_`~l`hT$c zudH!k{HqU9HuZUE5=#^)D+XvM}%u)GrY2{2zdLI5nU{HQB<+m30J!?WRR910 diff --git a/src/cctz/testdata/zoneinfo/America/Managua b/src/cctz/testdata/zoneinfo/America/Managua deleted file mode 100644 index 86ef76bf2241b6abde0f4790d23b180db4b4b1cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 295 zcmWHE%1kq2AP5+NDnJ+nLI`US04iezVv+wqklC)20;2codb|MXXLBw|0MVRF>;gcv zVBn7jVERfvm@jO23(ObZ5(wsNCQeiU$!i_-2J^L@?}FuxPQC~8ogxl^`Ofy4V7^O8 zUIS1$gR6XG0wWVM6AKVBL+Stj*UK<407(f3mjC}(FJR#K|9|HO1|AT}DB$B8!r%+U U&cPuJu0ZVU62ia*J=vx+h!2DZpIKcEB$@d39;&*nYgXQo3RtAgToBamNzkhcHnExQe5zPNGgBPs+ zD{Bsz|Ls5#SpGYo&IXVf diff --git a/src/cctz/testdata/zoneinfo/America/Martinique b/src/cctz/testdata/zoneinfo/America/Martinique deleted file mode 100644 index 25c0232d95492333e8c1aef7321a24a331e2e24a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gw!T&&z*)DPfL{D6N!Ud#X*f-AsM2nb+ZD3?# vX8QmC*d7K3Fv;@&|M3G1od5q{y}-!p;~T=@<_07jgMrv3gn%Rx)+s`fl^BwXJfccIsy#+vR3{L)wzl9II zo~J&ZJ8yBA9%rqcy>BwYUTqre{TYAd{poYRUA(2Ft}z`?{XmF|XR^f!r&N8ysWHWH zn*Ihh_{YNO;U65Q^hYh6@qG%tdWH&5oS1v?KkqeZ!+_+LJEv2^RlKEL0^b9x-k-fkoLbE#MdFTNaqk62k- z3ad=Y)}Uuy&2wqiRmpR6v{m4_m3uDo+|GA_x331^ce2JMe!sJ^48I#&gWsFGf#1J< zgg+S3!TWc!;U%XFeCYLpk7{M~%M&5=ALl9XC!K2elY{|2&|rZNL{`CPQ*QX6eG&b^ zmudJ*JB7a#pTXfWGyIjU3mmm-;iEnU{I2N(D@MJ*zejoUp+A;kgO3Hm@E_4(_;|P) z{!=!?f9dUMS3^5*zyK0ejNgrDGIhnv=y5 zIM+J@=cT@a&G|jBIU1Je!lG@4Eo(Dy{-y^m_%H}tBiBWmJ2l(|3o~xG@J=Ia8_0w0 zEuA#R9JkeQ(S@tc9vncZOJl}snIZx*~=W{wo>YMPZ>CX_@22UQ+-zPe@CbGrZgwZV)yEqOdW%8f0hG(Cwz?t&kV3%a^C5;J=V%vrA-hNz}~JWR@s{ HL6h+d(?xwy diff --git a/src/cctz/testdata/zoneinfo/America/Metlakatla b/src/cctz/testdata/zoneinfo/America/Metlakatla deleted file mode 100644 index 71b0eab085dbbb48050d7b6a271ebb1a29fb1926..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 586 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1}ftKV!8i7V1MZEMG#%vZXgAsPj^Z!0MVC}zZ8J! zL^S~r{cnf60*L;I*<_lF8gZaXlMPR;2WGI*~>KOv&i&>h3`Qn;pV7`P>@B{`RkmQsA z^QD+f!Td1OM+-pWVNX2_Ky-xMe+4joR13_H{Pz&dk6OwD=11Q<4CcqUxGi90VrF4t z#S7WkL6C`!f#I4O1H=FSEz3Y;e**){|NnC*FmixN9xw?E{>B0Z5s)mSq>pb1LqISP qhXZi{5W9phIC=vG9KC@oE)dfa#MJRM)-%#G(D5}i)HBpG-~s@c41tya diff --git a/src/cctz/testdata/zoneinfo/America/Mexico_City b/src/cctz/testdata/zoneinfo/America/Mexico_City deleted file mode 100644 index 18112346129a885b5d5fa27109682b63784f72c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 773 zcmWHE%1kq2AP5+NDnJ+nLI`Vd0V-nyVu}Aiuyost0ua6aqc)h{mKK%(;%|4f1@m|C zn1T5_{ z!}Kx`#b8v-Q2?Ti-6KF0gGtaUFyB<&3d}b%Is@jLv&(?_7Sb<1fEX6f{(;HiHw!8ble7pX8V7~qA0x;hp{{Wcp*wR}7)W+cCzX;5CPRR%J zUG!VPd{>u1FyD5|IfG3M6nD2Qb70mZ~{2k2q-r)}B`m zKSFd?0Z@WCfET7OC+6|HV8E4FCVnoxs5I|NrU*3>+Ym nk>~&aof{Yhz@&(eZwP~La0r7l5c|3SX%G$%Vc-G^m~jCBO_)21uW9Uh)ADtx)>p0*F>@EO!9W zN}wVD`I`4S!F;V((qO*! zzHBgG=dy(ZP#J^nJYO(hZ?hDbuV1GR<{M1<1Lhm1dtU&lGb*|V<{P`~g83#v2f%z& zb$&44%xDpqZ_f4+%(sxV7`lf6qxVoq7LS}e(t%z$iz%6{Qv)S z1OvnW|Hlt7u>Ajj^#TLO|NoC4F!K2LhA=n=hcM_G7z42p1D6euWoHZ|jqG%MjrEN5 O40L=A4fPE547dR2=xD(J diff --git a/src/cctz/testdata/zoneinfo/America/Moncton b/src/cctz/testdata/zoneinfo/America/Moncton deleted file mode 100644 index 020e33d976179e8f61a6040caaef3c8eb7f348bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1493 zcmb`_YcNz{7zgmPxr{cq+;Yn$l}oI9mI%d2*=Z*$X@<^+E<7Z+HQJ%tr*5oKv@TdJd0tHF>hv5X@N3k=sz+1|>8cSZHUb_r!NQs3=e z1MfL{8{TVN2-`cIgYDN}(Oetl$Pa@Z z*e!1scE1pyB7Gj0WUyzLHSBfbIqYrEgZF#n!#&9%Xv3c9i%rNg0DZePWK#G*|G8amuP%cE~ z#!OPnrMMKikWvyiQx@grIOqEhD9`CR&+|Dw&k-GcE+zRh1UA8whxqr3mW_q6jHfKN zy|?YWdR{XmUcD|Ge5BLBKDiq9ea{5=|0xZxypYuXQ#iYK1Xd15NW4)Q?Ql;0Gn}g^ zgw@ImI4?X2&QE;8e*WVRT=01g7Y1dM{GrHu1{Zt2V9m(_tX;f=OV%W~bkGm$rspNL zM#^foV14%>Y{;61%MEpKMT`qJrm0}##}wgVk|n^Vn;y9G;T^8>8DaBfT!1&0m2|jz zF9_F+M#Hsp*Kl2jVv;}94;;f*T_h};*WiZa7uc3L4mXlZ*q*Q|u{C19_rOiTG1%c> zf}5|LaLdj4Yw_)!0mlQaL0r;z?)8!2zNP?144)pDul@Xc_`g{BZSg* kH<3}gyFnuOEyyW7J`iHf7Li!2BGI$77+7T)#h{M*1uxs6P5=M^ diff --git a/src/cctz/testdata/zoneinfo/America/Montevideo b/src/cctz/testdata/zoneinfo/America/Montevideo deleted file mode 100644 index 4b2fb3e560f6ad26b30b2215d26b3d6176d076b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 969 zcma*jTS(JU90&0KYIB!da}FY!Z8NiJLzHNNX4eT7w`JT`D{m!2;pTD!+A}l*Z zyn_}E-||oP@-{hNn;0LxRUfRB!xutP$`Lker@Z<_6`{QL_CPh|^=A!c${X?CG0L0K z6R6+*J__F%ABFEeAAs+L2jKBr-Eb_}4d3r;gC7Li;P|PoYWm*8+U@Y8Lw-1+*TWNQ zy>L=yGgDt`y$()gb@1bJVR%xPfG01umr>vRsvf+b|GE`kXmr2}J<|rNFKLd#OFy*m zuRk?-|9eqgM*pMGf830m@fs+_`_4v?iETra(ta&0ee>!PS(XUno!sAwck#8w>hSFLiXl zr5PLQ#$pxvjp_ZUmn%%Dmq&8Hd-L2B>ZbEWsMom`;rg9hVgerx%~#TtJ2Zna%0|7@ zgZy?HZjyDN-ZXU>ZqByAEzx?|ku<^1!GK-h!!@FW-6!kd*3f5o*TE9lb0ptGeYCWU;) zUZh2Zvh9PnGr5lu6x;8#LijK~mh#jk-L?dRDa;5gI!=CiMReD?L(`{~xc zCNn)!y63p*4Y9=7?|o#yUK_8kDP#JqAIcdJSyEG^h}`kRWm)7m`Q|o}rC(LWi`-f4 zsfpZ`T8YcHyn=U!fJ!V)-mwF<`}egMLxO{@znI`upze!~2~U{B75# z_`A>jv7;I)Z%KeUadNt8M8Gjz1N^QlbgB$Ug=n8yRD#hmlKf#?* zTV-*s(^amB>Q}=Eh+P@IbZ^*}C z9d=o-N#P}#*nDsSw&XsItwqytL`H@tdXei#a8yz}Pdf|odk6w!OU?mhfO;c*6{=d6pW6okp(%)B2ZXWtu@_^*UcOR~P&)DozVuHS2 f(ASIlT4|RII->Q>Fk6&4(rgX0MMRh*%vQs{dz=-7 diff --git a/src/cctz/testdata/zoneinfo/America/Montserrat b/src/cctz/testdata/zoneinfo/America/Montserrat deleted file mode 100644 index 41bf898bd7965d787e3eb1b55fb6347e10710f14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@r$VdXJHe`A*`tzCnVk6c!{xa zBT|VVSz_3@nsLEGmJUH8VVxUq;mn1In4K_8XFZej0w<@oD{Mafxf=fastTTYS_r4^7QkwsD${==+YQ(Bf0NkW+IvUg zb!SH4+Dp6Py8XA{^_@pVx<=}o&cO|PcELVJ6!!ZXVE>QnidLi5q-k~k=Tp@?Q9@Mp wNnE2-)xn!YkGm14X>(8@{%y3k(hkw~3528Y(2G4-%DZ`|J?L`rF5b!g14LjPpa1{> diff --git a/src/cctz/testdata/zoneinfo/America/New_York b/src/cctz/testdata/zoneinfo/America/New_York deleted file mode 100644 index 2b6c2eea14df07392729ae9f5712a44ec4f02bae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1744 zcmb8vc~FdD90%~HLuD)FSXb_AZECl}O63S8VJF8nxh5}Dn&pq)VT2iS6v+%R8pbh8 zbU9ZSR%{`w$+%iaIr5f-h*vpM?0TNB|CxR}&wlswdw;)Y|Jv0o(ys6$|1BFj!450U z|5x;MtP4H8th8e6#JwzaIfHnX$F6+fSRUU&;LO8!;S+K7@X6%&0(+jd@;sca%Ej}X z`IRE;=StJyJpZ$Bo+TUer+e;!PuHfxXIgpqtWgV}GtYz1>t@0F!m;p$ByTwX=vNYrz$W!Zp51fXEeNjgj)5!MqB+*D zbPa(ks{`RXJ4Lu^_}9P5bzslDwn1d`k3wF;kE2ZRlOd(>Q&k>ZO)}vc=`OfNNQR$T za(TA@yetlWQJV(8JhhEu{aWKH_*GggEa=p5opw50pQMCeM~sFWV!Fd`q7?$$Zw&Vq zS-uT$hu_KE;P<^-;3kJJaMSlk@P|e-{PD>}xY<+;e=0R|?4Hm1DxRfytQh{1UIe#n zJ_xra9Du(r-2i`!Tn~SrycqtWTm-j`UMH}7e!5M7+npA|?QIK0*6(;14F9SQf`3;G zge{i`z}8%=Kz}2I9JGimY*On4mbU8z*p9bw%=X-Go@JLg0>{!JY zr4e$tcc2U0NA3*w9VX`pt$t3;aDQ88xPOa;XMK;lW_ZBEkMO|j_u)bL_u#>q`S6fL zg8iXe_rt@Y>fzxl^#Y+aLRAiroVgDkCC!0lo@-#4r5lu6x;8#LijK~mh#jk-L?dRDa;5gI!=CiMReD?L(`{~xc zCNn)!y63p*4Y9=7?|o#yUK_8kDP#JqAIcdJSyEG^h}`kRWm)7m`Q|o}rC(LWi`-f4 zsfpZ`T8YcHyn=U!fJ!V)-mwF<`}egMLxO{@znI`upze!~2~U{B75# z_`A>jv7;I)Z%KeUadNt8M8Gjz1N^QlbgB$Ug=n8yRD#hmlKf#?* zTV-*s(^amB>Q}=Eh+P@IbZ^*}C z9d=o-N#P}#*nDsSw&XsItwqytL`H@tdXei#a8yz}Pdf|odk6w!OU?mhfO;c*6{=d6pW6okp(%)B2ZXWtu@_^*UcOR~P&)DozVuHS2 f(ASIlT4|RII->Q>Fk6&4(rgX0MMRh*%vQs{dz=-7 diff --git a/src/cctz/testdata/zoneinfo/America/Nome b/src/cctz/testdata/zoneinfo/America/Nome deleted file mode 100644 index 23ead1c004ffd82c03b69b44e147daef4c07c961..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 975 zcmb8n-ET`_90%~HUDuamDC=grqI+v~tM0U2XZ5zWI>OY>^dNI%O^Qrnx-1bQ8$-ep zZ;2brknWBIX-F_lXm%qp7gHCMc)ek}5b++%c09lDA7JsEJkR&{dCvD7c}K@?51VnR zc!M@AdFD@KUK9AXDSS1KOg*LSIoXn>9PJN}QD!T?Cy+5IK=~)THAOjnuS=p-uF3)a z55_J=B?{H4`T(W+pbyUL+L9q_Vy$D8`K@&sN^Q^!>)ge#?#w>eVEhdmZj4LR6TZBJ zXT8heeL?P5fbM5!((s(&96a~h3-pZxX?R}$eR%$%%Wz@GCD_z<1TNap3m5xi@B&9W zTvFbXVSFt#gkZCJCv2`U8R_2qHI$+({ZN&pv}7ycMI$Auo81y^l+4BLv{!uIOxuzh+mMLmab7IwUO4OdSj;F<>yVdt~cNnT^i zt_;Dh+nsQ2?{QeXAi?fENs)S(r;GNvf;&vfpRm_|{$+f{m;1-LO{HYrM9f|V%BxuYrz x=CVx@nQe~py`67KW+6U@!ZK^)8Eoc5u$fN+oqn=2;&pjkqBG)lyWB2O_zN7H-5me` diff --git a/src/cctz/testdata/zoneinfo/America/Noronha b/src/cctz/testdata/zoneinfo/America/Noronha deleted file mode 100644 index 9e74745ca79137918281337fa270c5fec4bd7da1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 484 zcmWHE%1kq2AP5+NDnJ+nLI`V72P$I*VxIp%Fl|+83W(mpZ+!tw|23KbqIZ5&QvlJs z?xhKU=vx*G!2DaU-+<{ml9v~N#P96%2Fu_5%?=j7H~RvZfB$X|nExO|70mxK{UccY zSJnV9|J#8uu>5yEfe9dUegw*a`9F?t2h0EBIs#VzYsD+D{O{L4!18~(^Cy7(DSNU( z0YuAHoCNdb7pN})@fC~@g87P#(F!2G68A1JUpazl0f?{sC`kZBtC~Mq0H&|(1oO?m z?Ev#Fc9etpmiMnJfaEP-GJ^G6pZExtx5;Oiz{E%t{Qv*q90rE}|37|UWcmO9@dE}9 VAKwrLT?0cPHe%qi0g`q`TmX|XySo4Y diff --git a/src/cctz/testdata/zoneinfo/America/North_Dakota/Beulah b/src/cctz/testdata/zoneinfo/America/North_Dakota/Beulah deleted file mode 100644 index becf4383301e2d90db0c0c06659b588d25042ee5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1043 zcmb``?MqWp90%~TIi0&*>sD%Wn>}c`w&vWXGq;{r+gdY6VmGV^OEAUWWJN{L!!51Y zi|A4WmT6nj6H-llQw&OpBIx18gvbJWcvIN}Q9;sl>zwaD;G2GzbHC?v?(fHab;QlB z%?>hYDQE{)3iAAg6Jyotk0W1P%3%i`Ve^3z}862f!AKViuszCTO_4| zJ{c+m+y3V#lis3pgx-SQh(eW4cgrLjdme9kD|#a&wERIGi_>@Dd6Q|Jn?F3~uNj*^+66BdPQwfDr*PkLy$fE{ za~@uN<_Nr`traegH^3!3cfd=7Zg`n{Eo?21Dzs5*5@DO(1>1f&leBODVuBqRBV0E2 z9bP_^g;%8C!Yez<@P5^~0l55t3RfH-XVg{)KErEvJ%XJjFJMz-XzXyJKxI6=9-uT!Cv9!KD+vvJsa#R>b4bMpEAPL4bAX|eOWl*3c)r0 zad@Mk)wR|>HBAS#U$wdhbFbmh%Sqhd^zi|_c|fb{mXS;F*2`L5x7|#@b?sVR>$`gs z^l{`~;Xz$7t(kRqOlGkNAN%=e;-gV!VeT-u$fp_(Ppn$k;sZ*}P z3+X^Ny`XIcVMI0QqGV7?5J7dbZnD5$ZYp~rDoC1c{hsgs05AIec+T^Dp7VR)z&R(p zx4YBLW?dS7f`V3f_K`MzOyFV3^0iMVB`6Qx@TruqCIy9Z?5qWjU;Yd~>yzMA#qS8+ zPqiBv<-b!$43yKK_Q2DxTH%?eJ~;Eh3ulKc^mvS2G#e;s&SfYu?Xej+@1RK`>)K0I z%K6RH3gv=^G%PqLV4>dw>kXr@{`N5D#UIz;Iq%}QFO5Iq(~Qj>?SoZP z)C(`@I}I;9z8_xH-2oT1HNnMOH^U`f8@$-I3O1Gp6>5~~McAaZ!ls{kt!5-@t zxYqp|UMtw)I`bbs#aP`(3HGMPVc(PQ@VYliczr@tso0PlfH$813fEsb2{-iQ-fLsD zKSGU7J96*U-_ZjHs-g<@gMpoJ@Yj8&)$pCCL!$D(cR_w`^WWebBC45jdnn980Uo<}wDM>UGe5VVTjZBo4o9e3cFRsj$mNnRx1{66~wyy|!O{a)t{zu%W{y4l52 zhc20PgKV<+!=E%t*W#p|AWCaw;0Ad{C31Z=#1rgaftaNI1(Op$!xZ^q%$+wdHTn{s zTpfp}-amxu=@}JyubB+Nw9zqmIv~LGzPs>@zXxWtbihm(54Dy`c$O}NI*lHlOGt%! zgzfW{N0MRAhodkz{0GucH=!Z8291OBFt2wSGQJnk5C-~I78x^XWH z-Slb~-5gP(TgHz;Pk0Mn@85ym;1X>0Mqt~Wp8}cJUiKQ@;aNcY(udKV){r1O@?So= zTojiFC`uF~D^#2)M!(A9$w|e#IG!>vthCLP(juKUvvitlG{+hXj7*-vL~|wvzl`z# D+K#Hs diff --git a/src/cctz/testdata/zoneinfo/America/Ojinaga b/src/cctz/testdata/zoneinfo/America/Ojinaga deleted file mode 100644 index 1dd08b1cafd4b36ce963bdc42a075665fa723b54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 718 zcmb8n%PT}t90%}ouMtfXlk7-}QjB2+<2e|H@w%SZG#HFWBnyhH$Sh>CGAwL7vLFi! zlQc-#u@n}}4i^Q>YG zc2Awd?T0gPNAC{YxiScQlv6(qT|S?evO9Gf?&(M)vYzQzk0eVWlB^LYL=68rvdsBP zEMuH6`Bk;*(-Qd5Txk+N7PC8y{8-#iKZhi9Jm_ssJ$N>il8#}15% zHhA$U2VbeCH49a`L0P#o+QIwB>^~a1x~tPSW>)`dyvNq-D(`V+Utx><61HY8!SRkU zSYS_KA=(4m^lsR`{zPY#gvBs?c)klh@~kt;=Z>KkIPuXf_-I=td@ND{CtY{L$yFkJ zyu=Ql5N)tCOH>&p#kvWn#@OK0Z9(Jnv~Qbm`sy$E8xBYLp6}icoL^A|7hK(d{jMCi(6;~=SrXvlv`;#t6#v-cjg{;! zV}Ab4D*A=bBRZd7oZixSzx1L*=lycu2e@?jCR}!R4leI{pz`lm>IUIJ^9?wd*9wP% z0XXz~GHN!(9QwZ}Hg5kt`XR+I-Y%NVhA}_GtT@~8b{NLgW0u6{CTFfJvrxUlLJd?w es%r`h&^bV7frfq>dTR3}pCo%~ypWzNh zCT5oZ|Ic_ZFaSv#1`yi^M4mgr!14e8)e8)KKE5Fg0YI#4U~FsvA{n@BfTW!<7XUfW BELZ>l diff --git a/src/cctz/testdata/zoneinfo/America/Phoenix b/src/cctz/testdata/zoneinfo/America/Phoenix deleted file mode 100644 index c2bd2f949b248b835c98216b4dc66f9f6eb0265e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 240 zcmWHE%1kq2AP5+NDnJ+nLI`W&1}b9#VuAla5XZu^0YuMRW;Fps&)?170HPPP$$r^U93H~J1!S0W0RTV0SUUg! diff --git a/src/cctz/testdata/zoneinfo/America/Port-au-Prince b/src/cctz/testdata/zoneinfo/America/Port-au-Prince deleted file mode 100644 index 3e75731baa7c47f2a60ad07733d6f8467ccfbebf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 565 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1uA0!V!{7Fkl8LD0HWvQ75)L~my~w90HUQB-#dWm zkM9CNwDiM^V7|=73t+zN!OdX4+{R5{zWl0V>y_w6nf{dgKEJATTQW1?C&OTZ8!~L3hA>C;tktd!18U9T*R749pLf5d`x?LQjDCA-_L^`C+E3!2F0KA3rcM zGZ7E}|KDT4zyKs&7+C)QKYoCb^Z);y8yI+fd_x!l0)T|83lIl~FmM40Qy@pj*I3U; P&p^l5&`{4%&wvX6G;?mv diff --git a/src/cctz/testdata/zoneinfo/America/Port_of_Spain b/src/cctz/testdata/zoneinfo/America/Port_of_Spain deleted file mode 100644 index f4fe59034242c4416bc84f06f38530d625149329..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~+1z*yf diff --git a/src/cctz/testdata/zoneinfo/America/Porto_Acre b/src/cctz/testdata/zoneinfo/America/Porto_Acre deleted file mode 100644 index fb5185ca60283bd56f795e9a956274c0b6e63325..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 418 zcmWHE%1kq2AP5+NDnJ+nLI`V-2P$I$VxIp%Fl|-a1Q5N0KaBxQ|BX2SqIZ4_2msN$ z?oDt2(YGv4f%&)Ih=J)ll7BCN#P94Z1H~SZufB)__F#kb_KbZezhBR3H zSJo;p|J#8Eu>5yEs{7CynFoMwXOKO) zDgZ>wReU}GqU9F^UI5Vw#;*^6XvM}>u)GrY6ENQ+p&rZ+s%JUC#E1tnGyVU6pn!ql l|Nr9$7+HV;v4MdD#Aaae@eN_nH825UQwA;@AZcgH1pwW1w6g#J diff --git a/src/cctz/testdata/zoneinfo/America/Porto_Velho b/src/cctz/testdata/zoneinfo/America/Porto_Velho deleted file mode 100644 index 7f8047d9396f92476873c9dbedb4598d9d238046..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 394 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%Fl|-S3lP17Kl}rj{_D2^MDP6Q5yEoedy!egs;9`9F?d2Fw5AdH`1cYb6_4{`VUZu>7Cy?hPP+%ATC# z0HWn8o`U)E3!D#t_zK2%!F0wm`-?mfsvVs t@&Err>EOaI6Q=b3&=6y0ss#_Fq;4X diff --git a/src/cctz/testdata/zoneinfo/America/Punta_Arenas b/src/cctz/testdata/zoneinfo/America/Punta_Arenas deleted file mode 100644 index aa839ea7d42eb9822002e66322c4ae195f1644b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1218 zcmcJ~ZAep57zglkx4D^fscELBwJgnA)^wWFbY5SUnr|y-O00+iQ;9T5{g6;esPrLA zln4tkA|yhuT1`pu5|vbo95j}Y1Z74MiAC?~?VLaK*-t%}^E~|S^FLg!bzenUELpNR znqY^Ob?Ga$G^U~_K%!OA95&Bpt3J!jW~c3)h0U&pHxJqDCdWlKg#-0)e|-wiJdj2v z*c>da#{PDA9PZsoypH`{`4Q~xA#UvL)1BB4E!g1UaV_i!J%+sF=zHW}ta=N(48_Q~ z>e}E1XENqu+i!t=S8_ZP=|2!s^GaZYtF?%1%J>{uUK|T6v^v(` z-bj34<5N%U6F=xgLM!R!M|j6$4V-+=0jKoL!luezIJLzI^F>btdX1!&55nn&TX05p z2b}4D9yZ4e@H9ruU#sCPzjiolR;Fj~v*+sIoRKPcm$MYk9U{o*^(Vpkk5t$fSQqK_?B64o$rUoW z$Nznlk~Dgj5Zdn%g(M9N#8Z;SMdHmmN4sl+^JSg*=H**S5k1lRczWXKF%Yk0+D!(p EzhvT4*#H0l diff --git a/src/cctz/testdata/zoneinfo/America/Rainy_River b/src/cctz/testdata/zoneinfo/America/Rainy_River deleted file mode 100644 index 7e646d18e18851bfde743b379e52df4ec5b5a20f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1294 zcmciBZ!FYt0LSs~`O}?4B&X{LQQZ!myYnZ1OJT+`;uO_dnv$NlRLleVwQTVyQY*W4 z(LBi7!mRn%q?p;t8W*|fx+IxDC2aZEUBB<=*K^PM-oC%r_x=6-dGg(rRSorZZ6vxUrEG!rn{qRH z$afj{hqCRkuP?ty=>7NUXVJqM!{`z30rZEER`e)oL>ojkXoIN=Jx2KGvHsKOapQf4 ze(zI5rG{$kDn@^5NvPk#h7xA{ZM6AyZPggkHryjx~yRrC{DUzRX*VUukSZBsYkmY8|SR~Vtd`yI4% z?uJ6r%(?Iw+MBAOgW)Bi!?F7sdTV^#BFR5cN@5z1}`BnQb= Oaz#M0QYlx;6~e!?Qp8jM diff --git a/src/cctz/testdata/zoneinfo/America/Rankin_Inlet b/src/cctz/testdata/zoneinfo/America/Rankin_Inlet deleted file mode 100644 index 6d1d90dede9888571eb09299dbd0b3e7dcfb1cc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 807 zcmbWwODtSr6bJBc7-n3`R8hvGgEAQ%*PZbi>e-ozMSB&Pw9kd^zWL@;|wr*KI9!c4ujLf*zIU z?vrvJ)ADCfc^!Ufr!%H~6Rc1VczG&Q4=g!RsOzLnSZ~^ZgA6mUz`U^F`vwQ^55ggT zrhWX3Jy`hwhb|1jVLu0G%?v}G@Wb9tIQ&yR{HU!Sj%akikrfU&D$fW%wiw~)q+FSX z82vSD^oxOw=g|r+Vh^t1xUEY#esvd4@b17*#+PAJR~W@vV)rNlLfwhur5I|&y|T`ROG zTzRHw)QT+pUHg~|Tj2_tSs)5}X^UP0k-_QTnCI1~SRb80Y sXjOG$jOl4+A?cFDoGuS@zVa|Pe*zzJ_`+J1DcVKJT4l3|Hc=A(14>JgdH?_b diff --git a/src/cctz/testdata/zoneinfo/America/Recife b/src/cctz/testdata/zoneinfo/America/Recife deleted file mode 100644 index 305abcb8a2217834e8333a2c486ccd389199a334..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 484 zcmWHE%1kq2AP5+NDnJ+nLI`V72P$I*VxIp%Fl|-(4iLSA-}3>O{_C&+MDP4)VgRCd z-78T5(YGwtf%&&y{{qu@Bp+@7iQm~736{V6TNEsQZ}vSf|Nh-sVE%&;V=({A^#5S> zUs>b8{BH+R!1CYuk?S~uN6PQ^1t7(f#v^n*De6Mok8|w zp8<%LtGK=ZM9VKQ-2kE$jL$Cs(Ta_kV0k6(6JWk_gaBAx`B8xaNM6R=a|KImuVEF(4@dHMd|NpOE YVBqla4PnqVFaly@1}+;QX=ls@031EO_y7O^ diff --git a/src/cctz/testdata/zoneinfo/America/Regina b/src/cctz/testdata/zoneinfo/America/Regina deleted file mode 100644 index a3f8217a544ebb0993473bbffaae8e2d723c4ec3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 638 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1uA0$Vu}Ai(Drw-42Yh$WBmjWJ%2ZQ1Bl+5>i+>m zZ!_?C0HU|M8iM&d1hl~XovOlM{>~3PVE%4Cg94Dc-RIwd`Fq|8f%$uPawmYq4;68M z)gMlL4VFI=_zKKFYB3osf6VX&T9aP-`m#?=HKsZ0P`Qr%LMZuW+s98kLtX^{KuXy zVE&UhT`>QtrW%<4%-u@>WX^LTX9f`cLR|;UfAL8b%zypt1DOBj+GQ~R?XgP&OpI6| zGYeK>h+@|N|K~no02;A+0V4~LJ%ND(%;o`;Kr2=+U=Z=~4Po$g0pegF4hQ0Z5C&%; Kn+r&oaRC5Dz-C|o diff --git a/src/cctz/testdata/zoneinfo/America/Resolute b/src/cctz/testdata/zoneinfo/America/Resolute deleted file mode 100644 index 97eb8a9c1fbbf56b8e32a1bea34f68e263e2a9d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 807 zcmbW#Pb`~Z90%~H+G+PHim|GWV$;;>_4f6z$~Lr(k;u$Sa5F;e;!T*vMcTy0!Iso^ zSR^*PEtae%B8_aT%MKzz#6kQC7g;1*-f>g$dY*3_c5CAI=E?K@{PKNnudlPeS0ph< zMH}p}@x^}fnASA(7!*2N(SV<3qUlP&eWUrW#2jDq2i6Mfu+Fju-!y!KIWh-x@>@9J zU=r4Ehh#!0G4c{l3J2lj&q1~(hWA5o%J>kRI?@KG^|!&dI-GENgA>lEG{LuRCfJx) zA+eCDJBLkinXu`^=x2+p!zgUtID_vj@4?w~yKv6TPuMb?%<3dJFazhc{)6*he3x0c zTeb<`Yy1Egq%XkM!T@Z&*zmK3jq8SO`}1(&u@}Do;~i|@d@iwG(ex{rpZCDUqaCm? zSpYlwhFOh>gF3jRz8x-YIfl!uF1TD=g)6jX*qQZPX2E%M0ar#>VArn$xN7GMT>bUj z&lV4sUc(RH?8A?yB)DcE0@sdBNUT@)-W3bor6!xAjk~r0MKlOhv)mOi+ vqJ%>#jiStcBs!LfzDN*=+v6kdXFlSkhohmKF6>PuyvPgoCWnJ}@B()U;8v1r diff --git a/src/cctz/testdata/zoneinfo/America/Rio_Branco b/src/cctz/testdata/zoneinfo/America/Rio_Branco deleted file mode 100644 index fb5185ca60283bd56f795e9a956274c0b6e63325..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 418 zcmWHE%1kq2AP5+NDnJ+nLI`V-2P$I$VxIp%Fl|-a1Q5N0KaBxQ|BX2SqIZ4_2msN$ z?oDt2(YGv4f%&)Ih=J)ll7BCN#P94Z1H~SZufB)__F#kb_KbZezhBR3H zSJo;p|J#8Eu>5yEs{7CynFoMwXOKO) zDgZ>wReU}GqU9F^UI5Vw#;*^6XvM}>u)GrY6ENQ+p&rZ+s%JUC#E1tnGyVU6pn!ql l|Nr9$7+HV;v4MdD#Aaae@eN_nH825UQwA;@AZcgH1pwW1w6g#J diff --git a/src/cctz/testdata/zoneinfo/America/Rosario b/src/cctz/testdata/zoneinfo/America/Rosario deleted file mode 100644 index 35a52e53d123b5ef5d293b3af19046630f02bb66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcma)&-7AAp9LLXIFiTlcB#CUTO=`_%^47EqFWC(%+7%_G6uB@ZhCZpmC= zZDV5?F7(tUDHkhpN76ja>v7I^f54p6@A>{d=kq%k&v7`128|@+lCTM0d^s{-X<}p9 ztO_YxW6RrKo*N5p1JC`*E-TN2l1rTX%G_XId=%baG!^FFzqbh=NbSN07jNMY?;hcg zCY11@KrwvS=>{LKtbk7%BAAa%3z$DG72(hN0YPeo(!A4wPdXRH?f zD`JNK4tB%;Y^C4pci9Z4^Cl~MTavTc;pM4NkF4>m^z4DvDi2s=c>`-+$HCf)d;_1; z3cX+*p;pd1Z#`I_h{0Da^_25-i+GOvbs;^n)s>sh`x*GQ&kb;Uu)ka)mHl&P$h(HLwa!R9NqM-CfkmOPNkdUZ&Px3nL4q{_fZ7{K_VPz!BM%FdgDE|PnyG!l> diff --git a/src/cctz/testdata/zoneinfo/America/Santa_Isabel b/src/cctz/testdata/zoneinfo/America/Santa_Isabel deleted file mode 100644 index 0d8c993bd1cf2fa2cbf002421ec9c0fb2b29645b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1367 zcmc)J$xo9(9LDi!Sqf!)WfxE@pruesTehMivS?)sAQi=fTM&bZ0Yr&h5EK)MK?-Q1 zF<{l0NKh6rh(Qr9L}T3QK@dbl1cL0MtWswl{s4|nGw-*bd4KPFX{tGpk**}GE*_m= zn=Q@ij}*}{Q@WiEblqzj&SI_3OF-+ULJF9h($nB4t{h=*7EVvHz8)#TeZ9vF?&~XS zasJ6Q6?2_skKt}2fV zy9J&qeGgBcYe#=&K0;>>-9>*VTt)wcT|{U7a?v@jI~;q@yv=@i!K?^gn7bfi=ZnMX z@KWb7`0vZz@N%;nHr)5-*zZWLOGGTZOO`PItOab8?WJYs#z(|DR+A(lY#MG33*@7) zpd=DD=ib8R4_}DrI1x_P!xnvYxNq6@hGXYeZDp|a(>mCux>m%_xf^Bhnqn<%o0kLI zWt@WTQ}@CS(Hht>Bp7y*1i{Yk$y!3!T61UEg&zpJOb6)Lxof`@?51~w*R{{X>l^0a z4Y#{tQLc}Oj+2dr&tdlzE7;@2XO5kF22Q}6VxGa99X`Nf?#L?SGJCB5%p z?~$XhPiq4#{g|(1bG}s-u&nVg?3aHAmRCf;isR)XI!2T^p0L0AG#rp@3I~c);2`BN z94t`5DmN33K1NhSE^x@=5WJ;h3EtZM3f@-ltfONjw50~#Ub+B>-7JB3WcI+}Mb%n1 z7m?5kN2Xndqx^L6&Zv{{E}QeP+A{%G&)pIcx}uF0aCB!O95Y}C$A;Dv@c2Bw5#QK^ zUjEmIZ!na{5n?b@YKgJIP+CCD*ms^KuJoTnzuU*fYe;;uh9t5bMfX0s6E#Fg4^;F( T8t*St%H+~`g+iu~$%X#_Z)Mmm diff --git a/src/cctz/testdata/zoneinfo/America/Santarem b/src/cctz/testdata/zoneinfo/America/Santarem deleted file mode 100644 index f81d144206ac5bd2029d59beac0bb82801ebe67a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 409 zcmWHE%1kq2AP5+NDnJ+nLI`V-11e(yVxIp%Fl|+p2Z-LmAN~PM|MlAdqIZ6Dasbi0 z?ll>J=vx+h!2DZpIKcEB$@d39;&*nYgXQo3RtAgToBamNzkhcHnExQe5zPNGgBPs+ zD{Bsz|Ls5#SpGYo&IXV{w_u1wUu^oxv)nZLRG`0wkg7?ZHPPX8fpsyL2um`9VX52~Hq)eWG^T%m z47RWyge_jr!j_8;@QPsrY&G>2wr>BVpvQ>K&^Rn>7=u?{9)N92dtkd0MuCnI`-EnA zRdFBe;8O!TZodexwr}FuoRjwv*lDgBb}`R`T@1Tn*O_S8ty>MRd9LROE%$S7ut%2$ zUR(JaUe_px9C>;aj%uHUHRYXfbb|rrG9L5v7>OzE zg=3XB;B5)#;W&pgur{cNqhmz-r4o*}Z-(P%#R~R3VXg*F9ISwM7_#A{euDYr?g%*L zfd%r^^m>8NO1spFJUw;--dT4R-sSs^V|j+Y3f5V_g0sSAa6YT+qrmbU=ZA1k<1;vS zz60Jhj@&vZe2TpNfME6PLdKB9Af=e?;dcN z6qp9)TmIhj0Hn`K^I-xbGZQll9I`UA{{O$Pf`I`@CNQx4|9|`dBj^ABJ2x=!{{Meq m2csZJghAZLH-sVB1xUEM0C8{#gRX&zu>pf4ki`WgOt=8q(o)<2 diff --git a/src/cctz/testdata/zoneinfo/America/Sao_Paulo b/src/cctz/testdata/zoneinfo/America/Sao_Paulo deleted file mode 100644 index a16da2c4d5a980cd944d86c34ea8a2f597e39b71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 952 zcmcJ}-%C?r9LMozR#LOHE+Q(_$A-vi+G%I$EHi7^Ty56!U~@(Y)zG>qqNpwcqmn=< z?3Z9S4_$vgW7q3dYIPf`F{QZuX@JWm)GV zJT?TE6y;&R%PaZ(ta7>bTCra-`xg7&z8mP3lWFuFw_WHvhb{D~Gr91t!7lXb z`XBJ_uD@_i*(kiH!-V&)`_7p>zVK_J#-c2c1k=9Plx;p2X|fo+5}pA*(TdpY$+ zM-JRLvH^}{O~aAi1-NM{0Y`5daI?{(%h%Y^);Q0y{kM;0jRhIAtaQq@)UrOjW6Ogf Rjg=~H`KZiZCBLgx`#+zs5jOw; diff --git a/src/cctz/testdata/zoneinfo/America/Scoresbysund b/src/cctz/testdata/zoneinfo/America/Scoresbysund deleted file mode 100644 index fc1b11cbe876cabb53fc1d42db25b0aabd967fc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 984 zcmcJ}|4S2b9LMoH=V%OnxH5IMnblm=yv@69n%XwC8 zKg5U&Mi3S)ihc-NzpVN}?F$hkn!m(|$|x8WeIW{yijeC*ul)i3)aUrzi8+RHa-N`^$o!Ff&|U(4p_}LLW{`? zH*1WgC+FUu@_+%NZ%l?M!^-s{2dIjwx)3E-?1mvQ(ARm6okhzYb zEOdItp{wTtY^b~p8y&|AE)K&cV@f9Xn%?xIoBtj~w@mubn_maf?i&&48E=8!GwrZ- z)CAjNX4pQ`%#e9o{93dxYD90fd_;Hn7SVp~6gpsjiw=DI0Jmu#6`Xwvx96|H9hsX@ zn0X+R`Qo`Gx^wI*dS@bm?n<6Uckek1d*Xv|*QPj>gaGWV=!Co3+Je707%cNMWPb3) z3iRHE8g%IHPxQW=9^IE-4#U~6aR2Z;jHG7afk+PapZF}3c?VnXp$Eb<=xEhN^q?n$ zj_K~mbP-*w`5#Y_qI@|-QHqj(M-?l|kMFdOyeS>|GrB|&CCbJ*)Xh_M97pNhYIz;% VoATNtL@*F-n{XgVtt$P3f diff --git a/src/cctz/testdata/zoneinfo/America/Shiprock b/src/cctz/testdata/zoneinfo/America/Shiprock deleted file mode 100644 index 09e54e5c7c5bb2384e37626d4b985cfad29ed29b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1042 zcmb`_OH30{6b9hiQfNDlGAban#Rn**we|%SS|6acqQ*voHJ}Sk6CS~hsIkU{I!e{B zFiez%O28Hf(HOPFji!l0jK;*rqHaVJL^moLW7LF7q2s-O)GZtDITiC{kFCT$_~lcinouj~eRN)v*ol1BtKpZeGUPrs^%XP$WA z^j$YBUo)`JBjl1^U`cT<%@R=_oq;nB>O^K$us~utvvyi!IjcGatLEg)8Y;y8vQxL= zqFpjvy#EY&1)-G5r>Wi8}n}UAzZg-}wcu>OKiqA9w+82zQIDv2jNX-qd&;_S!DMKJPx*_v4YE zRQ!1|RR7Aqt^bl`xu=WJ-}y#Fp`x`!G^lyJh3)z%dAeT N-QssRtPZQ4`wbnj4)_27 diff --git a/src/cctz/testdata/zoneinfo/America/Sitka b/src/cctz/testdata/zoneinfo/America/Sitka deleted file mode 100644 index 36681ed78eaf0b46f8d142884cf7ae8903a18907..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 956 zcmb8t%TE(g6bA6yQaYWXYL%k3fQ|)PT56fL7N{>Q6p3PEO{)fXBt(M?t&$jx(O5N6 z5+6g{*bvRILKB6FE|i#vVPhg{VqF+xd~Q_Y!uZ+{81MQ10EuUE?zz8vzsYPSyQgn& zgw0zfo}i}6&i_h=$3)&9gIDY1>kC5P%&I=A%rG@7M5B-ok|VL|x@3m4mA(eWG>Z%@cP&ZO@;T=roM z_x9J%9CW_m(IC8Vd<sSp2psJ^4X?>K;h3)%Zi@VYn}yAAOI5kdc(r`4hvPH9;kAz? zc-@;<@Os^=Q*Oh9ad@L@gIkA&;7tdo;l$Z{8jrEI?N8zM-U6I#9ECfQ$Kj5j9~G0i z#9}V}*JHH_|MxIf9AV5b@;+KGpJEonxTczHSnXK(Z=TOFC*7J{*jH~$Wm!7IdpGYi i?_`#Bb0@m^Ceg)r60LD^Fcl3&LP{_d4u`@aMfwXhr^v7X diff --git a/src/cctz/testdata/zoneinfo/America/St_Barthelemy b/src/cctz/testdata/zoneinfo/America/St_Barthelemy deleted file mode 100644 index f4fe59034242c4416bc84f06f38530d625149329..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~+1z*yf diff --git a/src/cctz/testdata/zoneinfo/America/St_Johns b/src/cctz/testdata/zoneinfo/America/St_Johns deleted file mode 100644 index 94d790baaccb72298bb577041cf3c8400339a7da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1878 zcmbW%e^AqP7zgl;A7duvm!mrvpsq3BxPM+Q2^!F4fX{}t+DbGN?phBZp!+T zdu^15WS(rw!v`a`QGQds05@pn;cwMr@R9Ay(0^3k1ve(&gY~h8;qO+A!c9KaaMOJg zd~CcJZoaI8zrV1jm%d{#Rlz?rtKpU-+HF)nUXu>De)s|WW2pc>QCtL{RPx}qbUAEH zn1tK;e7Iw&e>UCI8JKEAx^KciO~t~dp$o8Ct9+Zz&3&9k%2Ou{5tLmVN1#ke9r5*fa*QbLvYWv18^^^4IYSbmDBk^ zq1{3`xL0nayqM*!pd5OW4-dy*hc79(u+{%8JQC-GM<(>}Xt1A(=0*q3SSW2{8u+rl z6z5~+t?=*ra^Wjl8GN-w3}35^g8#@2g~wlAfUgVOustKfO84Ff3ARu=_;avhdIolK zY_PL`2)=1I!;>v-@SolF@L#9Q3YwoXm{gRvboKCbtq#8Z{vLRytO|C$riR_QJK)(( z>F}MzH2AKd$U^tr3yg#3xN>;z?q)01=N)`_!MX~*Z{flZjDE1^sMA8fGuG!5Rtok< zy|7osdDy#rLP2$(LWhddH}5>mN$G+8M9nZa`WWmVR15Q1pTfLb@4}Bfq>|eJ<*MvZ_c;x$>nJIOeVLi{#jK zpTVoL3dhO(@SSkn>Qp%H!F~gi61Wuc&a8X~z8X@L0 z1`FWKB|&gz>qa=ZvX%Q diff --git a/src/cctz/testdata/zoneinfo/America/St_Kitts b/src/cctz/testdata/zoneinfo/America/St_Kitts deleted file mode 100644 index 6170b6c09d7a4412e94c146246fbba418b3331a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~+1%s|0Yp!Fc6;1C8bAYsA<07Y;fvH$=8 diff --git a/src/cctz/testdata/zoneinfo/America/St_Thomas b/src/cctz/testdata/zoneinfo/America/St_Thomas deleted file mode 100644 index 0e62d30bb5d9e1a6c13b3a45323605828c8d9deb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@r!u^N;TlOL2ZM|MjyEVE&tHm%;qE$1Z{S?N={&6WMXCk z5~z^%|NmJp7=W5qFJNT(|9|cT1`aTr2TTGDUA=%o#K$*;!Pf6Bn2m!SMh8bv6tP|NrmYz{v9d|LO${96r7w49+e<92~;H1tiS4 E0FH_xivR!s diff --git a/src/cctz/testdata/zoneinfo/America/Thule b/src/cctz/testdata/zoneinfo/America/Thule deleted file mode 100644 index f38dc56bf20d9db68515ea7602c9edb39fabae8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 455 zcmWHE%1kq2AP5+NDnJ+nLI`V70xDw$VxIp%FuS4r4@jT-*Qy5~TH|T#1rV)yHRb_` z);ekr=4r5lu6x;8#LijK~mh#jk-L?dRDa;5gI!=CiMReD?L(`{~xc zCNn)!y63p*4Y9=7?|o#yUK_8kDP#JqAIcdJSyEG^h}`kRWm)7m`Q|o}rC(LWi`-f4 zsfpZ`T8YcHyn=U!fJ!V)-mwF<`}egMLxO{@znI`upze!~2~U{B75# z_`A>jv7;I)Z%KeUadNt8M8Gjz1N^QlbgB$Ug=n8yRD#hmlKf#?* zTV-*s(^amB>Q}=Eh+P@IbZ^*}C z9d=o-N#P}#*nDsSw&XsItwqytL`H@tdXei#a8yz}Pdf|odk6w!OU?mhfO;c*6{=d6pW6okp(%)B2ZXWtu@_^*UcOR~P&)DozVuHS2 f(ASIlT4|RII->Q>Fk6&4(rgX0MMRh*%vQs{dz=-7 diff --git a/src/cctz/testdata/zoneinfo/America/Tijuana b/src/cctz/testdata/zoneinfo/America/Tijuana deleted file mode 100644 index 0d8c993bd1cf2fa2cbf002421ec9c0fb2b29645b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1367 zcmc)J$xo9(9LDi!Sqf!)WfxE@pruesTehMivS?)sAQi=fTM&bZ0Yr&h5EK)MK?-Q1 zF<{l0NKh6rh(Qr9L}T3QK@dbl1cL0MtWswl{s4|nGw-*bd4KPFX{tGpk**}GE*_m= zn=Q@ij}*}{Q@WiEblqzj&SI_3OF-+ULJF9h($nB4t{h=*7EVvHz8)#TeZ9vF?&~XS zasJ6Q6?2_skKt}2fV zy9J&qeGgBcYe#=&K0;>>-9>*VTt)wcT|{U7a?v@jI~;q@yv=@i!K?^gn7bfi=ZnMX z@KWb7`0vZz@N%;nHr)5-*zZWLOGGTZOO`PItOab8?WJYs#z(|DR+A(lY#MG33*@7) zpd=DD=ib8R4_}DrI1x_P!xnvYxNq6@hGXYeZDp|a(>mCux>m%_xf^Bhnqn<%o0kLI zWt@WTQ}@CS(Hht>Bp7y*1i{Yk$y!3!T61UEg&zpJOb6)Lxof`@?51~w*R{{X>l^0a z4Y#{tQLc}Oj+2dr&tdlzE7;@2XO5kF22Q}6VxGa99X`Nf?#L?SGJCB5%p z?~$XhPiq4#{g|(1bG}s-u&nVg?3aHAmRCf;isR)XI!2T^p0L0AG#rp@3I~c);2`BN z94t`5DmN33K1NhSE^x@=5WJ;h3EtZM3f@-ltfONjw50~#Ub+B>-7JB3WcI+}Mb%n1 z7m?5kN2Xndqx^L6&Zv{{E}QeP+A{%G&)pIcx}uF0aCB!O95Y}C$A;Dv@c2Bw5#QK^ zUjEmIZ!na{5n?b@YKgJIP+CCD*ms^KuJoTnzuU*fYe;;uh9t5bMfX0s6E#Fg4^;F( T8t*St%H+~`g+iu~$%X#_Z)Mmm diff --git a/src/cctz/testdata/zoneinfo/America/Toronto b/src/cctz/testdata/zoneinfo/America/Toronto deleted file mode 100644 index 668e70d765dc3fb0eda16fb0f1932af607b53412..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmb`{|5Fro9LMnm5$Qky5i`X?O^-vkJ0Sc57Nj6yU05BHTItph4D|y$R){l(eIbcv z8YZEfvcXUkQ0oLegCM>r5lu6x;8#LijK~mh#jk-L?dRDa;5gI!=CiMReD?L(`{~xc zCNn)!y63p*4Y9=7?|o#yUK_8kDP#JqAIcdJSyEG^h}`kRWm)7m`Q|o}rC(LWi`-f4 zsfpZ`T8YcHyn=U!fJ!V)-mwF<`}egMLxO{@znI`upze!~2~U{B75# z_`A>jv7;I)Z%KeUadNt8M8Gjz1N^QlbgB$Ug=n8yRD#hmlKf#?* zTV-*s(^amB>Q}=Eh+P@IbZ^*}C z9d=o-N#P}#*nDsSw&XsItwqytL`H@tdXei#a8yz}Pdf|odk6w!OU?mhfO;c*6{=d6pW6okp(%)B2ZXWtu@_^*UcOR~P&)DozVuHS2 f(ASIlT4|RII->Q>Fk6&4(rgX0MMRh*%vQs{dz=-7 diff --git a/src/cctz/testdata/zoneinfo/America/Tortola b/src/cctz/testdata/zoneinfo/America/Tortola deleted file mode 100644 index a0a5d6021a529acb30c17e90aa58f31e519386a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@r$_#oZhw7zgm<&LSsSB-II7i`K6DC5aemGRRVTp){q@OoNo_jhHl(>EcMu)HH1; zy~)(LjA=$AhBv0B)Y$D}(Iyo;i(Jb!r{C}U4|v&g<~h&#JoEki-W>Jeg8X1+%`zhi z+O*VbAE_WQE7C3^sodDoaXK}v?E;+-+oU|5Z>l_Ct@m6JwKmU}rBhex#L@X7-WL9t zH4T5_Oz`J09o)yfh4s?suzsik?qBT{==p(89v(Ebz+dX0@pNzKxC4K!x(N?y&cojd zis0e09Qb?60r*F54E$3b3Xdco;^;l2&KWG7Mp-m$oC$$VHlDCaD}~2KR^jpHd3d6G z2>w;0hbJ3X1bWX@aT`2cZGdMkb@6mRTi6ND9eE7@POF3e#9e{sgDT+#zdD>>bjpX9 zY%AfVh07ehXW5t!uk@XO|GwG_ueK(`;uC+C{$J*f)r8|64`%Z^oS(^uUs-CfI(c5q8k`unZ~3&Kh{#i$>U~zJa5A_FfIV zzKVyPFP6X?3eLbTIa#nYMGd<~MZj+IaM;}|lV?b6v~!0&%)?-hnNWf5Hx0YNo?2IU zbJrrgrFj9~`e*>=N&`3&XSP+e!(Q2ru=lBcmhOGRCgJV-Uc$c8URdU@fn}=`0*Ntl zNjWSxyodcw$KZgDW;jq+#?#ymO)acwISL1ror9IN39#zqEsn&P;1VA=B>5~HnrRJ( z$+F?_U?Uu16A4FpTCwC96FKSuM=g)S(cLR>%)o1SXOp`?VoYq?Q+QYP5*&B`2E4m) z5RR{`=V>k>tpnb3{2H7XB*00Dr{Sbo9cON4ZedAY|LqaQ>$e$36d&+rmZDf)&e-DH o0dIDHs+vhpB%Mk6An9~9BO!<+%fQqSMX*8{n5t4KR0^f!AM7IBd;kCd diff --git a/src/cctz/testdata/zoneinfo/America/Virgin b/src/cctz/testdata/zoneinfo/America/Virgin deleted file mode 100644 index 0e62d30bb5d9e1a6c13b3a45323605828c8d9deb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@r!u^%@K_2GX?Df=~rmMBNdFW)5G23*t*VSxxViZb|bXYef6Go5` zj-D^(Lp;cM)!Uz6v+Zzkr)3RT9t~)p2-Dls!d&2i4yw}nZhxZ1q!#0Bix7yCYtv`|i)tJ3@5by2DY1ol>8g|4+ z;I^f9c;9GDqB?WF?Ztc7mB?8Q>`Nu#u6rr?@WM3g4}XBW<0J5qz%%%0)c;K`qiGVK=v2=PUB+H<4AEO&O=VGV7#8^a@&(EwFXD#1ZsnaDgpN+;tbCAZ(O&4yua8tS{ J6|`9t{{Yyp^R)l~ diff --git a/src/cctz/testdata/zoneinfo/America/Winnipeg b/src/cctz/testdata/zoneinfo/America/Winnipeg deleted file mode 100644 index 7e646d18e18851bfde743b379e52df4ec5b5a20f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1294 zcmciBZ!FYt0LSs~`O}?4B&X{LQQZ!myYnZ1OJT+`;uO_dnv$NlRLleVwQTVyQY*W4 z(LBi7!mRn%q?p;t8W*|fx+IxDC2aZEUBB<=*K^PM-oC%r_x=6-dGg(rRSorZZ6vxUrEG!rn{qRH z$afj{hqCRkuP?ty=>7NUXVJqM!{`z30rZEER`e)oL>ojkXoIN=Jx2KGvHsKOapQf4 ze(zI5rG{$kDn@^5NvPk#h7xA{ZM6AyZPggkHryjx~yRrC{DUzRX*VUukSZBsYkmY8|SR~Vtd`yI4% z?uJ6r%(?Iw+MBAOgW)Bi!?F7sdTV^#BFR5cN@5z1}`BnQb= Oaz#M0QYlx;6~e!?Qp8jM diff --git a/src/cctz/testdata/zoneinfo/America/Yakutat b/src/cctz/testdata/zoneinfo/America/Yakutat deleted file mode 100644 index 773feba89d36ffab4baf105b8f0ae69584a74014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 946 zcmb8u%TE(g6bA6yQabI3TBQgrh$D}dLLH_9rL8Y4v>L@mNJkCsszieetuZkgqoHb| zB)$?i5)v48n5dcPLWu%~jftp%2VeflxmQ-^SoYA4YLs z@OoNeycRzigqMtr!b@*F#JsC-5MI_h053n0gA2QRV0Y&}xM=HMcttD;7Y7n>Nkv9y zygW`H?6tPS-a5C7&b{AT49e0^)jDO_R295(LV(Nf*x^+}Ut#H3Org2exkmlt(D#?}lB!SdZh zaQ*4CuyU;(4js@Hnp2OeaKn}}aAVpHhy7h}llmKu2%F((S)s&uML*ZTvDshn+Q%Zi zZu%9x-tZYTx8cDEyz#07Ztm}gHyxgVEd3s93Cd zHf#Prmtg;>3e*xk7GY)@&dGtGN9?{?k^jm6ur a@l!G0meykAV5&h@WhIyjh2)T|h<^cFp~tQO diff --git a/src/cctz/testdata/zoneinfo/America/Yellowknife b/src/cctz/testdata/zoneinfo/America/Yellowknife deleted file mode 100644 index 645ee9453073acf4cff9f9420b358a8ebbe40f93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 970 zcmbW#TSydP6bJBcZFP62EvItLOV+04w%a!D#ZB#MwVM?!iH?N5gkXxkBn3ea)s!n_ zFHJ>Ih&Jn`j6jWEiiOmqpqmdH1$No29t?|!3JMIT@BE+kP3RlWobx;1IWP|+A82au zu{n={Pf*a2=U%DhW2rncbbihz#wRIv-5pdZUyGR(%G#9+uoiEFyU%@wdm?F!?t7b` zz13<-HQ2m!LJsYi`QkL|FY&2=3d#~(&sZ{UA9U& zweqh*IjwvKHhB`T+5Qf;h$FDThGF4*H#~nb3R@?J`8Hzdvo33$V!Z}7%9F?iFEpi;3p)(LMp{}tZaaSAR!JPvP*bSTu= zzHbQLQGWss7F~ox!Gmz<=R+~Yko3$mCL#IaKWbgStTFzZ-qH+4UGG$x8MPH}ac@{= g;UJG{9{YJz%1q!W;Z1kgFZm>oJM8sJUdbc;1G${^$p8QV diff --git a/src/cctz/testdata/zoneinfo/Antarctica/Casey b/src/cctz/testdata/zoneinfo/Antarctica/Casey deleted file mode 100644 index 84f1c61e5c7c35090fd2e628e307cff72389fb02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287 zcmWHE%1kq2AP5+NDnJ+nLI`US1S(?&VxIp%@K5ec1CY(&b&E{_M0@w2`T(N+R?blX z(f-b7CxGY(F6#ym9kqmC07OUc6mbC2F}<=4AUbxMs{x3POFjys7~(4y*nsE+pX~u4 zIx(UN%umvp3FaqTq=5M;92*%Jnb06e0|*o}Ft9K%%-X=fp=)5kplx8mplxW#z-0qu J+38wv0RS#AC%FIs diff --git a/src/cctz/testdata/zoneinfo/Antarctica/Davis b/src/cctz/testdata/zoneinfo/Antarctica/Davis deleted file mode 100644 index 3ec32224f2982db46a19d1a159f9017286fd1413..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 197 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I*VxIp%@O+K~1Bm|SeqR7Y|8rjrGKRtHmWTm} z_MZOB0Yv+)Tm|O)JAXgG$iT=1gdkxMNGf1pVPJ3zVBpX-FksL&Fb85&1}+;Q%TCvv F3jndjA(sFE diff --git a/src/cctz/testdata/zoneinfo/Antarctica/DumontDUrville b/src/cctz/testdata/zoneinfo/Antarctica/DumontDUrville deleted file mode 100644 index c0cfc85a29e833d02896066e54126317826ed90f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9$VvhenaAi+f1Bkw7l8^wRpW84sFv3k^=vlzP VqHAElplxWtz-0p@?Q{(dxBwv_8BzcM diff --git a/src/cctz/testdata/zoneinfo/Antarctica/Macquarie b/src/cctz/testdata/zoneinfo/Antarctica/Macquarie deleted file mode 100644 index 99a8e60edffca85f5caf8eda9d05d85a4978e665..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 976 zcmcK1-Ahw(9LMqR*&O1W+7r{%t+aA#dpJjJ&eWOa%m+q6L(=jADsvY>7by}o4p^QW zy(uBdKr6W(_M4Q66TKlI7$<7pRqT$$?RUNLo}H|K}oRx||Ti!E@w zcT(naJCSmJJW=y~nGqBVL%OQxP=BLL=1oFMHrjA53vF2Uz(iME^J6AVO8chyatj*& z%)#WbgT!O{^cALrHeu@PS(w)T1@0Mn3ious zT#h!+5Wyl=l_byyeW7;f-YQIKp&sFg|<(G(T?FuXy=fEcHQ)%#p^+| z)Yb}%ng?*dxUvFW;_gPDuvpPbbv}bW>oBY{G~xR*i7zxawD(&7{Q}(1A=F}UH||9 diff --git a/src/cctz/testdata/zoneinfo/Antarctica/Mawson b/src/cctz/testdata/zoneinfo/Antarctica/Mawson deleted file mode 100644 index 05e4c6c5867330a5af95cd6816ade311a0cac82d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%@JPX^0mx?Xx~1g62$BJVkOT%61_rkP Y1`b^V0|spaGaxo);IaXdcDklq0BGzFF8}}l diff --git a/src/cctz/testdata/zoneinfo/Antarctica/McMurdo b/src/cctz/testdata/zoneinfo/Antarctica/McMurdo deleted file mode 100644 index ea1f8f8a7797921488d015ecc6dbf72a81b7d3c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 768 zcmbu$ODF_!0LStFc-1a;S&}@~YrWR)?CfH_*K5674mN3%=EAn*t-+%vcx;&j0^5-~ugS~9dzkjjQYyR|AebZep z-Ll_^BKlK;EAvqKI4`mep8i0GobABS{&T3>nuF?gFASR+hT*nZsOfXV2<;GzY^{_1 z>V#4GS+X~SBB6^;s+HaEfH9n2cA*BwUWCB7kxUrxeSlhbFie>7!Nlr&m^82klLduD z=u$jKP^Z3wsXQmrW0K}qfld#-5^0k3OP$2bxZe|*nY%#}Q-8Q1GP9ObpkZ|s8pi@5 zKi&;ZT{lqZaX@qZ0kpJuBtn<1UqDRakMqch_=2g!Mry$%s&}}1*gxjaJ>f> zZL35=S3J>#E}4Ep+j`CD(*9#~Sz9A4Z{L6w#R9CfO+tH|23BeNWZz$5^_NTZ8IIAlB3}y!kpCI+ zBmdj)g!NvBBL7WsgS9G8b8hG^&+Q@%r^dEu?9|8!I4xQMr%$-xjCain=R0ns!#l^_ z@UD(EIP+Q-oOLlq@ZRo_5za1Ig>&k^z`1E3;XD^yE<8Ij6br~+W-3}i-bs83zt|}y}(Bp$`t!=Qqd{*$iL#czE36*eB z;v`%gJA-`}CBd#YX5=MbEgH!x9sUL%dX)&5^}L14AI!t<_A$7kI|3_#*Q$I*htEEO zJ@ygUTYU?zOzDGtg%1_EM!ugNaMiY(aMip~@O|}p9aNQ(f|HwoseDq}; z^7@7@jbt6`A4A^YnS+mCxDNX*OA6vx-&CjK*#u1{%X()F452D7ez{$$w7XEIxbAggf5w#&9re3?AC?eYHrq*~Sw diff --git a/src/cctz/testdata/zoneinfo/Antarctica/Rothera b/src/cctz/testdata/zoneinfo/Antarctica/Rothera deleted file mode 100644 index ea49c00b2240fbd608425793b225d6e10a58ddef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;4v>0YCS91`|NpOEU|`WTFksL%FlOMg0g`sc FTmZ^O3BCXT diff --git a/src/cctz/testdata/zoneinfo/Antarctica/South_Pole b/src/cctz/testdata/zoneinfo/Antarctica/South_Pole deleted file mode 100644 index ea1f8f8a7797921488d015ecc6dbf72a81b7d3c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 768 zcmbu$ODF_!0LStFc-1a;S&}@~YrWR)?CfH_*K5674mN3%=EAn*t-+%vcx;&j0^5-~ugS~9dzkjjQYyR|AebZep z-Ll_^BKlK;EAvqKI4`mep8i0GobABS{&T3>nuF?gFASR+hT*nZsOfXV2<;GzY^{_1 z>V#4GS+X~SBB6^;s+HaEfH9n2cA*BwUWCB7kxUrxeSlhbFie>7!Nlr&m^82klLduD z=u$jKP^Z3wsXQmrW0K}qfld#-5^0k3OP$2bxZe|*nY%#}Q-8Q1GP9ObpkZ|s8pi@5 zKi&;ZT{lqZaX@qZ0kpJuBtn<1UqDRakMqch_=2g!Mry$%s&}}1*gxjaJ>f> zZL35=S3J>#E}4Ep+j`CD(*9#~Sz9A4Z{L6w#R9CfO+tH|23BeNWZz$5^_NTZ8IIAlx3y{iEu m10xfd10<3P7=ZfR0vI@S4Gb8x4a|Yql!40zNZRR|asdFaJQ3vp diff --git a/src/cctz/testdata/zoneinfo/Arctic/Longyearbyen b/src/cctz/testdata/zoneinfo/Arctic/Longyearbyen deleted file mode 100644 index dfc509570a5be7ea90f64610ad5ca5a58fa3d172..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 676 zcmbWy&nv@W90%}chGn5|ZMI=-Z1eSFKW!*+n&n{MlkY*IghcJM926IFaB%pNgQ7?d z6n0TAMk!L!FMhUW0LTA-e9xREawUGQ?o1h4!m7#Wnoct9`E z`R6S!^2>5NOw3u~>x2#_M;Z9mBY~;T6im0o;5!?I8FdJLFiC;#{j}vHegtbvG(lACkd_{V!NB=F8Bl+(kM6SfI^^#mdiWySi<#^)ubkoKYx!5cY8qJ*3+GMqxIftEU HbIN}KI)2g> diff --git a/src/cctz/testdata/zoneinfo/Asia/Aden b/src/cctz/testdata/zoneinfo/Asia/Aden deleted file mode 100644 index ac571479d181c64527f34272b901498e885408f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iV#E72khD4?YU(yV2`z~bW@!k}$n%)n&> JB<*yKxd31}4BG$z diff --git a/src/cctz/testdata/zoneinfo/Asia/Almaty b/src/cctz/testdata/zoneinfo/Asia/Almaty deleted file mode 100644 index 02f047d70fc811f8cc17f2c08ddc1f328576fb94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 618 zcmWHE%1kq2AP5+NDnJ+nLI`Uy0V-n!VuAlauu8J}4v5~m_`Ly0zo>fc0uU`Gu}J_# zi*syL0MkF8P5{voFP|&`(UP|%!SYgPGQoW5J!J<#;xcQ}!L;n02rwaOUl5sK}tH9HjJHgfB^`MigLlU zv26*MHVN_v)26avVA{;c5JLa80Mi!Iehv&kU~yLp%(wh)0Onim`2*%#-xdP%ZI(%b zY1>_2z_eZKZ!m2?>l&DLNWBZD9h*NLU;u*D2gei`nVGOa7VN?hrNCt1p#swH7Qn#5 oz>rkH$N@|f2@E_Sl99*9H-tgkz!Zqhf!K_J%Ld4^(>3J+0Kt`S8UO$Q diff --git a/src/cctz/testdata/zoneinfo/Asia/Amman b/src/cctz/testdata/zoneinfo/Asia/Amman deleted file mode 100644 index a3f9dff57148554c4207d71df64851aee2b28b19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 928 zcmcK3-%C?r9LMozm6>O=HWBnf&E>4+)XmMD<+7H}pIaN-Y3kH@bW_L+gSEhZ5oPoT z%!oil^2dctLA1K*_wJS#g;p13_8@^EN#I4GAnSQP`vbi4JI;CSz3+KAR}+0#`;27I zk+CQE#Yf!xNDF)H5W7?fHZLc>edgy5hi+1Csv_#*9?_U3xVehGkkU_i3!gHum#_at zE56^rK0RI_u{Ajw`G`I?oq|?|X3#maU(vZ^Y3RJjF8cTb>SD)8e&`ok-4jEfaDPA- zG$-G$3BE=b>fYo0N%J-IDfu{BE5A+&8|_*X&Y%AM7W<;bKJ0a`da*B#HlRyJ>d~cx zFVOmjK|F70ox<;B!8)|j8iS@&Sf^R3~e8{?F)sa(4Q&n~}{c%O^; z(Nzo2(3Xh^JU=`HtB1ny!c!-_81O>tz&}dZT(XB?jU@nUi$!R&>S3Lt0@kZlN&jTS zMxj(9Y#JAL&`ldkbaQkCZI5rE9gnx+<>@cb8U6v?3w{@2<0&6Qi|*%?_m#~1Xs_`J z+PganTQdfe{=5g{|SzyO#4eXrHgZ{gPuxq4BB5b72RLbqXohxyBvJ#XV x@Fk=JviNxI!35}VD#Zz9ndOhmA-dv%FP_z%)`uonOT diff --git a/src/cctz/testdata/zoneinfo/Asia/Anadyr b/src/cctz/testdata/zoneinfo/Asia/Anadyr deleted file mode 100644 index 551884d322bcd2201b4b9898ec765141277e6eee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 743 zcmWHE%1kq2AP5+NDnJ+nLI`Vd04ie#Vv+wquu4*P4v5~mxaR;+j6qag+5kk0N%$`S z(c&C_8^H9>iC}SwmlGU7e92o!z~WM8M8SONJxU26ahWy3U|Mz#3z(Mc{tBk$tDk{s zh3xBKS~2jRk{aEt8v$YX?2zr4;X+z{mV=+t?^{W2M}Mg z!T~~GsRoN{9mxUH+FN45w9XPgFs(bq9!%@C7=UU05=Ag=kRk-84P)&R7=Xa2ND@pN z+bV!*lfd6#+EkVaOq&_rh0uSVfN2Yz{tVCux)-U=Z-}4PnqWGy-B1AT|bK PLk2DzpopEWp%E7VnShFz diff --git a/src/cctz/testdata/zoneinfo/Asia/Aqtau b/src/cctz/testdata/zoneinfo/Asia/Aqtau deleted file mode 100644 index 3a40d1175a7d81d8a307d0e546a1fe9a40888b29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 606 zcmWHE%1kq2AP5+NDnJ+nLI`UCnaBpj0{?+vmE@EMAbRWKzYah#1~G|q1|V9TW1|9? z{`q+Uh?aQyX#;4yNU6JixRFW`X}y-oU|PRq5?G%>N;8-?j9vGD0SJtWI>EHD?F2Aw z5|j<5O=XL~w3(4Fg#H@>rY)qi5*UEM;;tE(Z~5B?%(vPr0p?rZ)&uixmYITS+uZ_S z+OAC;Oxw@;1g0HQe}ZYp7QP3JOw24y=#Z5WBE-mw37Hre^c5I@z`}ung@M5>fPn*; l0umT_KqMoObPHhQ@bL{{&^9muVpAYCW8ks@vg~wCxd8kpZUg`T diff --git a/src/cctz/testdata/zoneinfo/Asia/Aqtobe b/src/cctz/testdata/zoneinfo/Asia/Aqtobe deleted file mode 100644 index 62c5840a83e29b4fcedba95e438581cec96b3cf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 615 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1}b9%VuAlauu8Ho14M6K{MP{}#vrQRy#YjvNgPlB z(c&B%A@tAB3qX8{m!H7$lDE~t;!;4yNU6JixR< zjwP5@jL`zqNFW`X}y-oU|PSV1xy>Hl!9r)*aa6r<{1@LgK1;i zCNOOh6bq(JWmCYknUOt&{_6&&Eu>=tK>951YJmBczwN+$tG!%czV&SdFyCgGI+(WI z%><_H+Bm_q{j4Wo+9CBdn09PoxWLH7%)-os4q1W1I3WXr=?t(l92i&_7~BFFIDknZ kfsqG9G5|@p07ecU-w+0E0}~)N1!6M>E*l`rPS=zR0Ohl6^Z)<= diff --git a/src/cctz/testdata/zoneinfo/Asia/Ashgabat b/src/cctz/testdata/zoneinfo/Asia/Ashgabat deleted file mode 100644 index 8482167269080ead3a6046ae5e64b56d48dac1dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 375 zcmWHE%1kq2AP5+NDnJ+nLI`V-1S(?%VuAlauu8Jm1w?OM{MP{}#vrQRy#YjvNgPlB z(c&EY4Z!rz&kI1b#LG`$dCA-A3Lw7JnQ|~+dQZy*5MO3ZDVUa>lLn^cdcwi9e2oW~ zR>-jg(~2=#U|PvX8cZwO@PKI*?Z04JRr(#6R^z@8rqx-w13>1hfB6HZHJlLn^cdcwi9e2oW~ zR>-jg(~2=#U|PvX8cZwO@PKI*?Z04JRr(#6R^z@8rqx-w13>1hfB6HZHJrBL9J4mE`0A5WRH?cK}Ggn8Y~)5G~HJQ2|W< z{Ja1}OT7HF0YppQR#yPgQfJD+eCa(c7eIWOHKkx$c1{|Ymg@-z)ABVQU|J!^5=<+` zXn|=ZA89bHY{LVlRkZ(tX;tZWU|Nm)KA2W#g}6)o%bx&{JsMAbCxB?pip3E6$~~~S z){*mIT6@a@Fs-v>Bbe5mvItD;wM+)n`Xw!3+90JAOdG~7xBxQGsHhrD8{0O4X_KH> zFl{QE0;bK3>>>1DH!y7>odvev;;z{PkbcYGK48ApUI{SY`nDdJZ?nu4Oxx}j0MmAD z;$Yf-)+aFSkopr$JGSsWU}R!uVM2$jY-mEPY;efLz+kX}0SL4V7+4q>+yWRlfGHq> qfd@n~0!g<3Mxcm=1A~B%ZwQ07fiV!902``6pQ1;;9XoZ+Wc_%(pt052mfRZvu}W9GF=if^@8r`Drk!msg2i2Q4}ob{c~-Ev8{aoD?apA)z{tc*1_XxL r5|9y^3qY~1Wx&9}z+mCP$m8Q1!r%nN+6KlzY{I~017z9h8gl^v?09_azn&(byN03#DniGB`< pYiI#dYT>}Z#lWCtz`*C@8^WM%U~FsvBuzjp1}+;QX{T$<1pqkL7mWY_ diff --git a/src/cctz/testdata/zoneinfo/Asia/Baku b/src/cctz/testdata/zoneinfo/Asia/Baku deleted file mode 100644 index 96203d7a4266cd8646032165950374761090e318..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 744 zcmajbPbh<_~*^Jkf1m?@zh5L!aqmRA1cAc`Es*+Gan z8Rg(OE9Kx%N=b@vlJX~hzmMz6_v!b%p7-zhJ(tJbG0>+c{|-k_u*Jsx|0gzjOh8xs z51kF!ay9eeO6+3aC#Y7AnTgV{jwy*gwZac>hbes|$4uF^3Gb6a(`fnO;w{@x-kgMr zwK147*9%kq9+>8{!}Lxw%y6oq(vk!-wIY}$|AN_~XQ&d$yo8SGO$c-DV}@C)&p%-9 z$rCK-x{PQ0`q6!8DBEI5j4iX!q*#E3`oTZHN1$0g6JQVKn^tu3XFs~+$b>GvcAzcm z&9E$}h2=8_Sg{%ht$hiwa!Nzk*lOOa0t2P1P&9RuDwnm1k)C%LT0C?fn@( zfR4LmSiijnouS9Jizgy zB3yiqA7MAr$tWHn`G;F@{+f?L0kr@Gtpqa^q!0jAim6+NH8rs#|uo$^;m;x`5GNC zt&k%NrWIrOz_gP0e=x0V{Q*p?Xg>tgs?wLhv>NweFs;t=-T-92`j-b_TI0!m2M}Mg zq8&nCIRqBhI?eA55FdhJk4_BSQ%N*8)siNc%Z30D;9_DKOviw*i=MwdW6*Z+%+` z%(q!438rm#eF4*Ut-ryv{j6(X+9CBWn09RbbbtW}oLu*V`Oe8#z19jT{J7&RoYEW^VX=*WQJTkE9sG%I8GKs%0X}{8qaQb{gX5oOa6*2E z{X~pI|23I}PX>MPsmL_=ZMOuRzB)qxebE&a-bN(H0~}4MaRHp&Cgv&UKxb)M)Q(yM92Uf<0;8p%8 z_RE9Y@D)BWeC19EzG}V!zWTrfukO7EYsLrRwT)@?YnpDrx>7Z~UKK}Q|J4I;AX8vN zI1g+LgwZ!0UZZdJU4boYTj07mFPIsb2V46uv2Sy4V&C4p0j@XCf*q7P$0fM|)APZoe^$=i}(d8sp*V7~O8vI8J-nKkKPT6RtZn3n7D1k>_0R$y8o zM;lBl#>jwaB_Ccet!(`dOsi^GRN*OCe5>$lwn^9@qG!FkH;vNQZiWLEFF-h|Pi6jDgDrNZRR|aRC5N?`;DB diff --git a/src/cctz/testdata/zoneinfo/Asia/Brunei b/src/cctz/testdata/zoneinfo/Asia/Brunei deleted file mode 100644 index e67b411b9f5af9cf6b85aa51051f76b57d972afa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$V!r=Cu(pfI1w`*kckf^X%4F{WnUYz-z{0># c(7?du;~T=DZD4L}03(S^=Ujl?csXWMXCkLI#GQ8z3u#E-C-|Z~>XRrdGxVTmbC&IB@^~ diff --git a/src/cctz/testdata/zoneinfo/Asia/Chita b/src/cctz/testdata/zoneinfo/Asia/Chita deleted file mode 100644 index 9d49cd35cd5e52c5ff0f2c0cc6bd3f4f6e856915..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 750 zcmajXNhpM29LMqJHG>K1y;#RGmN6L17)vu4+h8&?A|^sgS+XUGP?EA9Ce4AA97eX1 zTr3CNP)N#h!ai<|e%S zx3K1KKJ4Vy!XaH}K8o^A($|0dj`Wj^y}*y%I@14f2mb@EpYEswPqWd|J+qBEXiW!$ z=MrFuH57&p@KDyy!LXWF7;bXFh>R;3sXT;o={Ah=T!9MlB~SAeZwD~?eqTl%)7R$o zY8l^S4`!fpa{|UK_QUw8R+unS0~5Q=P}QJ=Nwv*3ny2p4!(^Qirj*HHYH%D(Q@cC; z@`f5|Bv1D=w=ZbzryDwb?*g51{eaF~dWO246PPu64zp+1U{2!(%pE?m(Y(BZX|%q6 z6`e2dMHlF;=t9>jv>~DcZFuT|MWRxtXO+c$!~4DMedM$CRw%{Y=J* zT>f~(e}Ddc)Rhx4)>=o?I)|8;F{_=EFg9poUbJ(PPu>d diff --git a/src/cctz/testdata/zoneinfo/Asia/Choibalsan b/src/cctz/testdata/zoneinfo/Asia/Choibalsan deleted file mode 100644 index 6f5d3a15abbe48b8a4dc72aadc88c416160a56a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 594 zcmWHE%1kq2AP5+NDnJ+nLI`UCnaBdf0{?-a?eaSxkUoCyI}<>(#LE*6AX@U)pAR5f z>Wps#h?d@CPynK3*625YXxTYJV7^?BAeb*-{RPZd$o>rGD@I=f^Od}>g89nUJHUJu z?d@Q`s`M-{UyXYvn6J*V?E?c4sDIf8q8K!u%mDK>ugn1RwT@JQ`Py5mz0jC zFyB=+P=EmlLPckR`C+Vy1t5Od*BUTC{Hb#RBQq0;kbxn^1Y}B50Vqc6CNOd^FcdT} a@c8(KFlZZ?1F38EKFU(^7i7gn--0MRERr?p`IRaYgj{57BbVE%QR{b2qL zwzL9}IX7iLfz{u1toZ$;V7>;sJD9I=$w7dL5f5ZwD7+3bpl$*q3j;$z0|SSTZwQ04 P3lIl~FmM40T?;M%d{}{0 diff --git a/src/cctz/testdata/zoneinfo/Asia/Chungking b/src/cctz/testdata/zoneinfo/Asia/Chungking deleted file mode 100644 index d6b66984a2f36ae36b35e174756707aa7286c292..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 393 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%P-o_>38EKFU(^7i7gn--0MRERr?p`IRaYgj{57BbVE%QR{b2qL zwzL9}IX7iLfz{u1toZ$;V7>;sJD9I=$w7dL5f5ZwD7+3bpl$*q3j;$z0|SSTZwQ04 P3lIl~FmM40T?;M%d{}{0 diff --git a/src/cctz/testdata/zoneinfo/Asia/Colombo b/src/cctz/testdata/zoneinfo/Asia/Colombo deleted file mode 100644 index 3eeb1b72b68993e26a2452afe98a6420ac66bafb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 247 zcmWHE%1kq2AP5+NDnJ+nLI`W&04ie#Vu}Ai5Vmcm3W#o>yH^H8pN^8z0MTcrYA*oM zmr5HfK;{}QW6%K6MuiLtAlk+Ll?EddGYbNQNXZ@cHAR)FZc zD=y6dnd@bJL;ys4+uWGI$i&RV!pZ`)>a|SLOps1a$85aQihB7n& diff --git a/src/cctz/testdata/zoneinfo/Asia/Damascus b/src/cctz/testdata/zoneinfo/Asia/Damascus deleted file mode 100644 index bd1624de5148d5670e4585dfcb445d8b270c02df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1234 zcmc)K>q}E%90%}cQ`6?Wjik(&D_xpvI_H{|b6UEVHfwE1@$Qz8nFyA?$kd!~yipX` zi^w#}bXr7YM39Ui%CHC}sGt!{NxINw&KtALp6B}y__E(P=XXBm`#o%fF|MfUxRR_n zJlbFf8*c4K8feXz9$~9=Zg}pTVf$ulqK)nTvff&@Z&}0O0c{IBm@x<2#a4Jo@)jQU zZ+5f(>_rn{+f#fE`CMHb^7+(r@Iu~Qcrl7Ye@Q)s{?e)%_6C1|y;Gy`viBhT`{^${ z|Ht_nUKyx||2l|`z29n^-Oau?=~H3xDxJ0Lg5OeUW7{V?7`dyw__Z?e($G@fo_H-f7R(GR&@hdk790r{r+=Wv9x z2HyNW2aa@jU~yhF9Mv@gOY~>qt(_5WcCk%U4@Xz`!7<7wHg-cQ)uF#VJPVHXi-lts zi(ND(ai1?4+1@c7X<*H{1XdbV zaI$t9RwbQ4f0y_ftQPekPvKv65jrVz6UcYZM8SLBaq!+TvxViUkJ{1K*xQh&T^U8L z?Rbnlz2PVFjOuiFUr8Oj-*6iJ%rratS@J>TI?)PzK&VEpkJrNb1vB#Oz*CciPWG#1 zB?$PYc-h}@Q&ksiR$YfV)8HhbleeK2&R2H8 z`STTUf#@V$@Ug{3=oESkaFN3b7r#k>OL{Zm(veWOtXT?|_sEU(F=8q8hpmkv@G;F- zxT0v*$mji^mk<4!2GGw&;uSplhq6UN*0XC8WXR=+PG@E(j>r_rM4+K(tvp%q4=F%M A`Tzg` diff --git a/src/cctz/testdata/zoneinfo/Asia/Dhaka b/src/cctz/testdata/zoneinfo/Asia/Dhaka deleted file mode 100644 index 28136808b6d1029676448d8711265d8c55cb4bae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 231 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I&VwwLyklEI@2SlH`-L?TlpJ6SO0Mk>AR)FZc zD=y6dnd@bJL;ys4+uWGI$i&RV!pZ`)>a|SLOps1a$85aQihB7n& diff --git a/src/cctz/testdata/zoneinfo/Asia/Dili b/src/cctz/testdata/zoneinfo/Asia/Dili deleted file mode 100644 index 22e705ca1ab1218e9f36b9f4f607258389853c8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V-n#VxIp%FzJ~b1BgC7)93?8Kldwx0uXI^cqRiQ o6C)D?L+Kt6zo3BusIP7U1BZ`q2!pnP1rS>@aM=J!J6%gI07p<6j{pDw diff --git a/src/cctz/testdata/zoneinfo/Asia/Dubai b/src/cctz/testdata/zoneinfo/Asia/Dubai deleted file mode 100644 index 58d75bc26eec90272e97696f40483eb56c2b8b45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iWg@YBo{Kmp?$Ak7vI3@kprAq?6ECJbCQ KK+;avgbM(ceGa|= diff --git a/src/cctz/testdata/zoneinfo/Asia/Dushanbe b/src/cctz/testdata/zoneinfo/Asia/Dushanbe deleted file mode 100644 index d83fb076a256817ca0a3ec4e43c7768e6680dc84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 366 zcmWHE%1kq2AP5+NDnJ+nLI`V-04iezVuAlauu8JI0Yq)mroXeXvy1>V0o!CnP9&3p0WcVahWygU|M!g1eliV@dVTIHCA9+ zAx9fbE5^uxX(bFfb$)FmeFHC4qqlL^AUD_=YfO8<+yIIS`vMaM=KPcDklq00pK! AfdBvi diff --git a/src/cctz/testdata/zoneinfo/Asia/Famagusta b/src/cctz/testdata/zoneinfo/Asia/Famagusta deleted file mode 100644 index cc44179564afe36db0f1f7aab0a19cbc3e4fa4d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 940 zcmb``OHUI~7>DswY8SL1MbwH@E?N;@hjbY+a`V$uJW0>St`>?dzp(9{rBz z1qlJR4s^nW7qjq|h>rb5O0mwjv#s(Qc$;Gu&$kz)VViLhw*4M~cPtLW#a}MNJKtV{ zg%=5p@v%=2>C}?@F}O6@2bbMG0++{w@UF8icz4JNJ6iJKJ)#A!5SHP+mJD2JvV<9* z$`x}jwdzL(cFr%su6Li|>SuGXn0^YoC!WBb#9g@N`Zz2_2jJRsGdknrRqkk1xizIz z>)hAi`jV?~gZGw|?l)uy(MDk+MQ&WU0Q>&kfSX?W;pVTW;FgEy(bnfp=>Cy5^uRqk zdNAfd+Y&x2op-3+1pA``e7NEl9Pnr1cGE{V==cT)mw%#1jkD{W`+y!>oJ5b$JVHaC zUZ?1MWh@DIOh14-`}^T=atJ=rGm4&!_o0z}aa0Wj(JosD+ATWQ`$s~1v_Xx|KfO|A z%`yD{k1>a_vU&Oimt^4o3VS)rr8UbBDJlyDBJ`!QYDs2hzHoc#mZ->{dXH2ii%PA8 HRh@YavF)T6 diff --git a/src/cctz/testdata/zoneinfo/Asia/Gaza b/src/cctz/testdata/zoneinfo/Asia/Gaza deleted file mode 100644 index 0d79662716b445f61e5577bdb09e7c91e4a40d28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2950 zcmdtjdpy-=90%~nbQwx(U1t)hq}+0ehENotBzhrnDwiqc7%L_9ODLC-+#_s6Dn%$= zNT*y99l4}v>)56ebxul++3fdxe*1g=-{Wd`>Zaa)Wb?(pasIG=K2n%)4B1kYk9-sn zhHQ=LWax8k-X+L(e>t4LTCtNy&tHAebfEcK?mGOsgV#dcKQJPpIZ&|&^KXPl;J0am zu(+g*PkYIMMGVb%i7(I(y1Al%AEbc(gK-@CA?FJq(?LfbepC5`9A^$3Ap(*q6HIJrjfgU`gZxo)XvK6T?QiuFHelJq7`VSFd z*S!6QFt5}!hV%Kn4BW3AUJ9$&RG?qrku74!iK_B8^b6f|&@Uop@M5_)=odeJfqAul zA-tqU8ohe^0Opq#%}2lNrZ;+xXen4Ta~-VZS%i7*P<2?xx)#08%gOL^ueChFE?o-& zQqOV;QePz>X|PZhxk4%mX*hd3(rA(;?ll?<6A^Z;6!UQJH_ts`W8rGpTzBXxeSBLT{fu3~w+H;J%H)-8|YmY)ur=+~icnqv>dwi+;0y z4(w#(4?E9l714f+x;xId3<)IEE;AZomyUec_5DTIts)BE+7=JHpIIX!?Alhg1NV6x z-j8$7Bu6CA!xgzbbRKetS)7QlYp1&h?(wqopd{WV=CF_IM26Z|aRKZ*Tue#69i0IC z)hocex?jM%3r1o8T4_Gr?1}mX-kaYG2l&*${D^uuaN{$E9(?Cj1P5tX!@-uZ@b}Yl z;eDEg5<0g}91e#}jfO*nUhsi8yWxYE*TSLA_VA(forJEiydgf#!y#5Q$dQ9t=ouF^ z_^7oE9Bw27A5$vDe8il7IATBvj?}1wBMk=OD5=Q|J%|$2;`yi%?howoS?%bLi~7)? z$k+p)XzAiSbQO-Sc>u@wbipx&;p}aM#B`*?vAMZJlxGx;D8N>&D zhJ`#s4>DfPLx1{;E_}LE9?p~xg){5M;H*@6fRw3#?XN)E>qw#RTa40@GV>+ zEe&5)k(JQ7tH1Wbm1F>}6x74lJCiYgVhv&`NFA=?9nLjKT%YpA2PGRW5U7H~Ip44+l_x==ao5oHPA{1~xKjH8@^eutin15vQ z4*jEyWt>|w;MPr5aGPQq+~$+cxzHTXw=d6u+ea(VcbJ;<>82x?`~7~ba0`C?EDe39 zY%$zv>&$s18-8-@0Q{uKNkTVIRYn38EKFU(^7i7gn--0MRERr?p`IRaYgj{57BbVE%QR{b2qL zwzL9}IX7iLfz{u1toZ$;V7>;sJD9I=$w7dL5f5ZwD7+3bpl$*q3j;$z0|SSTZwQ04 P3lIl~FmM40T?;M%d{}{0 diff --git a/src/cctz/testdata/zoneinfo/Asia/Hebron b/src/cctz/testdata/zoneinfo/Asia/Hebron deleted file mode 100644 index 53a3c14312bc770bf9bca1d2e7518763fec7a485..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2968 zcmdtjdpy-=90%~nl!h*A-Ay8ulv{FZ6pA90L@y*xB~~fNSShJrI+V*u?h!U3NfAnk zq+AjmxumdlY?DMeDK)0q@A>@p_x!)d>-aqH=kxtNFE0-4o%edIB;zg#c7nd>vLE*m z2|adfBKw*(#;(A!jq_;MItdAKBn$b_Acdi>@9sl3T=^U4k82hng;A%FjX9afCxSp^ zQ&<~ApKIQek8JUh#rZ3}-8_2!>Vvv1&DXNG;Mc9ZM(V!)5i!mF;scm}BRm1WO&Ej+ z@(cO27av*7(0mvD68)gF6Z-eQa_B!8MxY;ZNP|BrOou<|HDUhKm^tQ$=Sra;?y7@F zhF78gOJ%Js{XTwqEL?>AoZm=O`r~UJO_{8f@QmJ3c&5^Jq})g~@|(zmNcr+VMTA}R z4m>9!LWZ$4)^7JL<~0LUVJ(X)^jbZW;1%xcd4yfsrj^K* zW=oMeN|{LAMKVY|i4dgz?43vhDKp$_Fcv5x>{>Oz!@b|WaDxqnYhk0irts=(i{LeB z%CK>i6l`*0B5dk%61mp32f5DlrkJqHOg)Q7)BNktwlvpIeJ(=2^5)ar&_5TpD3wBQ z`Dg^*m~O;lYhsn#30v~dk9h_Gu% z;V#_gdi*fX-D2#JJXa^=&Vc#IUB(e2!miyeuDHkD+Le;*F*1QYlqWLOp7IM}&*3~u z^4;hJcyEmyyszUWygzFc_NtQP)6Id9U*Ut9-LSVu1Xt05gCGIA41!fHKX&(1Cr$J5} zO+n8%s=y~Lq~Ra~Y50^v0pSImUC`Qf}6IK!Oil`aI;4u=WG)^-?AbNZW%2`-@4j_PdBZ8-0$~OxjXRF z&II&rGI?;Dl>_IIRQTDQBk;2>dokTSR~luI?F{<%i*a!K%~8$+d*P1TyZB#7jQ24? z@;^Vud;EXd6QbBdzr)M4Bqk6duSnQ`5bS;m_S3Cx?1{PgR{F`FSemgfb}z$1U7H@O V*{syi(a_P<)l#!rq4n=p<{umC8mj;R diff --git a/src/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh b/src/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh deleted file mode 100644 index 86e21b0f524426287fb3b21a82369283c4040c0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 236 zcmWHE%1kq2AP5+NDnJ+nLI`W&1S(?%V$uIV(9z@E1)?V|*5(4yXHB0qfar^n=L$gd zC2PA6Ao{A&ZUGSeWZS0+Ao{KT43KpUT(-v<7@3$^n3#c(fg$-DNDxS}Ffb$)FaWJ8 lXkg%FV5pnGAn4;8!Vmx=v<=LG*aC;TbMoi>Qv;@<)_(UM|O=&QF`|UR{ zeP_pCFn#yz4KRIgk(33UG30Oo&oxL^TN_a#FJ%>Sye3C#cI{sqkcu387?{}4?C z^MA4?fcZbaI)nMYo;rc~zwgDb0GadWT-**2{db=unE!8`1DOARp7IJ%yfXAD?Eq1X zb*x}MQyvSL&m8+4%xCd^2IjN6vuJ?Sv6(YlfM|BLXJ9^ivn`m<$#w$F=lpgY%;$Qx z3e4xewi3+eIo1Q_3(mF#^M&$rRxmO#voJDI2pJf%xj+soXkcJrV5pnG$icu+-oeNV dVlxQ&_=Yfec!O{-hzJj1@B%WpfI_+!TmUPfblU&` diff --git a/src/cctz/testdata/zoneinfo/Asia/Hovd b/src/cctz/testdata/zoneinfo/Asia/Hovd deleted file mode 100644 index 6e08a261274e48f93eb5e221ba294e54ca671b94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 594 zcmWHE%1kq2AP5+NDnJ+nLI`UCnaBdf0{?-a?ed=~AbtGYuNHu4iI>+VfN06v+#rfU z>P$44FTKaE0mPSCV+-cX&QSpK<$C17eEAwCFkc~u5zJSNegftzc|Qj8m939~`6}8+ z!F*Ne6=1#^_i`{_o#iM42&jKKA^@T_o-7AZ44PM#f%#fTI>CJHEgfLK&XQ~}Uw29t zn6KC33+C&W_<;EaDf(c(VQj_(5W~pVy8%QS+j@cdCc3&{zNxGZm~Y0*59V9FJh%a* z&U(wP1t8jH$xblecFG(u->zjgm~UTF2j)AZ)PnhrAqilp{0Sdu7dIpjuifeX1<4tH{e zBqim7T8artIo`MtB_+rAeRfHCzW(p;d*1K;UW>J>Lrecg#7^+xvHbr_89U~~Cit7B zZezHZyATw(!(Cr=N%%cdWwV_dBAa>QhWgHMDD>^X#+5zn+qq#EANU^bG^5M6tq#5) zu_D08c|DApP{ZiKD5&TTgfR^SV})lJS8xmCRW6ty--C(%>rg4aQ4ovrbnvstQw)o*{C2E^JFr*ML3g) zJj9-VJYIiq|32z1CTia0x3ZPJx7f&+XlP0lKxDI%gs&pD4oy*j$!wu2HY!ann>;o; M^3$`mNUihx0nK!Yq5uE@ diff --git a/src/cctz/testdata/zoneinfo/Asia/Istanbul b/src/cctz/testdata/zoneinfo/Asia/Istanbul deleted file mode 100644 index c89186687300068ac4e8505cc0012a1dbf6a9960..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1200 zcmb8tYe-XZ7{~E5FSAXTNrVmOrEG3GwK*+k&CQxqv}sGHf@y>|j6@_03WZimUM>(6(qq%OZe?4YG+iU~q@#8%7`<^tk zL+gW{&{qJw{j7-*faZ4j>uX9k_rVRLpDDSEXC!_7&UM|3ozBb%#WR9z9=R+a^~>r-L0 zN(y(x3!zxVhcSU3DDjsx(ETOutx)=n2V)(7VBE_EC>xrA@s_tRp}oaL`x0C4qIaIW z4&_ysVN&@M%oQiPU~+mlOer`6cZHkaZpC4*D-}=~cDjM?tDMb5r+G@zd!ELi_fD(O zDytTzKaPOv3u34-Gccnj0PbrQx#)iTb@OO#@~ diff --git a/src/cctz/testdata/zoneinfo/Asia/Jakarta b/src/cctz/testdata/zoneinfo/Asia/Jakarta deleted file mode 100644 index c9752d2f23ebbb8b1ca5b8ac604c6f24be5d0def..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248 zcmWHE%1kq2AP5+NDnJ+nLI`W&04ie#Vuk-eV4voh0HRk`v_1gQyTtB+`KR|ccYyep z!rm2t=<7DeI6(BR|7r{%`pedR9gIxOEX=ITYzz!33PAHfBntyWx&i~xhRg~EJ_d%m x2@E0(3LKOf2 diff --git a/src/cctz/testdata/zoneinfo/Asia/Jayapura b/src/cctz/testdata/zoneinfo/Asia/Jayapura deleted file mode 100644 index 7c22f539d948e5757a0847892da344309b582473..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 171 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#Vxj*)uuJUV3=n-GV&?}C{blQ-3`QoPlI9m6 m8zf{-F9D1(CrU99|M z5Xur7gV6;m3nExibc5xVNz1Z4UA)vL*oUT$($4$ri{JdxJ6?Y8?|J@b=kVGc2OD){ z(Iwy~=%&lQ_#+4Sv8DXZnCDmR{U>osH&cF=^5xzj0pniqRem>1Jun&pU*DKR-v2@h z20Plokk13YIeiKoI3H%|b8j1Z!NEf*$iof>9v;~Pf3JQDAClC=Kcr137zu$N`}E-O zgF^5VcM<&D*U!@bAMrc_x%Okoztkq)|JC1!{F~8<{JYx(A6;1jA8Vch$I}OpPbh9C zIB|krBN4Tm!{z3C=-1Y{IhwDN?MJ`f!Jywjir|WrN%V?$W0>C<3Bor$PC}nO7{z>! zPl|r?!v^%qa{_p7S0!BK^kH6oG8@jAo}t&6F2l72P3U!+yDq{nedZi`LwYCN@XL!n zPbgw(pBEGyrp%8yS;{TLvmE8t&?NG0w-WbLaIFVk*mK84`|WM5@S>Kh9QER(MtF(M z7XDxOx4KClt+6fq{jA f!QO*`!^by-LEFFtgpCatxNN|*ovw+Mu>ltVLVFjF diff --git a/src/cctz/testdata/zoneinfo/Asia/Kamchatka b/src/cctz/testdata/zoneinfo/Asia/Kamchatka deleted file mode 100644 index c65155402db6a465c05a8cd71ec7a0fc0f792762..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 727 zcmajbODIHP7zW^P#;6HJL%Twx6>Z1*%dcZcvD2n;WcbJc94jT5ibGl*A3aa^Zd0X&`#IGtSEA5t{)p zazO#3#@}Fc|09g)yo9k0Cos;q594(kFhM;J6T>H9lJ@{qDI9miqI#W!$q%zHyr=X@ zZZG;VPjz)c^^OImt<*q`tq7)%XkkWgEY!C6L&2iA5{uXq3Ns61U{>uX%#M`99O2gO z*8|KAd%q)=+?!+cypL=2e5V6lcXfzfutx(18vLr`iRgT=#(R$?hB>p(AU z9z-`Jn$XKio6yTW)6py94d@lmMp)^Q|_xMZz@nzQ7f@#?~dSF_vM;=Ve*9d@V zg&amOtr-0YOe=Xm2Gh#cSHQH2_E9jcD!mO%t8p&})9Ngj1wiJje>noCHJ%(+0P!^| zvLW=9WngiwBh$gO_LdGXt+S*OOzTd`0@Hde(O_D?#0N|pq}YOK!`O@oAoGlhoWZoQ ztrwU!2~q{qrm{L<+RTU@LjUCh(-zVy0w8@BcRqmmmcQA+e5*Z|zRvAKwrLZ37DiZ9@YfZ3(0e8MthKEIVCGE&u>Lg9`uv diff --git a/src/cctz/testdata/zoneinfo/Asia/Kolkata b/src/cctz/testdata/zoneinfo/Asia/Kolkata deleted file mode 100644 index 00bc80a65e9a7aa470d63fba1ce1b29ef173d922..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I)VzK`~ptegw14KJNe{BGw+vo1t1)@*g?g5LR zVJ(yZ@y|>(S^=Ujl?csXWMXCkLI#GQ8z3u#E-C-|Z~>XRrdGxVTmbC&IB@^~ diff --git a/src/cctz/testdata/zoneinfo/Asia/Krasnoyarsk b/src/cctz/testdata/zoneinfo/Asia/Krasnoyarsk deleted file mode 100644 index e0d4fcb5c3d781943a65dc53cca9fab5d1905f9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 741 zcmajXTPTBJ9LMozHd=<uk1%`m8Rje;K||XKG!Ea}*}U9>4Rl`1 zAv!;57G03HiY|2TM;9q3&_ypZutaEfdfW?3?<$~ay$Y5&x;Qq!d`gSvO%HN`(Cwd} z=>O}#Pu+!tRQs@@d=n87VzCOugfv@-7dr*?v{;F_tehumE{$#--CE+ANzd$ft>-T! C>VmQW diff --git a/src/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur b/src/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur deleted file mode 100644 index b396deca1927d0cb76b903f57140274594434871..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmWHE%1kq2AP5+NDnJ+nLI`W&04f7vh5tZMXBN5&M7K4!E(X!N()}iY=mT6&5Gf>51_iApRwf+z%jo#3sIDU}R!uVP#`wXJCjA1BoTZGO#c(Bo%;6Pgh{%0g((q yGP8m~h=HMQ0)qqtLqP+BjE`>!Log6)8<>NzkpYM_29cIPY{9@~10?NqEw}(}OFg~- diff --git a/src/cctz/testdata/zoneinfo/Asia/Kuching b/src/cctz/testdata/zoneinfo/Asia/Kuching deleted file mode 100644 index 59bc6e40b7bb0b4eb199dd8c17f416ee00ca4158..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 320 zcmWHE%1kq2AP5+NDnJ+nLI`US0xDw#Vu}Aiu(peB0*Ky~?%n~S_gAYofa%ZD0U-Kd z>>4ot;ME0S{$aZZ3?T8t+b&-K(MJ`8!SY9Eu!H4~GrEK2k5^iO*zBf#>PJaRuUGBcq-7G?&9^a7BtGAkHZ7#KU}aNed$|31nF^aM=L)cDfc^0DJ^|K>z>% diff --git a/src/cctz/testdata/zoneinfo/Asia/Kuwait b/src/cctz/testdata/zoneinfo/Asia/Kuwait deleted file mode 100644 index 5c7f106a35195a2386041e5cef07bd22f019a7db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iV#E77zCD4_EPq*=>=fyKu+ghAWDn1Ra% KNZRQda{&N)^$pqp diff --git a/src/cctz/testdata/zoneinfo/Asia/Macao b/src/cctz/testdata/zoneinfo/Asia/Macao deleted file mode 100644 index c22f75e42db6b12db3c837056436cb77d176b83e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 791 zcmWHE%1kq2AP5+NDnJ+nLI`Vd2P$I)Vv+wq(3%R8aeg#PW&$+lAAo}kV80sc4@PJ500UzHG2It@q25mzF25kdN24|NL1}>n0t_2qWpKFVf diff --git a/src/cctz/testdata/zoneinfo/Asia/Macau b/src/cctz/testdata/zoneinfo/Asia/Macau deleted file mode 100644 index c22f75e42db6b12db3c837056436cb77d176b83e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 791 zcmWHE%1kq2AP5+NDnJ+nLI`Vd2P$I)Vv+wq(3%R8aeg#PW&$+lAAo}kV80sc4@PJ500UzHG2It@q25mzF25kdN24|NL1}>n0t_2qWpKFVf diff --git a/src/cctz/testdata/zoneinfo/Asia/Magadan b/src/cctz/testdata/zoneinfo/Asia/Magadan deleted file mode 100644 index 16bac8444656c393288dcc0209a96c7c3f487a19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 751 zcmajXO(?^09LMqB--dZONO_opas?UtyoCSdw^v^3xN{X+ajbJv$9s~Y zaxoGnOiN(m=sQeuJi+Al8<=7_g(|}#Ox0|{G=&SMhfP7X^uR~+)$bcH<8gzMWezv` zy`IE<*2xIe>^WfeS_jn5+hESP3FZ#vLS0W16g#a>8l)do!@RN_nBN=%3zQMCP<-+G z^#+R-!9Mz~`0g5A^7)J|Jw8AiZqLxh^($C*v<*!Yd$8O!2P=9PVC9&{N%N}A!|3Yn zS#(WW8`@m$MArry(RHe3blqz!te52by)eLrhiGWoQ9|pv-beFoGv8>t#dA;HqF7{t zB;b#q^zZB6PXh%BV>4YeZF+@C8FPCD8Dp+p7EY(YPq&xJtTsE-h&sOYe2Xm9$WN12 H6hnUiiV=;I diff --git a/src/cctz/testdata/zoneinfo/Asia/Makassar b/src/cctz/testdata/zoneinfo/Asia/Makassar deleted file mode 100644 index 5990010b649745369501c7641c401bcad4345b85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V-n!V$uIVu<%pt1Q5MT>?)W(-67im;$I4TSHQ@` z3{;!{0c0+a1hNYn7&sUh>LxJofY|~*z99_0K&)+G0mPOJ;hrIm3|t^m*MbWGa>yuM diff --git a/src/cctz/testdata/zoneinfo/Asia/Manila b/src/cctz/testdata/zoneinfo/Asia/Manila deleted file mode 100644 index 145bb6fb162e192da18e0991c00578d43475b384..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 274 zcmWHE%1kq2AP5+NDnJ+nLI`W&11e($VuAlaAoB2z1cTzUGxTV7}Io^I*RAmUCdf&XSE_zV4I_V7^|| eh!6%YAfamn;_CPs>zV2q=o{1flEe~U*aShKSK|AeDs0@^`d zTI&+Io4LDkFQ<1TSk*Pl43Rh)BviN(1V67wn3Cr!{15YpSR~=6waC)_b{ESL8xAO2 zE`^cPMi@1m1m&GF7+n_#W6HcxVSIU*e^UcflfAyo0-G;F`>;||6@-f}D_3{LvI zJivY8(Kb}?IAM}=5hgE8z?888nA+D4H7yR9RzK!q`?Ng`Fg>>oW>n?FOj$A1X%#-d z6QM!MY1li%jTkxWD+W1x{}tKj;Unj)ieT>E6Euy#z`Ugs$hDrs{Lx1j+gD)OLN+%a zBNr;?kuBymovQ;sKY<-=BCH|d0&w63$Lj^3`tcK;MLmb<0o3Xfg{(gUa{J*b% ukJ2$hD&1_Cy^-(<=^o(;32EvkVs`Sxh8H~pmuVFlfF~oS3zR0WOt%xKc3qm%Mu#l8Ala-`A z7Me0)Iax?7CLuO92pf6c`=70vb36Cf|K9W6#V0oObZW?D32cHlFVXcU1~%r-+V_{$ zhC>$3-8bKbvorEn_AhV)f-D>g^f3FvkE;o8(BmcUWezVMDcIhKEVp*=@Eo#L4;5?W zFmz4_!^RU~c&`FRH2J_t(=UwDy})SI9gLBm!&t8qsFXgd`TNTETNw9nqvtt(WY+1$ zG0qcCccE&};`FDAk5Qt#$5R=Jae5mftr)({>xIu#f7ARpq=9Sv0-j zf7LD7ZGyz@pC!eyRB*i{f`mP6< Ieo~g_AMfvp!vFvP diff --git a/src/cctz/testdata/zoneinfo/Asia/Omsk b/src/cctz/testdata/zoneinfo/Asia/Omsk deleted file mode 100644 index dc0ed422f6193fb5d7dcb59dd0eb3e06eec8d4de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 741 zcmajdTPVX(90%|-8!eZT!e;KwFyn8Sx&Oy5jSXo@qBOS@B}s?};Z2e#Ng?ti<+cZ{ zOnH(-$;(m-4<1b6MGWVB_ekyg?{_|Z&;OkN)8E$I)1@YUBcLbPu-N=x(a~c;bi#jV z*7tb_^Kj#ZWA`H!<7><)$zC`!TD+SGKOX0plBb6?rqnIP`{~w$8fRg{* zE!4_tc|xPTjX^K^fm1`sVKaXTOPwhP^QHH+TmZ?-tSJT4vUAeFv|LX(n3k{c0MiON zmS9>jMhi?U`ACClWg8wat)l%GOsh)&c>pp`jr%Q_R%ew=0P)qoa)D`$C%?h8X2oI% zedS&N0}yB(xeMlNZ#f61b(ZW0)4EeOfN8y!gQ6B3*uwXKk%^gwnF$%PvVkBIgu+5HF)$dYFaUv;0RsyI zgIfRt2QVolF!F#%1|aDczz7tva9|Md@eN_nHZTTaQy?}2ViN`~8z9e4*OUtYB|>k~ diff --git a/src/cctz/testdata/zoneinfo/Asia/Phnom_Penh b/src/cctz/testdata/zoneinfo/Asia/Phnom_Penh deleted file mode 100644 index c49800e7ee4dab27f9c0c3ccc1bbc16cec8d63ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 200 zcmWHE%1kq2AP5+NDnJ+nLI`VN1u6q!(f>fu(c`KDq9-oa<^s`YO`kP@=!=o(3PAKF zYr7AOOw24y3=ByzAPbVeF|YvH1q_@F3pSlhtd*Z@dc0m91uO}nb;2yeMvvD0Ax<+IVLb2 u^`^9dk%^g+nSr772}q*61Ejfb0s{w_WbyG0Vek$PVekTCE+9kKk_!NE&?7ql diff --git a/src/cctz/testdata/zoneinfo/Asia/Qatar b/src/cctz/testdata/zoneinfo/Asia/Qatar deleted file mode 100644 index 7409d74983c8d0cd8347a663c3bfbc1c041124da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%u<+Ad1CTzJu1N;4yNU6JixR< zjwP5@jL`zqNFW`X}y-oU|PSV1xy>Hl!9r)*aa6r<{1@LgK1;i zCNOOh6bq(JWmCYknUOt&{_6&&Eu>=tK>951YJmBczwN+$tG!%czV&SdFyCgGI+(WI z%><_H+Bm_q{j4Wo+9CBdn09PoxBxOQ^}#U(MkZz!W+rsV3KYf#S(q3Yte1e@_=YfO8<+sGDG-}6aM=J^cDklq07{*2Bme*a diff --git a/src/cctz/testdata/zoneinfo/Asia/Qyzylorda b/src/cctz/testdata/zoneinfo/Asia/Qyzylorda deleted file mode 100644 index fe4d6c6d6d44f0f6b7dd1f55702c4d640270a1fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 624 zcmWHE%1kq2AP5+NDnJ+nLI`Uy0V-nyVuAlauu8IR0f^qZ_^$&{j6qbrdjp6TlQ^IN zqQyBjLg=5L7l8N@FF%3hC2y;P#ih=agZa{XS}uU(W!98}Y1uhxU|Oyx98AmCcz|hz z97`~*7^4NIm3*YZw6YBkm{!sL3#L`2-+^g0?)zX`os~NPWWM^BKVVwp$?pUZU$bH= zn6G)|f&+-Jb>uvluf62}nATac5lrh&Sp=r_S|)>O{gM_iZIDt5rVV2kTmb1eDyjz4 z#T59V*uroDWL}K)jRlNM%q+}I=#Z5Oiy%}H3ljr_Z30NY xg#!Z%1A|)t0|zioBrx)TNCqJ37Qo2i;~T=DZD0b#ra)}Qz-0qu+3A{c0RUQhZm$3U diff --git a/src/cctz/testdata/zoneinfo/Asia/Rangoon b/src/cctz/testdata/zoneinfo/Asia/Rangoon deleted file mode 100644 index 14b2ad09ead50a62d5e2b426396c51f9beb293be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 187 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwq5nV-wypCbh+g=qI1ogi{`5xzL|>eh{(+H+ znTdfRN*`n{kOb<9&S2nRV5pnGz~|!|!Vm<++6HFE20+r1fy)NWw$nAUGB)4>0PImF AssI20 diff --git a/src/cctz/testdata/zoneinfo/Asia/Riyadh b/src/cctz/testdata/zoneinfo/Asia/Riyadh deleted file mode 100644 index 01c47ccb86ccbde2bf9ad0803298e8df87178a34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iV#RoZL|P(b?(NVAp!1B;Ju2!pnPF$0$k KkhIe^<^lk6It`Bi diff --git a/src/cctz/testdata/zoneinfo/Asia/Saigon b/src/cctz/testdata/zoneinfo/Asia/Saigon deleted file mode 100644 index 86e21b0f524426287fb3b21a82369283c4040c0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 236 zcmWHE%1kq2AP5+NDnJ+nLI`W&1S(?%V$uIV(9z@E1)?V|*5(4yXHB0qfar^n=L$gd zC2PA6Ao{A&ZUGSeWZS0+Ao{KT43KpUT(-v<7@3$^n3#c(fg$-DNDxS}Ffb$)FaWJ8 lXkg%FV5pnGAn4;8!Vmx=v<=LG*aCnw=@)4Ef9!L(kB9hlZH(FfB8DGFfPFxIC4WROvjI+!-L z)dSNeLE;S{aZ_12Fl}b|6GH!G0Mi!IVnA6228%n7zsz zRwO|dR@{)8m6?H|^#sWDx(N&{3=As{Fmf<3%-X=f10orLWX}Qy0UzHG25kdN25mzl TAT|VI0|qV|Aj?kI(2xrNZF7bJ diff --git a/src/cctz/testdata/zoneinfo/Asia/Samarkand b/src/cctz/testdata/zoneinfo/Asia/Samarkand deleted file mode 100644 index c43e27c5d4bd341649b3aa32de068d76618c81ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 366 zcmWHE%1kq2AP5+NDnJ+nLI`V-04iezVuAlauu8Jk97Jzj{MP{}#vrQRy#YjvNgPlB z(c&B%A@tAB3qX8{m!H7$lDE~t;!;4yNU6JixR< zjwP5@jL`zqNW6Eh1l z6DDL}usaD-YvI7a!oc7bz`y|vmjp&05Xr#f;~T=DZD0b#ra)}Qz-0qu+3A{c0RW;& BJ`?}| diff --git a/src/cctz/testdata/zoneinfo/Asia/Seoul b/src/cctz/testdata/zoneinfo/Asia/Seoul deleted file mode 100644 index 1755147fab44e07b7527ce1eaf3ae991473fb222..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 415 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0$VuAla(0%$Nf%!Mj>OKJRZ(Z*KtGm6HAI!h=>=BrMx9206|Hxkx%zu)-9c=DXVTlZo zzGq3yVEdj6`n&+~U+5Qr`7fS-0n5MQ4+8UF9lr+VzkY85=D%6K1I&MWUJT5C*FFo( z|6p2J0rI!P;)DqxS}`vjOe-}zfoWww&k2l7EX+{I$chBPVhjxB93YM59SkfC40RJ2 mfV`dsj67gAP^5JRBae@72!nTU2!j_8d%J`%Z~-~GmRtaloVXbP diff --git a/src/cctz/testdata/zoneinfo/Asia/Shanghai b/src/cctz/testdata/zoneinfo/Asia/Shanghai deleted file mode 100644 index d6b66984a2f36ae36b35e174756707aa7286c292..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 393 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%P-o_>38EKFU(^7i7gn--0MRERr?p`IRaYgj{57BbVE%QR{b2qL zwzL9}IX7iLfz{u1toZ$;V7>;sJD9I=$w7dL5f5ZwD7+3bpl$*q3j;$z0|SSTZwQ04 P3lIl~FmM40T?;M%d{}{0 diff --git a/src/cctz/testdata/zoneinfo/Asia/Singapore b/src/cctz/testdata/zoneinfo/Asia/Singapore deleted file mode 100644 index dbbdea3c8149004cfd525a0fc26e5da72b20e8a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmWHE%1kq2AP5+NDnJ+nLI`W&04f7vh5tZMXBNB|M7K4!g6Uo9eiK0a16)rMK=i52 zPr>x*iSZmD{w0sx40Pj65Kc0Z3+6 wFbFX))JI+5H>OZk;Wj>5{NArxNLx=ovsBJ0BYwwz5oCK diff --git a/src/cctz/testdata/zoneinfo/Asia/Srednekolymsk b/src/cctz/testdata/zoneinfo/Asia/Srednekolymsk deleted file mode 100644 index 7fdee5cbee2b1ba0904a672dde16240404466fb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 742 zcmajXPbkA-9LMozHq4)clo{Ln8-^MC&HUYr`M1~>X&1xEpJJCK2XVwf=FdS6ODJSC zau`WF?4TS-k{p(U!eJ>bxsc*{K08u-*7Ll2KYM;(n|)+hL!vGoeZe+cw&9aVx zQ-0{$&!~829&dRb=^aT^RCh5&Vn=|PE*!mqpBs%#acCX?X9RBptTV6VXo+9#WG(gP zLfKj>%yRKz_S6T=alF9X-g}s5zJPMwDa=>y!2*dJ7ADO@h2SL2<|{sSVbSw0OHw@1 z8S!oo_a*0(Q0a5P((OK|TCu{i83QaIFNf;E9LV)soNSP0OaUwE%b>P90anUVU={Zo z@%tUtNaDlnyPAhPbnRCNUFSbR>w=eP{mw0{KRbYiSs!e0FTuv4RcM^{I@!FY)(Ld; zz#_V(z>aQhcB0#2^=Om48*O^)f$e;4#A_YwcoISLp$uBCG+{R1y6}UxnZ1uZe#}2V z!T;BPpT_bDS(dV)u1z8!#1r5N32`5hWOnlC=?M^_#cCr;PEEIlZjL1C>1j}LT;eYf CU5tYO diff --git a/src/cctz/testdata/zoneinfo/Asia/Taipei b/src/cctz/testdata/zoneinfo/Asia/Taipei deleted file mode 100644 index 35d89d036d07c3f28dec64092ab1b533c21ae2bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 511 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1S(?zVuAlaP;%~r1c*Ky>e&FIFNH*c>C4^KVET&F z+7BS{tFB56Ao`lmelY*K&3-Wd23uMINc^VkC$RdP&u4<=Z~a#T%ilh67A$|~0mR(9 zs~EuY_lk>Q6a&ZGE-;_-Zf66C&vkC^2M{fIdtn2J77Dprz{teNOcZ2bD0~6ZRL}s5 hfVv3`93YaB$HzB>!8tgD!3&6;T|yYRfE-;5E&yjg_Y?pC diff --git a/src/cctz/testdata/zoneinfo/Asia/Tashkent b/src/cctz/testdata/zoneinfo/Asia/Tashkent deleted file mode 100644 index 65ee428ce1c5093a4b3dd29512d98a33b4c753a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 366 zcmWHE%1kq2AP5+NDnJ+nLI`V-04iezVuAlauu8I-6GU%a{N4bhUsSzz0f-ip*dzd= z#W^-Afa#x4CxB>)mroXeXvy1>V0o!CnP9&3p0WcVahWygU|M!g1eliV@dVTIHCA9+ zAx9fbE5^uxX(blVPk!oZMJz{mj%mjnhL5Xs2n;~T=DZD0z-=0I%5z-0sE+3A{c0RYJz BJ^26t diff --git a/src/cctz/testdata/zoneinfo/Asia/Tbilisi b/src/cctz/testdata/zoneinfo/Asia/Tbilisi deleted file mode 100644 index 247caa631ab9964c1de8b35294fe4551a9167af4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 620 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1}b9%V$uIV5Vma>BZyulISWibzr_;(GDlQ><^d2b zCUMRHM2mBrbpX@97&m}uiB}8AaR*B&0tz~P6?Qn>q!OE z@-<;#S|P_BOe@A%fN3QkO)#x&BL${abhyE^s`MW)t;YQpOslg>CNKbj`d2P6t?`tz z0L0h4axVZxYaKc00HU?G902ommMjMIb*C%>^YvOIaGB9nB5@`Tb&R`fj=>Ui} z33A*3qD^JP4uEJgBV{n(?5_owZz1gfR&Q}v3e30stpw&yBD$hrzJ@{>n6GhrE|{-*dJdSc zwNDAm*Isi0tY2q-m<33mZXYvPUaz4OEU%w$4wg4a+zXaB49Eh@8##Rd%NrZL2lGu- zOTm0o5oNG?Gq#mr^=4ng!1CtL?||hku62RsEl&!7<*jz|gZb90r-J!5vz)-{ZF^3D z)!S8V4a{g5~|HtikgB885){0nvG2`9SYnFh9ulGngN&vkpAfzV%un<(0`rqB9)Q&+Yo}Q-GBdHVurf1I2pJd*z*YlE76t};4@M3K215%5 vJ_ZK207el81`7uU2_N4Oh7cguHZU8zf{-F9D1(CrU99|M z5Xur7gV6;m3nExibc5xVNz1Z4UA)vL*oUT$($4$ri{JdxJ6?Y8?|J@b=kVGc2OD){ z(Iwy~=%&lQ_#+4Sv8DXZnCDmR{U>osH&cF=^5xzj0pniqRem>1Jun&pU*DKR-v2@h z20Plokk13YIeiKoI3H%|b8j1Z!NEf*$iof>9v;~Pf3JQDAClC=Kcr137zu$N`}E-O zgF^5VcM<&D*U!@bAMrc_x%Okoztkq)|JC1!{F~8<{JYx(A6;1jA8Vch$I}OpPbh9C zIB|krBN4Tm!{z3C=-1Y{IhwDN?MJ`f!Jywjir|WrN%V?$W0>C<3Bor$PC}nO7{z>! zPl|r?!v^%qa{_p7S0!BK^kH6oG8@jAo}t&6F2l72P3U!+yDq{nedZi`LwYCN@XL!n zPbgw(pBEGyrp%8yS;{TLvmE8t&?NG0w-WbLaIFVk*mK84`|WM5@S>Kh9QER(MtF(M z7XDxOx4KCltL@ZNizm68z5L@ZNizm68z58jufuR{>FhkD*MivH!x(N&%KE5FgUM@f!9Kyf_ IBy=sg04jJ!hyVZp diff --git a/src/cctz/testdata/zoneinfo/Asia/Tomsk b/src/cctz/testdata/zoneinfo/Asia/Tomsk deleted file mode 100644 index c3c307d7b99f39328cf289360526399c55984af6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 753 zcmajZODIH97zglk%~g|`G#k$`UW37SjPV*~a2aDT9;I9IioBu}NqJ;3^4dril%ymR z8%cRAqzFsRLLx~B3!5PTmt!wBsyj8vY$DA^&@@J~ASzUJ))M&DlxEXVYX zyFER?Joab+3H$=MUnxx&LLQQR|{=xO|ay+Um&zfCoRaL z?G^u5S@gcoNj&~o{NG~_p8LHdoP?0_752Q?KzKsB?3|R4#x5dfJ0~wG6^T}tM%zF; Nop_n(o*kd=^#inkiIxBW diff --git a/src/cctz/testdata/zoneinfo/Asia/Ujung_Pandang b/src/cctz/testdata/zoneinfo/Asia/Ujung_Pandang deleted file mode 100644 index 5990010b649745369501c7641c401bcad4345b85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V-n!V$uIVu<%pt1Q5MT>?)W(-67im;$I4TSHQ@` z3{;!{0c0+a1hNYn7&sUh>LxJofY|~*z99_0K&)+G0mPOJ;hrIm3|t^m*MbWGa>yuM diff --git a/src/cctz/testdata/zoneinfo/Asia/Ulaanbaatar b/src/cctz/testdata/zoneinfo/Asia/Ulaanbaatar deleted file mode 100644 index 6f5d3a15abbe48b8a4dc72aadc88c416160a56a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 594 zcmWHE%1kq2AP5+NDnJ+nLI`UCnaBdf0{?-a?eaSxkUoCyI}<>(#LE*6AX@U)pAR5f z>Wps#h?d@CPynK3*625YXxTYJV7^?BAeb*-{RPZd$o>rGD@I=f^Od}>g89nUJHUJu z?d@Q`s`M-{UyXYvn6J*V?E?c4sDIf8q8K!u%mDK>ugn1RwT@JQ`Py5mz0jC zFyB=+P=EmlLPckR`C+Vy1t5Od*BUTC{Hb#RBQq0;kbxn^1Y}B50Vqc6CNOd^FcdT} a@c8(KFlZZ?1F(#LE*6AX@U)pAR5f z>Wps#h?d@CPynK3*625YXxTYJV7^?BAeb*-{RPZd$o>rGD@I=f^Od}>g89nUJHUJu z?d@Q`s`M-{UyXYvn6J*V?E?c4sDIf8q8K!u%mDK>ugn1RwT@JQ`Py5mz0jC zFyB=+P=EmlLPckR`C+Vy1t5Od*BUTC{Hb#RBQq0;kbxn^1Y}B50Vqc6CNOd^FcdT} a@c8(KFlZZ?1FGsnw=@)4Ef9!L(kB9hlZH(FfB8DGFfPFxIC4WROvjI+!-L z)dSNeL7ZUPR8{~?n;E`_(0@LGX$xug4mcL$t`BrP6N}9&1(uk<~g}mfcehJePF(eY8067>RbTkyRq7U`R>X= zV7~jiNHFcmYyzRrS%Yb>$6{dGdz~zp_Bmtp0c5^!?|(4gFZYWBh#%s;>jNVb3o|BU zWy2zfsf>l0otce+q0J3sT0sK?3j;&l1W-DgwSj?$fnmh~Mgb6;5yEexkxD*yw8(>Mh3YI3Pz%nrq z^owA*I*z!?Zy%5=K0lBveW%D(em}Bd>mF8neb6{_0&CoBu(odt)=ha`ys0K1y;uih8-uZou{49RjU_W9VoHdVC0mjRB`ND+(i}+1!LB41 z%YnI}kd)HEIV^EX#EH>%mcixW=JOUwNKm2Badi}3Q_ z!kWK%t|7M<59vDdQj~R&-o9gZq>p6u6@Kj1lD<#7`0saZzoYg)%|uIWCM$Kox()`; z#=#(q49fa>7~ICekg7KrYP^SGX;&~@c?jjw9T?%h3Kil@p5`mw4`AfOelT@ZZ>z(r z6?~6An1;%&aTv4I2V*B&VBByOjPEi*RlN=-R5w{^p1M;H6LkidR4RwbfiW;e?dtH$ z6KbU4Jl)gWzM{3CF6dO-1v>5e5uLvL0(HA5Fk|E#X3ng`tcFdPJ#=KHc{zDgXnoxp zI#=F<&eL1a`OX#Sg0OaUfxR0Rib@=wl|#e58X7mW&~#eN)BK_dDcWp2W}L|Bk4OCX z=if)2MU3?=(9n)SCT7es$4M9)urd$YIbpZVF^Q?j%#eh{(+H+ znTdfRN*`n{kOb<9&S2nRV5pnGz~|!|!Vm<++6HFE20+r1fy)NWw$nAUGB)4>0PImF AssI20 diff --git a/src/cctz/testdata/zoneinfo/Asia/Yekaterinburg b/src/cctz/testdata/zoneinfo/Asia/Yekaterinburg deleted file mode 100644 index a3bf7f29b6f14debfbd0f8ccb45f1ea338009ef7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 760 zcmWHE%1kq2AP5+NDnJ+nLI`Vd0xDw%Vv+wqFgu=89Yik_+6bclZ(aP?0Vu~Hs@}Z; zM2krrPyo^59QzHx^v}-=K(xfmPhfe;+v*A+zSNm=FkgC4%LNc$W=$!WmYtIZrsaCV z!L)ph2bfmKu>{kKFl8s*~+NT0=B4KUyGw;h;owU-Obx4x|a z=G!b&2h+B@nZUGN8z-2ypY;SxJEXn_(~d0+7eMAYxt;~{os%Dd`7WyK!F*TeBVfK8 z>qIc$U3nRp@BVHrnD%7ufY9gq!L--oEHLf8t`JQ7oM{gLneW>d4CaUUFgh?Yu`pwS ztk{Jym9nt_{eKf=s>wkH5Zi%)1DGNc7{ zA;%p|E5=xWX(b;`Fs*DO1*TPWxWTll^dB&-#{CvdtFuZbFaUx2S1vHE@szUw#Miv? z3ruSrc@3tux7-2KI!n%iY27LNz_eb=dN8eDvH(mQq)Y_U#vPEFp z%*Yo){|y1t7SdS>3_xIU*9^?J{OtqgTkVwq^Q~{|f%!JeOu@A6ZUHcD*Cr08?Pq-g z(+;UW!L(xw-vb69aB{s3<~t{U0P|f`_k#JZ&X>S^H`e)JzPs`kFyH;%ZZPf1JPksh zn+vAB9#?>A?{)QH+ULyF1O_1R?Mnpn{nnHxFfub?fh>$rh(!)rJus|yfK1dfU|?Zj ma0_7M0EUJG0}qH~9Q^!QFhJaVq(#U<8hIYr_((IKn@ z?EBIB_$cbFHD{wqy)CQ?^|rcx%xMp|N4-5a7Wub68LZhAsCW2nM!h2;82L`oZPqyU z^XfW2jC%K>PS~?|#+5wIJF7wXUauW~P?xi=6vE!gOxV}^5cW64!hy1I__0VTCvyff z6XB<%7&sJj6%L05!I1zzsPH)eN8KFZn8*^2o9e*{eGgYM@3W=@>#7BuoYI9~`qkl7 z^G`VaY6{NC2H@<|RycRB63#~yz=iWt_%*OaPUbKAmcwuEd2q=-4SqL!0Do+ZhRfV5 ztcw9~Md2%FelwH~w^afcE1|BU0P1x~;ntc&s9#>eBYg(B`Oq*W9d1jIK%>Z8(D*_a zG&vavO})g>%*g|8=Q}`i0}HrAOBY%wyGzJ?i=|!Aa?BiB^=yGV>r|n&v$iqmvo2Xi z%r~m$k(i$~iP+{*AGD2afp*u*p&%#^3QzU&INWt>zm%BXzxP^CDl7f-QdRkrr|F4# zilXT;OG=5R7v?!?G_4q-w8)F$FkkJ3dGe>G&Esq$8A{K~TTC5fwv9l@Y!PKG5KzZF je8tR-n9^`!(k?POY@*$Qq5D)bycCq`62!VbxxOa254p z(C=RhNu*x1updSdv&DL7*t>>uk6vApXWgC7S~N#=J4heVd) z$(I7l_x=bx5z2-?c)UE@7e@3BmXX$W_+x(-Jk`?$f6lB$f4a?w^V4&4cpkNM!qGP& zI9A+;er)hQJd@f1&-gCD@h>(w(LE%v_a%>}e3Eaz3_ymHKO5cuqJ*DF8!u~H^1`2+Q}vd>uvG3!@AKD zxa?FNtiQy;hQltA)`+q9J6vw7fh+b-z$Uc{t~5S`tCmWzSs51SF=9^6!qtCpDyn_`NL z&a~A3H6Y1ujR!L(e@ z1TZaM(+H*&a*DvTVoWlaR`Lk})5l@ z|3{#5Ao&3tlne|U3=Dh%j66QRAq=_(h794ZAwV1)!oUS&8Gu+izQ%f{dItK2I=+Sm HAQl$@o9a^A diff --git a/src/cctz/testdata/zoneinfo/Atlantic/Cape_Verde b/src/cctz/testdata/zoneinfo/Atlantic/Cape_Verde deleted file mode 100644 index 8f7de1c0a19a8d3e0e749626c76c8d4dbd3c4de7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 175 zcmWHE%1kq2AP5+NDnJ+nLI`VN0V)Gwp8r5F>Dj6UAo|SIISL^9Qb~;f$Q*9*?+%Pi vjLiT4zx=|$@c;kg2MjF#|9||z$N?f5IDC9V7<3JcfY^|M%LYi=8FB#tdL1f2 diff --git a/src/cctz/testdata/zoneinfo/Atlantic/Faeroe b/src/cctz/testdata/zoneinfo/Atlantic/Faeroe deleted file mode 100644 index 9558bf7180acab14d3b3f63c956f5224f680b2a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 441 zcmWHE%1kq2AP5+NDnJ+nLI`V704ie!V&4Bi(4D&^0?1|%Ren7IM2iXE0n_5lXCd_G zePCMR@p>>Vd3gbtmO4BUOiSjNmeXKbzhn=XHb_|urVV3n3NSL^hyVZoTmiBh2v`^x_yia^e0)O~ g!d*c)ID~-<$T9%2bbO8VO!W-(4Rw4C4L~d|08D2^!vFvP diff --git a/src/cctz/testdata/zoneinfo/Atlantic/Faroe b/src/cctz/testdata/zoneinfo/Atlantic/Faroe deleted file mode 100644 index 9558bf7180acab14d3b3f63c956f5224f680b2a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 441 zcmWHE%1kq2AP5+NDnJ+nLI`V704ie!V&4Bi(4D&^0?1|%Ren7IM2iXE0n_5lXCd_G zePCMR@p>>Vd3gbtmO4BUOiSjNmeXKbzhn=XHb_|urVV3n3NSL^hyVZoTmiBh2v`^x_yia^e0)O~ g!d*c)ID~-<$T9%2bbO8VO!W-(4Rw4C4L~d|08D2^!vFvP diff --git a/src/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen b/src/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen deleted file mode 100644 index dfc509570a5be7ea90f64610ad5ca5a58fa3d172..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 676 zcmbWy&nv@W90%}chGn5|ZMI=-Z1eSFKW!*+n&n{MlkY*IghcJM926IFaB%pNgQ7?d z6n0TAMk!L!FMhUW0LTA-e9xREawUGQ?o1h4!m7#Wnoct9`E z`R6S!^2>5NOw3u~>x2#_M;Z9mBY~;T6im0o;5!?I8FdJLFiC;#{j}vHegtbvG(lACkd_{V!NB=F8Bl+(kM6SfI^^#mdiWySi<#^)ubkoKYx!5cY8qJ*3+GMqxIftEU HbIN}KI)2g> diff --git a/src/cctz/testdata/zoneinfo/Atlantic/Madeira b/src/cctz/testdata/zoneinfo/Atlantic/Madeira deleted file mode 100644 index 21e84571ee1694758dd244ed0702fbae962648e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1372 zcma*mdn}b<90%~{gygb1i{;*hgdE3vjxK7Mm8rE@jZ-d5t#qGEXS7DOgRE8l;7qMV z?rS@9Iiy@hl3Rz|5_LpGNC-)h)#-h{??3%j-gnRWJip)fd7g8Z1fD%5CjY&7>cLc1BKi-my76hArl=#-^rKTDYatk2nBi1iAcU+61FLQ&_bp1}NvVpxzKgj{*u79rachvRUb6|siIrQQ=bRS8#(@ij?rVB{jB~tjiq0h~SD z=h1xI19@{zKp4$iq)Oy1bG=FN+msi#y1~+^GJiUE(!3vO*H&rB!zQY!JIP^ zI6vsAr2j7y!=DslGNY7HO$RfeS%(~&*Th1LiUKwz#4TBRhy)$uWK&E;r5ovaO! z!gYs(p|zI;+U)Rz>jhh&t)(5@U}y^MbUYI1e!JOC(0<4kI&`jr8|!qTWAPjmWRF6p zq;4p@)&!lyDnlTH90%|-V`(I%CKMAxEj5>vBAMF@_Ci~UH(Npxg~&TJR&oh1cr}c?l3OW7 zd!ZCDw_!8GTxWAPmznEvp6~tuFFdE`e9!0i`#qgH9a&L%Sv>XUVlfkBlO_B6NG3Dp z$!vd`SsjWN4M}xxC`EEW-_}ENur|M${_t!P`lBh)=#S3Tp}!;vMt?aq znorIxn**mwu0&;Mkc&~M>o@{fH!eo59j>Fk-WdsRXs6)KN)EiG?uGTac6eJgf!qk%nYFpS;JIRRiw@&A=vs6gIv0!Dhc|ckVYJ53GUcAI=rRM;nPq%Sb)y$CEtx zL|FizcDdlQ;$--|$_!tKLtv{!3txtR!?q+7((V(C`W0^;zPkQ`ubpc6X4L}U8XMue zu?6^kRslb>kHC-p?(gQPXoa7eDs{Ut<=_lcpVylsDj;Cy`M?k%)>F#ZfuTGncuExWA5R Bu;Bmz diff --git a/src/cctz/testdata/zoneinfo/Atlantic/South_Georgia b/src/cctz/testdata/zoneinfo/Atlantic/South_Georgia deleted file mode 100644 index 7fa5f4683538498b93d1e639c14256c1f033c354..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iWA+4lDUHq&t<8 diff --git a/src/cctz/testdata/zoneinfo/Atlantic/Stanley b/src/cctz/testdata/zoneinfo/Atlantic/Stanley deleted file mode 100644 index 1a4c8ea86361731f4d7e854ac66d96a5ce6b2dbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 789 zcma*lNk|)E6bJBc+^W$-0~Oqtx?rr!B+tpt<)!qQLS@ReLJPbe`v=~LYgA~y!6i54=7kyd zpPa&h{bYD+WexuEjl_?$;xmvTvh%Vu5S4c*Cb59 z)~cVd^{NN9r7yy^!`HA~vmIoj?5o`>W$nMOu;XJr{4y{F*S*)PQfSDX6CNhc-ND1| w!#Vf+7{fJ;^Sz)HDgGuei{boKl^)ZCMb^D?vbUo1WuxdK(FUfm2vr(2x9gG87XSbN diff --git a/src/cctz/testdata/zoneinfo/Australia/ACT b/src/cctz/testdata/zoneinfo/Australia/ACT deleted file mode 100644 index 1975a3a4bd0ed93db1d10a2c562eb5bc3baaa489..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 904 zcmb`@%S%*I90%~lC*b>sI}i6Fw%A={F(-JvHQXgzoGtg30@dUB~H}0Js92l3&zYX!r1$} zFm7-R#+NU^gs#Uh(exfBHMI%<3_ydU9wtXURd|t-^-#Fl57RVt!axf&9^}DvzYAt8 z>7l867+!o6Bu?htUesC22F$L0%WcYOKY^FBdtmO3b>ZnTylkEpZmvPI?v-$Q3g#dA z;FZD83NI{MFJVE~B(w%Qpsnczw7>R3>0UD|>@0yrWlmV!kPJ&QOz^7oQ+P(uVKflO zv2%#JG;jp3g;wD8?QP;XCk|lQdHh(4WwIUs diff --git a/src/cctz/testdata/zoneinfo/Australia/Adelaide b/src/cctz/testdata/zoneinfo/Australia/Adelaide deleted file mode 100644 index 3bfbbc563cf97dc2548ff8974ab23dcde28e8744..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 921 zcmWHE%1kq2AP5+NDnJ+nLI`UK0V-nwV!r=CP%PFh0-~#hm zeZaKrK|wGrSGgEW%TM3Q0WwD+vK7o%Y`6-hm7ErV#g#KZfoT<`7BH>qc?C?XF{OcN zbu(Zz ylXD`3UcZiki4hGlF!Wb|WM^$)WMN?FS-`;Q;~T=@=;{I@fN@HuYhizMQ z+6<~xl9$isYO!#f@J?|NLYVTo|c^ zZ-=`uzStwFbPs)71r(C)B4xvI8?xb7IZTuU?nf&$rhey6=%H!-HQaGON2K*hpT5E5 zYY8yrc^sym`U=ycV=%q!70d|Vf|-_4xU=CBck?F9@*RV_lKNHJf4B7lH?G1xx)68d zJj`Bo!M!~-&^(h4Etem{eRp4ov`@~-2(tD12WYE&fPQ=H2HbD!hPl=6x$8gSfxHRs z;yajUjB=lh!-H#G@KAI~rE?t1cVK?_8FW4kLs!FXC=E11chhO;X)l4^QW+N1S>R!F zE-dsg?%zb{%QlO2j&EfRx#-Upa`E&W@{!N0$R)8KuypDrEQ`#-@_R8@aqcnn-mH&D^$s(Ev8(;e$k^bh tE`_m3lo@M63iAi+wMIr0P?(8+^NWhTl3xxej*we&x}B0ER6w}ArhoaP!bkuB diff --git a/src/cctz/testdata/zoneinfo/Australia/Canberra b/src/cctz/testdata/zoneinfo/Australia/Canberra deleted file mode 100644 index 1975a3a4bd0ed93db1d10a2c562eb5bc3baaa489..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 904 zcmb`@%S%*I90%~lC*b>sI}i6Fw%A={F(-JvHQXgzoGtg30@dUB~H}0Js92l3&zYX!r1$} zFm7-R#+NU^gs#Uh(exfBHMI%<3_ydU9wtXURd|t-^-#Fl57RVt!axf&9^}DvzYAt8 z>7l867+!o6Bu?htUesC22F$L0%WcYOKY^FBdtmO3b>ZnTylkEpZmvPI?v-$Q3g#dA z;FZD83NI{MFJVE~B(w%Qpsnczw7>R3>0UD|>@0yrWlmV!kPJ&QOz^7oQ+P(uVKflO zv2%#JG;jp3g;wD8?QP;XCk|lQdHh(4WwIUs diff --git a/src/cctz/testdata/zoneinfo/Australia/Currie b/src/cctz/testdata/zoneinfo/Australia/Currie deleted file mode 100644 index dc2ef554dc389f4a34146329935e5c3581a0f2f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1003 zcmcK2-Ahw(9LMqR*&O10>IpSMAzT=$NdH;UD17l3?^!HTJ zsv{&%@Wmsq{)#VoOq;xNR+7^z(sy>~U7y0<9<>sC=c5aKS2+%YFUw%)SPPt%9}}OO zp6W)wdG3X=NE@69ox}cH)r?+z-H%?124G^U11_H*!Tw65j=w&U_lCjpPzIWJzpT;FH7 zX7D~->l}mY`Yyxu#(QwX;hvPsmtdY_56ssdfCVKd6@Dm~ml!G(S``>M0gK}0uvm3N z!?+$APnqDRn^EG~+z~*RC^N9Md5D*3i~lFwT6z&~+Z%&rnl5NEr+zon-)HFZUvY&W z%yWb2ir55t`;!Z3%Y!hwa^MJB>{rp&UMJdi#*dbccET#}RjgMx)T3+cr_nnMMzlR| zAKIQE^v(qf+VSZdx;F9y?i!thbz>EkI}K ZAKwrLN9SM=;S$2Y1!C%2S{WN~0RXyMNZ0@X diff --git a/src/cctz/testdata/zoneinfo/Australia/Eucla b/src/cctz/testdata/zoneinfo/Australia/Eucla deleted file mode 100644 index 9080f5cdb1216ef6397e7de6205173caa794c646..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 314 zcmWHE%1kq2AP5+NDnJ+nLI`US1}b9)VuAlaP_m3`1BjmEcSQtD?{Sy{qECk$fzZdx z!QyAOXMpLm%OgcV_HgolgwWggz_b)&1cY8*3Z^wxgCO+!{Zl~dT?@B>X*bpwFzv2f z1eSMyR|%#)nL{A-xo8n4MhwWnP;midOs5PZ3j;$n4+EEvZwQ07fu)HlkhB1jTsC0Z LPS?W9#FPsFy<IpSMAzT=$NdH;UD17l3?^!HTJ zsv{&%@Wmsq{)#VoOq;xNR+7^z(sy>~U7y0<9<>sC=c5aKS2+%YFUw%)SPPt%9}}OO zp6W)wdG3X=NE@69ox}cH)r?+z-H%?124G^U11_H*!Tw65j=w&U_lCjpPzIWJzpT;FH7 zX7D~->l}mY`Yyxu#(QwX;hvPsmtdY_56ssdfCVKd6@Dm~ml!G(S``>M0gK}0uvm3N z!?+$APnqDRn^EG~+z~*RC^N9Md5D*3i~lFwT6z&~+Z%&rnl5NEr+zon-)HFZUvY&W z%yWb2ir55t`;!Z3%Y!hwa^MJB>{rp&UMJdi#*dbccET#}RjgMx)T3+cr_nnMMzlR| zAKIQE^v(qf+VSZdx;F9y?i!thbz>ESc3xj8CBH~ZPplON0 zpFt`XLL(wI7^I`5G10-FK}?!1ItboP z9C?*|%VSnGmt=i~U%p3{Dw`vNd|e%9S*#tAknt&4&9%eoNI$H3(!!-n0$g^jfXnCC zMb=lbd6Z#U=@nsZAdY%f=UR&0SNmU3uc?}bb$vIm?)?F-)komk+bdX~y8`Qvcj3CX zN!YLz6WM>p#InS)UfO~A(+Rj?C;$r^E|`wEVABi_n_GF>O^nPoQo;NTk@i*2^f|wit!mx5KbwEDU!noT0zdDZyQ%A-J0l ziLBq*H3#?P*irAT_QJg%!4#*+`kmQ||4c$cHSF)TJ(5kx{sosyNbr#46S9566}j9V p(%~HR5Cf%VLEZ)Ilql^ux7Aaj*(}JQ@{t&V diff --git a/src/cctz/testdata/zoneinfo/Australia/Lindeman b/src/cctz/testdata/zoneinfo/Australia/Lindeman deleted file mode 100644 index 131d77b54a2087ada0bb3a27d03bf752f84326a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 325 zcmWHE%1kq2AP5+NDnJ+nLI`US1uA0(V!r=CQ1o`u6%akg?@$An-lNX|qEClxhS0}T z!QyAOhk@y{%iY2Bxdp{w`Sb0X4M4LPmSc3xj8CBH~ZPplON0 zpFt`XLL(wI7^I`5G10-FK}?!1ItboP z9C?*|%VSnGmt=i~U%p3{Dw`vNd|e%9S*#tAknt&4&9%eoNI$H3(!!-n0$g^jfXnCC zMb=lbd6Z#U=@nsZAdY%f=UR&0SNmU3uc?}bb$vIm?)?F-)komk+bdX~y8`Qvcj3CX zN!YLz6WM>p#InS)UfO~A(+Rj?C;$r^E|`wEVABi_n_GF>O^nPoQo;NTk@i*2^f|wit!mx5KbwEDU!noT0zdDZyQ%A-J0l ziLBq*H3#?P*irAT_QJg%!4#*+`kmQ||4c$cHSF)TJ(5kx{sosyNbr#46S9566}j9V p(%~HR5Cf%VLEZ)Ilql^ux7Aaj*(}JQ@{t&V diff --git a/src/cctz/testdata/zoneinfo/Australia/Melbourne b/src/cctz/testdata/zoneinfo/Australia/Melbourne deleted file mode 100644 index d3f195ac2fac23afd46cc16650e0a2454f5a3923..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 904 zcmb`@%S%*I90%~iM0R@f%RMLR=G>;Asy4{+1(a?a;`f9KqL;mGxEt(kOY zY19)uxa6~6@v6r{)e-quEuUc^h8?}LsKB6&*j4$xaHR$Pwb^@cJ>Z6)$9>q}@S7F& zTNL^*4~9j=b0qCuBeM3;0ngb^gj;b?7xi5@^9SmGEx_|*vBVYr8h|@RI2jyjN8#0>Y2r$(>p@QHe2$!4`U0l39l+G&$1tsG9bOA*g4fMc!i_a();$wWy@faT zeK39alfnzj=2Mu_^#)p}+oA1|Q{5%94|@Pwel zXdo`f&JX0gz&^|mF2jQDZQ?4N+=WH+LFgPFzduC&J^s(gJ53nTlX24B_Q+J?D(A^7lb+`c$<7^% QN3vTbtKH(sW^7sde@9iYAOHXW diff --git a/src/cctz/testdata/zoneinfo/Australia/NSW b/src/cctz/testdata/zoneinfo/Australia/NSW deleted file mode 100644 index 1975a3a4bd0ed93db1d10a2c562eb5bc3baaa489..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 904 zcmb`@%S%*I90%~lC*b>sI}i6Fw%A={F(-JvHQXgzoGtg30@dUB~H}0Js92l3&zYX!r1$} zFm7-R#+NU^gs#Uh(exfBHMI%<3_ydU9wtXURd|t-^-#Fl57RVt!axf&9^}DvzYAt8 z>7l867+!o6Bu?htUesC22F$L0%WcYOKY^FBdtmO3b>ZnTylkEpZmvPI?v-$Q3g#dA z;FZD83NI{MFJVE~B(w%Qpsnczw7>R3>0UD|>@0yrWlmV!kPJ&QOz^7oQ+P(uVKflO zv2%#JG;jp3g;wD8?QP;XCk|lQdHh(4WwIUs diff --git a/src/cctz/testdata/zoneinfo/Australia/North b/src/cctz/testdata/zoneinfo/Australia/North deleted file mode 100644 index a6a67300dd5ef87e421c9749702039a6bdbb928f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 234 zcmWHE%1kq2AP5+NDnJ+nLI`W&0xDwxV!r=CP%Jhn0z_8}F&BX7IesTQ!1Nw74iJ4h zWEX@!o&y#?vpp6}pIz<;rq3;?0?VIoH|StwW`aTnhN=}H*VIh_*)(|tBPRnx>kI}K ZAKwrLN9SM=;S$2Y1!C%2S{WN~0RXyMNZ0@X diff --git a/src/cctz/testdata/zoneinfo/Australia/Perth b/src/cctz/testdata/zoneinfo/Australia/Perth deleted file mode 100644 index 4f771828c9b54d9bcaef82639425df4b3559b5e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 306 zcmWHE%1kq2AP5+NDnJ+nLI`US1}b9)V!r=CP_j(y35cHKcW(ih-s7zRqECmMhtS6x z!QyAO7lG-s%aa!X^)hhs|Ax@pB*3&3V-kd3UJs@Aq-p~ IQrChD0G5hMm;e9( diff --git a/src/cctz/testdata/zoneinfo/Australia/Queensland b/src/cctz/testdata/zoneinfo/Australia/Queensland deleted file mode 100644 index dc9a980a65923b6629d788e4e03b4358ac151c15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 289 zcmWHE%1kq2AP5+NDnJ+nLI`US1S(?&V!r=CQ1o^_2Z)~Icc=kO@6l%f(WgT;L+InF zVDU5C!@%^}Zz ylXD`3UcZiki4hGlF!Wb|WM^$)WMN?FS-`;Q;~T=@=;{I@f zeZaKrK|wGrSGgEW%TM3Q0WwD+vK7o%Y`6-hm7ErV#g#KZfoT<`7BH>qc?C?XF{OcN zbu(lC*b>sI}i6Fw%A={F(-JvHQXgzoGtg30@dUB~H}0Js92l3&zYX!r1$} zFm7-R#+NU^gs#Uh(exfBHMI%<3_ydU9wtXURd|t-^-#Fl57RVt!axf&9^}DvzYAt8 z>7l867+!o6Bu?htUesC22F$L0%WcYOKY^FBdtmO3b>ZnTylkEpZmvPI?v-$Q3g#dA z;FZD83NI{MFJVE~B(w%Qpsnczw7>R3>0UD|>@0yrWlmV!kPJ&QOz^7oQ+P(uVKflO zv2%#JG;jp3g;wD8?QP;XCk|lQdHh(4WwIUs diff --git a/src/cctz/testdata/zoneinfo/Australia/Tasmania b/src/cctz/testdata/zoneinfo/Australia/Tasmania deleted file mode 100644 index dc2ef554dc389f4a34146329935e5c3581a0f2f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1003 zcmcK2-Ahw(9LMqR*&O10>IpSMAzT=$NdH;UD17l3?^!HTJ zsv{&%@Wmsq{)#VoOq;xNR+7^z(sy>~U7y0<9<>sC=c5aKS2+%YFUw%)SPPt%9}}OO zp6W)wdG3X=NE@69ox}cH)r?+z-H%?124G^U11_H*!Tw65j=w&U_lCjpPzIWJzpT;FH7 zX7D~->l}mY`Yyxu#(QwX;hvPsmtdY_56ssdfCVKd6@Dm~ml!G(S``>M0gK}0uvm3N z!?+$APnqDRn^EG~+z~*RC^N9Md5D*3i~lFwT6z&~+Z%&rnl5NEr+zon-)HFZUvY&W z%yWb2ir55t`;!Z3%Y!hwa^MJB>{rp&UMJdi#*dbccET#}RjgMx)T3+cr_nnMMzlR| zAKIQE^v(qf+VSZdx;F9y?i!thbz>EiM0R@f%RMLR=G>;Asy4{+1(a?a;`f9KqL;mGxEt(kOY zY19)uxa6~6@v6r{)e-quEuUc^h8?}LsKB6&*j4$xaHR$Pwb^@cJ>Z6)$9>q}@S7F& zTNL^*4~9j=b0qCuBeM3;0ngb^gj;b?7xi5@^9SmGEx_|*vBVYr8h|@RI2jyjN8#0>Y2r$(>p@QHe2$!4`U0l39l+G&$1tsG9bOA*g4fMc!i_a();$wWy@faT zeK39alfnzj=2Mu_^#)p}+oA1|Q{5%94|@Pwel zXdo`f&JX0gz&^|mF2jQDZQ?4N+=WH+LFgPFzduC&J^s(gJ53nTlX24B_Q+J?D(A^7lb+`c$<7^% QN3vTbtKH(sW^7sde@9iYAOHXW diff --git a/src/cctz/testdata/zoneinfo/Australia/West b/src/cctz/testdata/zoneinfo/Australia/West deleted file mode 100644 index 4f771828c9b54d9bcaef82639425df4b3559b5e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 306 zcmWHE%1kq2AP5+NDnJ+nLI`US1}b9)V!r=CP_j(y35cHKcW(ih-s7zRqECmMhtS6x z!QyAO7lG-s%aa!X^)hhs|Ax@pB*3&3V-kd3UJs@Aq-p~ IQrChD0G5hMm;e9( diff --git a/src/cctz/testdata/zoneinfo/Australia/Yancowinna b/src/cctz/testdata/zoneinfo/Australia/Yancowinna deleted file mode 100644 index 947b50995f4045ee6562cae21120dc8a05687653..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 941 zcmb`@?MqWp90%|-cZYY&XTu`fa$6GC-0n7$X+F)nC4#fi8<=1am0}Md3bG6;$l;|# zM5#syNioz2fN@HuYhizMQ z+6<~xl9$isYO!#f@J?|NLYVTo|c^ zZ-=`uzStwFbPs)71r(C)B4xvI8?xb7IZTuU?nf&$rhey6=%H!-HQaGON2K*hpT5E5 zYY8yrc^sym`U=ycV=%q!70d|Vf|-_4xU=CBck?F9@*RV_lKNHJf4B7lH?G1xx)68d zJj`Bo!M!~-&^(h4Etem{eRp4ov`@~-2(tD12WYE&fPQ=H2HbD!hPl=6x$8gSfxHRs z;yajUjB=lh!-H#G@KAI~rE?t1cVK?_8FW4kLs!FXC=E11chhO;X)l4^QW+N1S>R!F zE-dsg?%zb{%QlO2j&EfRx#-Upa`E&W@{!N0$R)8KuypDrEQ`#-@_R8@aqcnn-mH&D^$s(Ev8(;e$k^bh tE`_m3lo@M63iAi+wMIr0P?(8+^NWhTl3xxej*we&x}B0ER6w}ArhoaP!bkuB diff --git a/src/cctz/testdata/zoneinfo/Brazil/Acre b/src/cctz/testdata/zoneinfo/Brazil/Acre deleted file mode 100644 index fb5185ca60283bd56f795e9a956274c0b6e63325..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 418 zcmWHE%1kq2AP5+NDnJ+nLI`V-2P$I$VxIp%Fl|-a1Q5N0KaBxQ|BX2SqIZ4_2msN$ z?oDt2(YGv4f%&)Ih=J)ll7BCN#P94Z1H~SZufB)__F#kb_KbZezhBR3H zSJo;p|J#8Eu>5yEs{7CynFoMwXOKO) zDgZ>wReU}GqU9F^UI5Vw#;*^6XvM}>u)GrY6ENQ+p&rZ+s%JUC#E1tnGyVU6pn!ql l|Nr9$7+HV;v4MdD#Aaae@eN_nH825UQwA;@AZcgH1pwW1w6g#J diff --git a/src/cctz/testdata/zoneinfo/Brazil/DeNoronha b/src/cctz/testdata/zoneinfo/Brazil/DeNoronha deleted file mode 100644 index 9e74745ca79137918281337fa270c5fec4bd7da1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 484 zcmWHE%1kq2AP5+NDnJ+nLI`V72P$I*VxIp%Fl|+83W(mpZ+!tw|23KbqIZ5&QvlJs z?xhKU=vx*G!2DaU-+<{ml9v~N#P96%2Fu_5%?=j7H~RvZfB$X|nExO|70mxK{UccY zSJnV9|J#8uu>5yEfe9dUegw*a`9F?t2h0EBIs#VzYsD+D{O{L4!18~(^Cy7(DSNU( z0YuAHoCNdb7pN})@fC~@g87P#(F!2G68A1JUpazl0f?{sC`kZBtC~Mq0H&|(1oO?m z?Ev#Fc9etpmiMnJfaEP-GJ^G6pZExtx5;Oiz{E%t{Qv*q90rE}|37|UWcmO9@dE}9 VAKwrLT?0cPHe%qi0g`q`TmX|XySo4Y diff --git a/src/cctz/testdata/zoneinfo/Brazil/East b/src/cctz/testdata/zoneinfo/Brazil/East deleted file mode 100644 index a16da2c4d5a980cd944d86c34ea8a2f597e39b71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 952 zcmcJ}-%C?r9LMozR#LOHE+Q(_$A-vi+G%I$EHi7^Ty56!U~@(Y)zG>qqNpwcqmn=< z?3Z9S4_$vgW7q3dYIPf`F{QZuX@JWm)GV zJT?TE6y;&R%PaZ(ta7>bTCra-`xg7&z8mP3lWFuFw_WHvhb{D~Gr91t!7lXb z`XBJ_uD@_i*(kiH!-V&)`_7p>zVK_J#-c2c1k=9Plx;p2X|fo+5}pA*(TdpY$+ zM-JRLvH^}{O~aAi1-NM{0Y`5daI?{(%h%Y^);Q0y{kM;0jRhIAtaQq@)UrOjW6Ogf Rjg=~H`KZiZCBLgx`#+zs5jOw; diff --git a/src/cctz/testdata/zoneinfo/Brazil/West b/src/cctz/testdata/zoneinfo/Brazil/West deleted file mode 100644 index 59c952ebc65169dce30078a3e1ee371e0da52ae4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 412 zcmWHE%1kq2AP5+NDnJ+nLI`V-2P$I*VxIp%Fl|-63y9vqAN~PM|MlAdqIZ6Dasbi0 z?ll>J=vx+h!2DZpIKcEB$@d39;&*nYgXQo3RtAgToBamNzkhcHnExQe5zPNGgBPs+ zD{Bsz|Ls5#SpGYo&IXV-LhoqO>@p^wOVUsb1!a_h#+h32XiZ-QDS9*B1JEZAyHA0FetGf zW&{eewrsjAon_86r)6eal=d>U96^wjMNn1*(l2(O@BRSmT+aF2?{l7e;9jn^^iX9k zGwo2o*}QD?X!_hsubkwr_9i6sD{mDGVHg=4ah!)3*N})!PbN`F~8|; zbk5D`{m8f86vMXA7TEsO2mL-7?C|WcQUC4p0^~b2hheA9?4kNydnfEFR>44Fsg&y7 z8W#Cp?s3?Y{4?g<6zu&z2JcVQN~yo^?GG3Xe}Mfx5jfzk@zDN*h5+(IS0)@hQ4b#- zya0zvPQu5V)gI~}-mnMx$;Lq#Dw#k%6kPi!_7 z$-Y8S>N}VoKN9oT02EJkz>J6oN`~rSX0V^7bF$j}a9N`pF2Cr6D^6EK=@C0zxwjmy zGFzc+lL@X?=0SOu0H;aOZ*G`0?%at diff --git a/src/cctz/testdata/zoneinfo/CST6CDT b/src/cctz/testdata/zoneinfo/CST6CDT deleted file mode 100644 index b016880653929aa40dd5ac0e82e4094a9d787cdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1754 zcmb``YfzL`7{Kwv{UQjZBm$vHxgogR;v%kz!4Ba>SgseW(IHKuX<|#1ai+m_B26cw zG{@}1#anoxMK?ksVMQVaYbHU74c!*9l`v%$Qv}*=&;OI(^h4*J^FHVIT+aLH)vPF3 z8!zs=T$~+p%cZ&hh~C-e>D<8%=UVAzuavR;P_$0Qitp}fWvtvX5m$ZIi}#%^5;DL4 z-8(iJ52!n-A6#w1hZdWte-*Tc{_2EATx~Z{KQie{e8jvPA06I=k2MwJnyx(jb$Kq< z8`5!Y$y|K=i&Z-L-4prCwK5vsS%AOEOvQCCN8oQ2VYpu9flqqcaYN`8++elfMh|x( z?`dpn!QWrD;!}FFP3D_g+i`Q55gS)@~%Uh-)mflFPit@ONT$w%DlO0BmRBc+t^b667DO|;Qo?%_>Zh4 ze0k+G{O2;2P0m|0RYJxq$>DfF5sv?wBJiM>z=OB@@l|U-{=2&sUu$c{*PHva@}42R zMJJ=J;tak~)`D+tI*5l058zv?w&H(sw&2_I3-Fzo*YL=b@7d%%cLNsUQSW>_I+8DB zerzBMkN0HZf7_$5{bUq&RQucH|0F*3C%9}K!mhJ2I~3R_@C5d$*)Q9Luk8~&!Lp0GpQ+X+^Zv&5cw)m&9B_E2OpCz1Mfjm@Mfl;3 zOYx+FrFe2~3J%Ij!H>)d!BZkbaPW*|tvpQi9>*cBQ*p@6V4X~a_Ko4NbEEjt)0c4g z@r!s`RWqKxAwaf^$2M2t8B1>9h}TcqVA zC!FjRhEqZZZ1Rv|wc|Ns9XPekg6H-g!z%r_PA29xeu$qgGvoQ6YjIkk5icm+p_P5l zUKb;^>N zQX4A^6R+W|a5vB(0vE50c3D6P3YUX6KxDm~DXg)sn+zKjO<-6}TzP ziGPYO!p+il+!F96Zc+1btLF_x>|Z(jiY(Govl6!zF2`zdGH%aFz*h?<<7*3oaYuTn zD)u_ZO>~RwiZI|VZ$Iw#y@tE%Tk-E5XYqAs4fbv=QN&*F`a)UcjWwI`&8J?(e=l8y z|4Gik|HdrFw<2@c@AI?Ze&ZtCe`}#Co^!iv1|DdR#)EZ!c&K6w)((2z;{PD+=ut%& z-fhGq);8dgxjnL|`zU`YB1g#$*f*sf-(@Yw#;`JcxBti3Bz=TUJ+I+=)U|kY%ZF}B zKli$_@tDe2vESi*Rn+}IeGHE+T!F`}OT^=IX5$IjAvj=x83!f|;h@MtJaLLymh^L< zu?+_s263==KoNCwdm9d^_uxsjwfKIg3y1FAkHhkNRefBVym1qrl647BUA5OO>f!Mx z@B<6q!qWmi!4cD+#Suft6@5&KGNt1v&kj7jI|@Hovkpf$J}Qg38O2XvOIak2DVU3` z+fCT^e735ONwIm?@yzr&IBwYwI6h($o)zoB5BX|1!TgIlOy zUn6~nxiH)>_}_U=JEQ+}O}p$i_-NXBmt^GgXx{x7XV|5Asrt>-?+X3OcFCk8PA^7h S%(TQ>tkD@Zo5g0an*IaqsOC)o diff --git a/src/cctz/testdata/zoneinfo/Canada/Central b/src/cctz/testdata/zoneinfo/Canada/Central deleted file mode 100644 index 7e646d18e18851bfde743b379e52df4ec5b5a20f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1294 zcmciBZ!FYt0LSs~`O}?4B&X{LQQZ!myYnZ1OJT+`;uO_dnv$NlRLleVwQTVyQY*W4 z(LBi7!mRn%q?p;t8W*|fx+IxDC2aZEUBB<=*K^PM-oC%r_x=6-dGg(rRSorZZ6vxUrEG!rn{qRH z$afj{hqCRkuP?ty=>7NUXVJqM!{`z30rZEER`e)oL>ojkXoIN=Jx2KGvHsKOapQf4 ze(zI5rG{$kDn@^5NvPk#h7xA{ZM6AyZPggkHryjx~yRrC{DUzRX*VUukSZBsYkmY8|SR~Vtd`yI4% z?uJ6r%(?Iw+MBAOgW)Bi!?F7sdTV^#BFR5cN@5z1}`BnQb= Oaz#M0QYlx;6~e!?Qp8jM diff --git a/src/cctz/testdata/zoneinfo/Canada/Eastern b/src/cctz/testdata/zoneinfo/Canada/Eastern deleted file mode 100644 index 668e70d765dc3fb0eda16fb0f1932af607b53412..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmb`{|5Fro9LMnm5$Qky5i`X?O^-vkJ0Sc57Nj6yU05BHTItph4D|y$R){l(eIbcv z8YZEfvcXUkQ0oLegCM>r5lu6x;8#LijK~mh#jk-L?dRDa;5gI!=CiMReD?L(`{~xc zCNn)!y63p*4Y9=7?|o#yUK_8kDP#JqAIcdJSyEG^h}`kRWm)7m`Q|o}rC(LWi`-f4 zsfpZ`T8YcHyn=U!fJ!V)-mwF<`}egMLxO{@znI`upze!~2~U{B75# z_`A>jv7;I)Z%KeUadNt8M8Gjz1N^QlbgB$Ug=n8yRD#hmlKf#?* zTV-*s(^amB>Q}=Eh+P@IbZ^*}C z9d=o-N#P}#*nDsSw&XsItwqytL`H@tdXei#a8yz}Pdf|odk6w!OU?mhfO;c*6{=d6pW6okp(%)B2ZXWtu@_^*UcOR~P&)DozVuHS2 f(ASIlT4|RII->Q>Fk6&4(rgX0MMRh*%vQs{dz=-7 diff --git a/src/cctz/testdata/zoneinfo/Canada/Mountain b/src/cctz/testdata/zoneinfo/Canada/Mountain deleted file mode 100644 index 645ee9453073acf4cff9f9420b358a8ebbe40f93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 970 zcmbW#TSydP6bJBcZFP62EvItLOV+04w%a!D#ZB#MwVM?!iH?N5gkXxkBn3ea)s!n_ zFHJ>Ih&Jn`j6jWEiiOmqpqmdH1$No29t?|!3JMIT@BE+kP3RlWobx;1IWP|+A82au zu{n={Pf*a2=U%DhW2rncbbihz#wRIv-5pdZUyGR(%G#9+uoiEFyU%@wdm?F!?t7b` zz13<-HQ2m!LJsYi`QkL|FY&2=3d#~(&sZ{UA9U& zweqh*IjwvKHhB`T+5Qf;h$FDThGF4*H#~nb3R@?J`8Hzdvo33$V!Z}7%9F?iFEpi;3p)(LMp{}tZaaSAR!JPvP*bSTu= zzHbQLQGWss7F~ox!Gmz<=R+~Yko3$mCL#IaKWbgStTFzZ-qH+4UGG$x8MPH}ac@{= g;UJG{9{YJz%1q!W;Z1kgFZm>oJM8sJUdbc;1G${^$p8QV diff --git a/src/cctz/testdata/zoneinfo/Canada/Newfoundland b/src/cctz/testdata/zoneinfo/Canada/Newfoundland deleted file mode 100644 index 94d790baaccb72298bb577041cf3c8400339a7da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1878 zcmbW%e^AqP7zgl;A7duvm!mrvpsq3BxPM+Q2^!F4fX{}t+DbGN?phBZp!+T zdu^15WS(rw!v`a`QGQds05@pn;cwMr@R9Ay(0^3k1ve(&gY~h8;qO+A!c9KaaMOJg zd~CcJZoaI8zrV1jm%d{#Rlz?rtKpU-+HF)nUXu>De)s|WW2pc>QCtL{RPx}qbUAEH zn1tK;e7Iw&e>UCI8JKEAx^KciO~t~dp$o8Ct9+Zz&3&9k%2Ou{5tLmVN1#ke9r5*fa*QbLvYWv18^^^4IYSbmDBk^ zq1{3`xL0nayqM*!pd5OW4-dy*hc79(u+{%8JQC-GM<(>}Xt1A(=0*q3SSW2{8u+rl z6z5~+t?=*ra^Wjl8GN-w3}35^g8#@2g~wlAfUgVOustKfO84Ff3ARu=_;avhdIolK zY_PL`2)=1I!;>v-@SolF@L#9Q3YwoXm{gRvboKCbtq#8Z{vLRytO|C$riR_QJK)(( z>F}MzH2AKd$U^tr3yg#3xN>;z?q)01=N)`_!MX~*Z{flZjDE1^sMA8fGuG!5Rtok< zy|7osdDy#rLP2$(LWhddH}5>mN$G+8M9nZa`WWmVR15Q1pTfLb@4}Bfq>|eJ<*MvZ_c;x$>nJIOeVLi{#jK zpTVoL3dhO(@SSkn>Qp%H!F~gi61Wuc&a8X~z8X@L0 z1`FWKB|&gz>qa=ZvX%Q diff --git a/src/cctz/testdata/zoneinfo/Canada/Pacific b/src/cctz/testdata/zoneinfo/Canada/Pacific deleted file mode 100644 index c998491112ea5e4430b8266498cf7f23e1266bc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1330 zcmc)H>oZhw7zgm<&LSsSB-II7i`K6DC5aemGRRVTp){q@OoNo_jhHl(>EcMu)HH1; zy~)(LjA=$AhBv0B)Y$D}(Iyo;i(Jb!r{C}U4|v&g<~h&#JoEki-W>Jeg8X1+%`zhi z+O*VbAE_WQE7C3^sodDoaXK}v?E;+-+oU|5Z>l_Ct@m6JwKmU}rBhex#L@X7-WL9t zH4T5_Oz`J09o)yfh4s?suzsik?qBT{==p(89v(Ebz+dX0@pNzKxC4K!x(N?y&cojd zis0e09Qb?60r*F54E$3b3Xdco;^;l2&KWG7Mp-m$oC$$VHlDCaD}~2KR^jpHd3d6G z2>w;0hbJ3X1bWX@aT`2cZGdMkb@6mRTi6ND9eE7@POF3e#9e{sgDT+#zdD>>bjpX9 zY%AfVh07ehXW5t!uk@XO|GwG_ueK(`;uC+C{$J*f)r8|64`%Z^oS(^uUs-CfI(c5q8k`unZ~3&Kh{#i$>U~zJa5A_FfIV zzKVyPFP6X?3eLbTIa#nYMGd<~MZj+IaM;}|lV?b6v~!0&%)?-hnNWf5Hx0YNo?2IU zbJrrgrFj9~`e*>=N&`3&XSP+e!(Q2ru=lBcmhOGRCgJV-Uc$c8URdU@fn}=`0*Ntl zNjWSxyodcw$KZgDW;jq+#?#ymO)acwISL1ror9IN39#zqEsn&P;1VA=B>5~HnrRJ( z$+F?_U?Uu16A4FpTCwC96FKSuM=g)S(cLR>%)o1SXOp`?VoYq?Q+QYP5*&B`2E4m) z5RR{`=V>k>tpnb3{2H7XB*00Dr{Sbo9cON4ZedAY|LqaQ>$e$36d&+rmZDf)&e-DH o0dIDHs+vhpB%Mk6An9~9BO!<+%fQqSMX*8{n5t4KR0^f!AM7IBd;kCd diff --git a/src/cctz/testdata/zoneinfo/Canada/Saskatchewan b/src/cctz/testdata/zoneinfo/Canada/Saskatchewan deleted file mode 100644 index a3f8217a544ebb0993473bbffaae8e2d723c4ec3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 638 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1uA0$Vu}Ai(Drw-42Yh$WBmjWJ%2ZQ1Bl+5>i+>m zZ!_?C0HU|M8iM&d1hl~XovOlM{>~3PVE%4Cg94Dc-RIwd`Fq|8f%$uPawmYq4;68M z)gMlL4VFI=_zKKFYB3osf6VX&T9aP-`m#?=HKsZ0P`Qr%LMZuW+s98kLtX^{KuXy zVE&UhT`>QtrW%<4%-u@>WX^LTX9f`cLR|;UfAL8b%zypt1DOBj+GQ~R?XgP&OpI6| zGYeK>h+@|N|K~no02;A+0V4~LJ%ND(%;o`;Kr2=+U=Z=~4Po$g0pegF4hQ0Z5C&%; Kn+r&oaRC5Dz-C|o diff --git a/src/cctz/testdata/zoneinfo/Canada/Yukon b/src/cctz/testdata/zoneinfo/Canada/Yukon deleted file mode 100644 index 40baa9aba2a879f7a38a5a0f67e16e7a2d677a5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1029 zcmb``+e?#S90%}c%R>%@K_2GX?Df=~rmMBNdFW)5G23*t*VSxxViZb|bXYef6Go5` zj-D^(Lp;cM)!Uz6v+Zzkr)3RT9t~)p2-Dls!d&2i4yw}nZhxZ1q!#0Bix7yCYtv`|i)tJ3@5by2DY1ol>8g|4+ z;I^f9c;9GDqB?WF?Ztc7mB?8Q>`Nu#u6rr?@WM3g4}XBW<0J5qz%%%0)c;K`qiGVK=v2=PUB+H<4AEO&O=VGV7#8^a@&(EwFXD#1ZsnaDgpN+;tbCAZ(O&4yua8tS{ J6|`9t{{Yyp^R)l~ diff --git a/src/cctz/testdata/zoneinfo/Chile/Continental b/src/cctz/testdata/zoneinfo/Chile/Continental deleted file mode 100644 index d3fc9b8343369abf5f14be781397f426c5969608..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1354 zcmciASx8h-7zgk(i%aUHrn#jxS(@cGI-`!J{w_u1wUu^oxv)nZLRG`0wkg7?ZHPPX8fpsyL2um`9VX52~Hq)eWG^T%m z47RWyge_jr!j_8;@QPsrY&G>2wr>BVpvQ>K&^Rn>7=u?{9)N92dtkd0MuCnI`-EnA zRdFBe;8O!TZodexwr}FuoRjwv*lDgBb}`R`T@1Tn*O_S8ty>MRd9LROE%$S7ut%2$ zUR(JaUe_px9C>;aj%uHUHRYXfbb|rrG9L5v7>OzE zg=3XB;B5)#;W&pgur{cNqhmz-r4o*}Z-(P%#R~R3VXg*F9ISwM7_#A{euDYr?g%*L zfd%r^^m>8NO1spFJUw;--dT4R-sSs^V|j+Y3f5V_g0sSAa6YT+qrmbU=ZA1k<1;vS zz60Jhj@&vZe2TpNfME6PLdKB9Af=e?+`@M5cy1BKLJ8HFL z*^tl)mMm<`uNi4j0-YtK@iotiry5Uu|BXC$kGaSCV2VNc8#k0AH_)~DiLK7V6XNM!*2jHmr zY&d$z0Iz*f!4VqkI-}v3K_k4r;TOE2Jr<5VEmN_%jZP`NDg7tBx$rH#C29_iGZ2B$ zi2FVX$A9_;Z=JmkCoJBFx80lI+1&P-o3Qf6RXB0P1t+zhg_AGW!ztA@u{0@fVEjOD)wE+<-@7+99XXyh12||F>fHju;FO{`sweK0-=%7{~q4)SOI5Vn1ZwV zJg~8T0M2%~VXou}PuIxKy1TGRdk5ZSxdi8gU4+f*VUCUw^XCRQH?$kh^+;9hyJevn z&Kq~ad)x=%{857Wf}sr9`oJIk!s1qe&?vexfPS%Q7T(*^0q;|O`dr+jF*HISZ%~iGfAbV gnMN~}1ZGkh_4J);OthvatCRI98cm{A_xBX|2T4)%{r~^~ diff --git a/src/cctz/testdata/zoneinfo/Cuba b/src/cctz/testdata/zoneinfo/Cuba deleted file mode 100644 index e06629d36841463326ff3350bc2f94d0417c3cdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1117 zcmciB?@Lor9LMpqO--himAY(MD@|AFbhCvue_Zg_N;j`;5NU!$Ej6TwU{M$m*yb{^ zRfmF~ph?5I`YrAJSR9`zG9PUo{TTJ(@mE)d5(KfjZsf3ZTITc*bIdXP$RR zwC>M7iSz#cdidQ$5@G;7Ch6?vKcw0^J`it%Rdt2loGjEbx-I3;Ta3 z2jOK;E4(tsVA&g%_-|mWcOgJgcqS#P(mesI&MpY#xRx&>HQt;mQ4@sM@S1e1Ku**R zz=@Gd5?ReWu=+>4Ku(%(gOfjYN#wOsExc~L6<$AbA5Q7)6KH=!!?yr+qsu2zHyQnK zYV}<>t?4S9o)deX#&QDQoY0K@3~e=>u~-goS<=JWx5os=$JUS<&KxR(w_S9Iw7$JZ z2kRQm@QyP|cxOce&S%-b!r56x@Gip?oRfAP&ebePjE~$EFYebzX0g8eb2q$aZWP}8 z;xwG+y94Lnv%!Ym3vj{Z0=UrK2pdn;qNXDyXi-f*x=%PN((}xjAJF}#;aHb_Xt6f- z-ijB40XlbJ=@EKx>M3do-9$@lua1`<$@gYC@|jWACNv=MA_fTZ3~o zp9axGs%WfFMC>09hv3@&4z$i6!Mg2QH)?-rN9*15sCfIgs8A{Y(}({*ry1i{iN(qC u8%dEU%j3f=xz6TfRz52#`E)p$nqSNudA1^h$xv8Om}fH@4MzUWsQw4Ss79v% diff --git a/src/cctz/testdata/zoneinfo/EET b/src/cctz/testdata/zoneinfo/EET deleted file mode 100644 index 231bf9c3b713e3676dbd8f3ced867973c601e104..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 682 zcmWHE%1kq2AP5+NDnJ+nLI`Uy2P$I&VyXW?P+~vB1w_woP;3CvJ8ND(0Mp0TUjWf3 zKP7|trvz36fcR&gdkcW*v#WeQfar6JB*60LCubIb`1gh9C4lMeTmc~WaK4F40MXnM zUm*0^bs#PS&))f9ns-TP1Bk)b6APyKTg<_3w6toIV3%fNXfcPTD zhrs5GD!-lp;)@C20n_5lXCd_GePCMR@p>>Vd3gbtmO4BUOiSjNmeXKbzhn=XHb_|urVV3n3NSJ= zF*C8Uu(E(?;vq1QY(P!|k}M1iS_X_9K<_Is@B#y0fI$$%W)$`D4PkHuVprE-5D~)Q f48}kX7m%lG1QOTrHP$oLGtf8I@ijC6vrM=EZ;PKG diff --git a/src/cctz/testdata/zoneinfo/EST b/src/cctz/testdata/zoneinfo/EST deleted file mode 100644 index 9154643f4c9189998392afb8a93e2e2eb9eaecf5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 149 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%klC�HV9UB)(u|`u~4x0Rsb&lwe@_ Z|9|HO1`Z$J5C&%;b`1_;-~tk+Tmb&%9IgNW diff --git a/src/cctz/testdata/zoneinfo/EST5EDT b/src/cctz/testdata/zoneinfo/EST5EDT deleted file mode 100644 index 2b6c2eea14df07392729ae9f5712a44ec4f02bae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1744 zcmb8vc~FdD90%~HLuD)FSXb_AZECl}O63S8VJF8nxh5}Dn&pq)VT2iS6v+%R8pbh8 zbU9ZSR%{`w$+%iaIr5f-h*vpM?0TNB|CxR}&wlswdw;)Y|Jv0o(ys6$|1BFj!450U z|5x;MtP4H8th8e6#JwzaIfHnX$F6+fSRUU&;LO8!;S+K7@X6%&0(+jd@;sca%Ej}X z`IRE;=StJyJpZ$Bo+TUer+e;!PuHfxXIgpqtWgV}GtYz1>t@0F!m;p$ByTwX=vNYrz$W!Zp51fXEeNjgj)5!MqB+*D zbPa(ks{`RXJ4Lu^_}9P5bzslDwn1d`k3wF;kE2ZRlOd(>Q&k>ZO)}vc=`OfNNQR$T za(TA@yetlWQJV(8JhhEu{aWKH_*GggEa=p5opw50pQMCeM~sFWV!Fd`q7?$$Zw&Vq zS-uT$hu_KE;P<^-;3kJJaMSlk@P|e-{PD>}xY<+;e=0R|?4Hm1DxRfytQh{1UIe#n zJ_xra9Du(r-2i`!Tn~SrycqtWTm-j`UMH}7e!5M7+npA|?QIK0*6(;14F9SQf`3;G zge{i`z}8%=Kz}2I9JGimY*On4mbU8z*p9bw%=X-Go@JLg0>{!JY zr4e$tcc2U0NA3*w9VX`pt$t3;aDQ88xPOa;XMK;lW_ZBEkMO|j_u)bL_u#>q`S6fL zg8iXe_rt@Y>fzxl^#Y+aLRAiroVgDkCC!0lo@-#4r0bS00!_gZ|T%(YMJJ2mCH46+nSoWw9<*%M#eTu88u6kiej;Z)WRWASVq`B z7zHWasI-e&mZ3rh<)v~NCMeVvk;_b%PQ~T2_dNXpe(a3x+3!5h3qw@r9VnEL1rLi^ z&^JBmg&Gk50gKhK<#ZOVF@ou40|>*2QzR`l;) zIpE$4g|PWf3H<()4(>a9FNZ#7OW2R+ZH^dt#J2?=>DOWZW7KJAw3C)hLU z8tj$E!G4inzmZ;eN6688kNKcydmcy6?vV zE_h3Isf93StJYwqx$UUdLNiUKfzx-U!14eW_8DRxoMAZ#XL8)&%%>dev+Q5t?DH+? zw-2&(ggJ`*HuQ?h-RKoJoaj}>8(~#LC3@9htB#oybwmaFf^56ajrD(D%zu-H{wAS_ s*0LSs)l?_R(6_xt_b-EO;|Jp6o=H?`&9 zFgwUehJ5Q=GMH@!%xSsFjIbV_hM4VElK}^e%!xT&5}KG>*b49F>-@t7WdCCcAN|BT5!Rb6!lxDr*7-iz zprQn1f8(GAHVuctXZ5}CdDR9@)?eJJLpNvJ!V6D-|tkR=Tpw17xFHlHIe@4#mf=s9|2MDXT)K+>!gd;j`g6IH>S`l%{A!NX&tzhTmsjXjj`l^q7&OLAaXqvP&c?3>KXb%eMuUt z$^jbkV^}*jAa6kijjHWviW$b;60}Li8rrnd0&NyIiss)IL-UYkXpzK++oc82Qn3iF zT-50lGpv2up^eU4Xlq-{I#B_4Xw#rwYX-C*FXEH?97@aK&X!c@cr6_| z34*%<<;LKBpvWm;0X&eZ7A^HaAzyCZB43bkvnbSX1P90&+W6U*=2~R0=B@qQlCE^2O#(e}YDen*dSF1_@ diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT b/src/cctz/testdata/zoneinfo/Etc/GMT deleted file mode 100644 index 157573b1d340e0f57a0dd4d9698bd3798cbf7136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT+0 b/src/cctz/testdata/zoneinfo/Etc/GMT+0 deleted file mode 100644 index 157573b1d340e0f57a0dd4d9698bd3798cbf7136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT+1 b/src/cctz/testdata/zoneinfo/Etc/GMT+1 deleted file mode 100644 index 98d5dcf917c6f1d9bd0018db0dc4dd0590e6a8ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113 qcmWHE%1kq2AP5+NDnJ+nLWtMG^8f$G4-5>t28Ik=HbBzOkP859w+SEs diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT+10 b/src/cctz/testdata/zoneinfo/Etc/GMT+10 deleted file mode 100644 index ecb287e667868e92d97cdf5fee601e09cded0ff2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 rcmWHE%1kq2AP5+NDnJ+nLWtMG^8bHv0t17tp#cMz4Un`mG~faNWzh&i diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT+11 b/src/cctz/testdata/zoneinfo/Etc/GMT+11 deleted file mode 100644 index e941412971a4d805e311e8e4e7eb37e10994e4be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 rcmWHE%1kq2AP5+NDnJ+nLWtMG^8bHo00V=rp&h_ diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT+5 b/src/cctz/testdata/zoneinfo/Etc/GMT+5 deleted file mode 100644 index 589990ae8966d1af67f1e05c21e14149adec2089..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113 qcmWHE%1kq2AP5+NDnJ+nLWtMG^8f$N4Gavr2Br*LHbBzOlnVf6w+OTV diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT+6 b/src/cctz/testdata/zoneinfo/Etc/GMT+6 deleted file mode 100644 index fcb60ca2465a3e0c4febd41ac1a05bbb39fd96ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113 qcmWHE%1kq2AP5+NDnJ+nLWtMG^8f$p1q=+j24)OgHbBzOj0*r{_XwE) diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT+7 b/src/cctz/testdata/zoneinfo/Etc/GMT+7 deleted file mode 100644 index c0427a40eef929dcf25451be77c74af6e9111065..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113 qcmWHE%1kq2AP5+NDnJ+nLWtMG^8f$b2@DLn2IdT0HbBzOoC^SBHwbd{4F!k* diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT-10 b/src/cctz/testdata/zoneinfo/Etc/GMT-10 deleted file mode 100644 index 11d988e10a3e318a7cba485d995872636d1acaf0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115 scmWHE%1kq2AP5+NDnJ+nLWtMG!obk8fPq2V(13x<21wfJ8X9l`08Lp2#sB~S diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT-11 b/src/cctz/testdata/zoneinfo/Etc/GMT-11 deleted file mode 100644 index f4c5d5cc29b5c1687e9728b6b63cd2a5328c9dfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115 scmWHE%1kq2AP5+NDnJ+nLWtMG!oV10?Nqjko|e4F#zH diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT-3 b/src/cctz/testdata/zoneinfo/Etc/GMT-3 deleted file mode 100644 index 4eb17ff0057b8843a0b840c6fef4b77accfe43b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 qcmWHE%1kq2AP5+NDnJ+nLWtMG!oZ+qz`&qwV9dZ}10?Nqjky3h4F$>o diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT-4 b/src/cctz/testdata/zoneinfo/Etc/GMT-4 deleted file mode 100644 index 13aef80cbbcf0c938b8d11d92b0755e146a501d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 qcmWHE%1kq2AP5+NDnJ+nLWtMG!oXnRz`&qwV8Xy<10?NqO}GF%4F&4} diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT-5 b/src/cctz/testdata/zoneinfo/Etc/GMT-5 deleted file mode 100644 index 83a28169552f4fd39e9d0322398d787aad303e3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 qcmWHE%1kq2AP5+NDnJ+nLWtMG!oc7bz`&qwV9LN{10?NqO}PL)4F(JV diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT-6 b/src/cctz/testdata/zoneinfo/Etc/GMT-6 deleted file mode 100644 index 79a983e5454a35f134cd4ad736ed912f3deae64f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 pcmWHE%1kq2AP5+NDnJ+nLWtMG0#u#Az@Tkl#=vC*B<*y~xBx#51}y*p diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT-7 b/src/cctz/testdata/zoneinfo/Etc/GMT-7 deleted file mode 100644 index e136690e165a933fbad2fdc0aba8d97886714fe0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 qcmWHE%1kq2AP5+NDnJ+nLWtMG!oZMJz`&qwV9vm010?Nq&A9+U4F*mC diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT-8 b/src/cctz/testdata/zoneinfo/Etc/GMT-8 deleted file mode 100644 index bc70fe416fdbe3abb2c636a7bc1485b79e03af13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 qcmWHE%1kq2AP5+NDnJ+nLWtMG!oX0_z`&qwV8Os;10?NqEw}(f4F+!j diff --git a/src/cctz/testdata/zoneinfo/Etc/GMT-9 b/src/cctz/testdata/zoneinfo/Etc/GMT-9 deleted file mode 100644 index d18cedd524f4cc132106d822fa8bb9bd3779edab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114 rcmWHE%1kq2AP5+NDnJ+nLWtMG!oW~Bfq_BWz>21wfJT5^GWBn-F!C&C4S diff --git a/src/cctz/testdata/zoneinfo/Etc/UTC b/src/cctz/testdata/zoneinfo/Etc/UTC deleted file mode 100644 index 00841a62213e6cccf7f0b7353e5e8ae214185486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S diff --git a/src/cctz/testdata/zoneinfo/Etc/Universal b/src/cctz/testdata/zoneinfo/Etc/Universal deleted file mode 100644 index 00841a62213e6cccf7f0b7353e5e8ae214185486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S diff --git a/src/cctz/testdata/zoneinfo/Etc/Zulu b/src/cctz/testdata/zoneinfo/Etc/Zulu deleted file mode 100644 index 00841a62213e6cccf7f0b7353e5e8ae214185486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S diff --git a/src/cctz/testdata/zoneinfo/Europe/Amsterdam b/src/cctz/testdata/zoneinfo/Europe/Amsterdam deleted file mode 100644 index 4a6fa1d4945d6646652e2972ee8b632ca64c00cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1071 zcmb8s?MqWp90%|_-CD>^Z?opIWv;buxjFBgjb8LZnS&xHt1c4eqEL*$7i*31MG%G2 zi}qp-p(0Du*)pcihib#khtv$rWrd-`S4l`@7DQydsdK*j1FUm6=X1X2ocrT)uULJq zzL;6JNyrU4XcO0eR{_FC2aGR zdFlCsi)+a3E-i9LRT4SikRf+kV#p75Cy|5v7<_bU33kalQm$6BwBF<8Ysew~19E8U zEOPgkdgPwqVdUP#9T>i@hkbo{u-|ovrF91U$Kar&06w{ps{2%6k)MfC7|B|N(b7gQ zeJ=WS7I{c@9(ibf1;&1LVm}^9AP*QE2d(b5X@ygs<|(iNEB;D(x-TDYr1gxZ5PxZ7ZXIyDdXuqw#QtUg+w z|4{<>e$>Hzb4pk+DTn&OHE0NYf`!dVXl$B>MV=TG>bjxHxxl4K{=G}nY2P6Gug);i zX8Q7qfJBP*Mly#Pmh6m56bzHeF)H%u@+ImDyU0`?7nw4mUJ!}}GMmV3wTWbqgAB4N VG|{EOZZ_^W3I@ALpca`k{sL)%tV93+ diff --git a/src/cctz/testdata/zoneinfo/Europe/Andorra b/src/cctz/testdata/zoneinfo/Europe/Andorra deleted file mode 100644 index 38685d4219d244f56f665c8afb92eaa6737badb8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 389 zcmWHE%1kq2AP5+NDnJ+nLI`V-1S(?zV!{7FP-nJz3W&bqcpIdhL1xW50T3-aXFiyg z>zM$i_1pp_iI+y?e diff --git a/src/cctz/testdata/zoneinfo/Europe/Astrakhan b/src/cctz/testdata/zoneinfo/Europe/Astrakhan deleted file mode 100644 index aff8d82d2a2de0857f78217cc9d04a112d1e1a08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 726 zcmajbTPTBJ9LMqJ^={F&3l|P!oAWG(F|%nHUS<}iq~*e)_$%Haw{N+K!C zh4Teh4oPmrT)9IjR}N`6QsnUbf9~Aud3&Bu-{*aw=i>FW^m@%K>=5`DG--IkACdTH zaz3Mf_*hpv{p5Z?*~s@;tYP7Vj8k8k$oQzB1V4mbQvJkE$b=g!-X~s;qcw-K_q4Cw z9EG|iKTMkJfyu+oFs080Q`>AX&7B3)?TIiWR|)l6MTqf{sr-Znxxq(mcvHiy>z5Ad z?6YTd&fYD|4FsWa?il8c?ZABh3N&@kz=HO}5S=#<%)`R6WoT&{f>zxKEHbzL`PB(+ znn53(v)xsri$7b?B}bX)(i=P4zUF{s2T8DeLJunz8I-({uyRZrqWh|xk7!5NH@aGX zfp$9X(KYfdv@87-?Rq_jwPN7Us|{H9Fahhgr=a_C)kpU?O!uQbZe0g;^Lva>5F`FQ zGC?MYw1j^|L1fIRqPwz9OvYGEqY%aai^TYzO%hb@1`o?I74m82)4~*XzLpy;ieIJ! Bh!p?; diff --git a/src/cctz/testdata/zoneinfo/Europe/Athens b/src/cctz/testdata/zoneinfo/Europe/Athens deleted file mode 100644 index 231bf9c3b713e3676dbd8f3ced867973c601e104..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 682 zcmWHE%1kq2AP5+NDnJ+nLI`Uy2P$I&VyXW?P+~vB1w_woP;3CvJ8ND(0Mp0TUjWf3 zKP7|trvz36fcR&gdkcW*v#WeQfar6JB*60LCubIb`1gh9C4lMeTmc~WaK4F40MXnM zUm*0^bs#PS&))f9ns-TP1Bk)b6APyKTg<_3w6toIV3%fNXfcPTD zhrs5GD!-lp;)@C20n_5lXCd_GePCMR@p>>Vd3gbtmO4BUOiSjNmeXKbzhn=XHb_|urVV3n3NSJ= zF*C8Uu(E(?;vq1QY(P!|k}M1iS_X_9K<_Is@B#y0fI$$%W)$`D4PkHuVprE-5D~)Q f48}kX7m%lG1QOTrHP$oLGtf8I@ijC6vrM=EZ;PKG diff --git a/src/cctz/testdata/zoneinfo/Europe/Belfast b/src/cctz/testdata/zoneinfo/Europe/Belfast deleted file mode 100644 index b9e95d92623c6cc4c35b16f7ceba3006f5ce4934..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1599 zcmb8uc}SCC0LSrnPAl(aIc=KGEM>Ols~w0Dk_2U`XboCMsYHe-F-0ts2>*ysB4!wN zXug`Im0Dh9YNcu3<~b3|vqR^RM_Kb)z0dEZzr$yY&-;CjcjIM~2Ze{ZQ~w=2b_aQr zA^-o840f9V`(FQt9imf)&BS|7`3&qa5EIkdXmomZ4ZNS04l`0kkhxkeCi^mDm(f{g z)6fs%8_?PQW$>Zb66POm3xPS#buiaO$~mEB$bFtrU7Tu5%sbIe`rF&3=&E}*u=-*ue0OOD)+pj&ZD2M-_P_TyiLUdkhV_ab z%-8oB!X}}UitKAjJpr3L>|o172EN_ET#fuF2Uf=H)qNfwip=UBKqh~{X&~sOU(LWA{!JonV;k<(> z)_-|9qJLA|IiL~pcizbSYNCvMlX$V&uuyWDSD;8LP`FYd}W=Os4r1KgMeJP z#?TY4rIR={w$M-z$=RTTMl=4@aDk(Wc4EXtU=QX!EE6wBU{mt`Dq&7I6Z& z!7U4JRLnt3#|ah14xvXKwBolyYwKLj&(Gi{Z4wmKBtx6w9056Jn^yogS0_Td>ndoU z83DzS(a<5m4{q_5L&s28xK+9bZaaKLMegThVvTlo*@1SR-vuQ`=A3FFbkWSh?Il_$ zZR~6l` diff --git a/src/cctz/testdata/zoneinfo/Europe/Belgrade b/src/cctz/testdata/zoneinfo/Europe/Belgrade deleted file mode 100644 index a1bf9281ed1bc2c9b82ee64efdca60b4af762ede..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 478 zcmWHE%1kq2AP5+NDnJ+nLI`V70V-n#V&4Bi5NGqj14N%%p|-hMG`Exl*207zbD%{nkG zJ7+$amg|`SrsZoI!L&k75tvqtNe0tOJ|SRQ*~S%2tLT`4X;m3@Fs;TT0jAYiohN|I zSO01PrZt|bf@#gGVqjY9C_9+e-tq%X>nwQ*rgf*>0@Hder@^#-$sRCmkg^s`8^+!g zU}Pc;85o2uK=$(qFt7l9sldqL;~T=@>dvkd2lLM@at8CyPci}17n)ST^u;1E2)%6@ z14#X)hAgbsZ@%eS>ov zn7+w$5UlRz%L)NdI0*Z?fN2rqUlTxlQRUZQT1@y3m=T6)i30g!%~HS55%?40>vTCQgTn3k_;1k(yRMPOPnCK*gC`GkOJWgAy8t)gQF zrd4Is!L%BW1ejK5b)En+U;V2InAUiz3Z^x$ih*gZqwHW>d&>_nt+V7MnAV+g3ry>^ zoCeeSC40cMLCRV%Z5Vq~fQbn6S>(K|QN>!DsS}id!m568)i8~32&`2Z(8iT=r7z~E%5eAQn zSR@`x4U)2mMB@D@+So*-EE183h4cNpNEhekJHPw??l~v-NbP;SRouUWXDg^^NdIrC zXUh^vG^rc0hb!QuD z)uBa2nWjf#V>42rrMraPI zVA)X;EcbswaXkVn=EBf2aRMuc0?_K&g0{|(z{khMJP9#5_WPgAaf(U$F*YZ#>+AVs tj!PFf1@-t0ms{dmSvecqXp*=l7E;+ug^gOG+it10SVgzZN>-LhoqO>@p^wOVUsb1!a_h#+h32XiZ-QDS9*B1JEZAyHA0FetGf zW&{eewrsjAon_86r)6eal=d>U96^wjMNn1*(l2(O@BRSmT+aF2?{l7e;9jn^^iX9k zGwo2o*}QD?X!_hsubkwr_9i6sD{mDGVHg=4ah!)3*N})!PbN`F~8|; zbk5D`{m8f86vMXA7TEsO2mL-7?C|WcQUC4p0^~b2hheA9?4kNydnfEFR>44Fsg&y7 z8W#Cp?s3?Y{4?g<6zu&z2JcVQN~yo^?GG3Xe}Mfx5jfzk@zDN*h5+(IS0)@hQ4b#- zya0zvPQu5V)gI~}-mnMx$;Lq#Dw#k%6kPi!_7 z$-Y8S>N}VoKN9oT02EJkz>J6oN`~rSX0V^7bF$j}a9N`pF2Cr6D^6EK=@C0zxwjmy zGFzc+lL@X?=0SOu0H;aOZ*G`0?%at diff --git a/src/cctz/testdata/zoneinfo/Europe/Bucharest b/src/cctz/testdata/zoneinfo/Europe/Bucharest deleted file mode 100644 index c4a391e73b97e1342d352c5cc15a0bace202deef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 661 zcmWHE%1kq2AP5+NDnJ+nLI`Uy2P$I$V!{7FkaPY42Z-Lj;S!kMY4_ncVy03^S6$1E_tZ$&ql-an%TOdsgT1=9yB;=uHw41X|vIKlx;AMr2* z(?>0o!1OTr-FD8I!q2LDrAX?a$`vQm-F}{!hqD7VOHh^d`;d5YG zoOwTl{=5N9OFUi(rX?>=0@G55o58g7p7jhMAhTuxn3kP05lqYVG=XXPnqn}mkdp$Y z6=Oodw33e-m{zs{1sel{ijD@DR+W(i(`r0iU|OBkv;o9W|H_pBqBWlU2Gg2X-hgSX zBX_~H_Lg&CT4%|AFs(af1DMupnGE)?e#s;--yo$F%r}f(_kaNijEbtk;b3&K=K&)# z6B&@1fkC1IWE7ADM!%K;BL^@z6c~7Yd_x$VfY{YF7(|3HZ~+NjBM?`|*I3U~&p_W; M$JfvR%rfBu03YwVYXATM diff --git a/src/cctz/testdata/zoneinfo/Europe/Budapest b/src/cctz/testdata/zoneinfo/Europe/Budapest deleted file mode 100644 index 940be4670a64ece1265dd28523d78a80f9008dd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 766 zcmbu*+be@%90%}sMj|w^1LkaI%xs2I?q*lKMcyk>ij=rm+6Co;wJW)J9U{zW&V^E3 zD9Z6d&WB+xv@nOeA?0ekzpp>Qh3D;gK7F6}_x#=iSJ_aX%ltV+LIq74+}}rvg)*@) z!@q^mDDQTV!(s9o=(_ch4)+pIj!dn>(KQ~9*$3eG(5{5;Pt>&{J1w!ulWafS|5!!8 z!{-v@qj@>%j-4jtlb$?yYE!|p!4?noJMY}LkQZe$Jb76nZ6{rYJE*(TtibD-X?PRz z`#g8R7V6!vE!e+z&iUxvL-{-2q{K9#VU*5KP`j1hp+DAqk z?<}M=^#sbIHlbX+{OgAkDjs@a%!M7s?sW5XE^d88LMj)QV7y}tCUo&Iv8@9pH8sQJ zs#=&*%E8nkGfdMKK$TJr)58={9c1FEzxp!|W_VRlvHTQ0uOyncJKS>nGFcA_aq?F|tlevNxjtLc(Yy(9tYt-fI^jg-S ICv%LUKPFBV)c^nh diff --git a/src/cctz/testdata/zoneinfo/Europe/Busingen b/src/cctz/testdata/zoneinfo/Europe/Busingen deleted file mode 100644 index 388df2969f2dc56738183bd4f0d5755c4533a797..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 497 zcmWHE%1kq2AP5+NDnJ+nLI`V71uA0!V!{7Fpz`5W1BfoX!qx_&Pl;zSfayntVEXiT zA25C9P%y}N22thL6F{_>@EtHM&U_X^f8GbCB_6K_(~_4LfN8126T!6fp1lGfeKKp- zfoa(}^TD)S&jc_nU(*Pt6>^Hev|>y$m{#%$0n^Ghu3%b4#|%uX%BX{BH695tt=5u1 zG-;$S|411>wwh1Be|%(i5C0;s9K7mC-tBlLBJaoiFvFQ<*z@5G?6p+V8)2 z2|l=W8a}*O2?y#9!ABMO@Nr2Be3Gq!gS*4vQ?(R63)ldMT!e7A&uXUke}25mNRE6? zawcE2N*c(~Yg)9eF&vI1H<KZkZvg@7b;HD0ANR1U8daMyGFDgfe<+V@o<4ken z#2BfJzD=<3v^uErJO{Ta4lMZhFjTwOT49o+oaJCwq+-60ml$p`S`f_w?RwYa;&4Q+ge3-6}gc%YI%#^t=I46bKVl|_Y z{aR=t_s+TzET{XEh1@s(hhVuab}+B&J{5}a=);z3z!x${xt!_7gc@@rp1KsfN62&vk?08J}@ou zcs-bwyu1KROC6pFrlt4n6#(g%S+fpI%g&h(rsaAjfNA-fMlh|AQv{|JW0JwNl1~Vj zR<>~k(<(YhCD zf@$3;x4^Vs%V{vJU$O^G8>FlS(}uA(1sIu`NQDdx+-E?}0g}L|l~G{iU|`@AVBq!f l4PkHwVb@>~5yHR)By_1pvDSt+D_B diff --git a/src/cctz/testdata/zoneinfo/Europe/Dublin b/src/cctz/testdata/zoneinfo/Europe/Dublin deleted file mode 100644 index 17d2b1582df89d5794f20fb028956dd9da154922..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1496 zcmb`{eJs>*0LSs)l?_R(6_xt_b-EO;|Jp6o=H?`&9 zFgwUehJ5Q=GMH@!%xSsFjIbV_hM4VElK}^e%!xT&5}KG>*b49F>-@t7WdCCcAN|BT5!Rb6!lxDr*7-iz zprQn1f8(GAHVuctXZ5}CdDR9@)?eJJLpNvJ!V6D-|tkR=Tpw17xFHlHIe@4#mf=s9|2MDXT)K+>!gd;j`g6IH>S`l%{A!NX&tzhTmsjXjj`l^q7&OLAaXqvP&c?3>KXb%eMuUt z$^jbkV^}*jAa6kijjHWviW$b;60}Li8rrnd0&NyIiss)IL-UYkXpzK++oc82Qn3iF zT-50lGpv2up^eU4Xlq-{I#B_4Xw#rwYX-C*FXEH?97@aK&X!c@cr6_| z34*%<<;LKBpvWm;0X&eZ7A^HaAzyCZB43bkvnbSX1P90&+W6U*=2~R0=B@qQlCE^2O#(e}YDen*dSF1_@ diff --git a/src/cctz/testdata/zoneinfo/Europe/Gibraltar b/src/cctz/testdata/zoneinfo/Europe/Gibraltar deleted file mode 100644 index 017bb2e34746c8a11c6955d49cc492c974412801..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1220 zcmb8tdq`7J90%~bragw(ikvoW&C0EbSm$uV`id!*>_53ujr_DI8a5m+gwIY)!bVd*Y}#RENq_UYJ;*KV z8=%wVMcwI}2U|rlhV-=-?uKnH32Z;M0d`bSurtFXBz;}XAaeJS{m^9=q3#;j!Je!s ze2zO)f%|(?{m33kEV3tQ66ZVve)M~dHtc(+_}K4LUqJ2~y9|BdIYCE0!~Q@dOTNde zwoc^NO=HM!sy@MiG7;+jf_CJ$=528Ba4zaYJC(@qXa)v!VetJXJN7?BE8xdPG|RoS zR3yKHfj{bD)KEEG>}H|3@gj__trL>I7+V=!Vkv==^9)>i>NJ#Qn_=wUOt?%>!{r-O z;0o1R7#Aalval#94^3vs{qmoy;mSZ9RCq*C**piXsv3nV>oANj@Im#NHkgoG3pEGq zP`mG?a2D@>C!hCcl9T+uoev59*PNdIH9>w(xR4h@q~>yeos<_wD%1k3BlHHEO4>zJ iTZvn^MRE#xxP^dQ#cRn@Wk^)7QEOBNt%jJ8DEJK=B2RJv diff --git a/src/cctz/testdata/zoneinfo/Europe/Guernsey b/src/cctz/testdata/zoneinfo/Europe/Guernsey deleted file mode 100644 index f2d87c6bffb6f59351ea8eab944941c97259c896..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1611 zcmb8uYe-XJ9LMovo0(?1%v;)J=8f5$N3#$iA}h+<&>A%Ag-K*czL-NKi->{UcGEPcq^aqKtkjvA&P!gp&2+Q#{LY)+S!bN{+4p(==P(XTb|f(&h+6ir zU?<2)4%zaz++)YA*wbx^J#IYA93tNFDP^G6Qb^41q|tZto8Z0dyD%rq4KkPNg=8)_ zbrGF+A{%}GY%4lnS_dEOTEO~4?_;pQw*?mZi8&{X40+BYs)tkKg!N*>3@lM6!P2(( zu&h7|%b7HW+*fg#Mps_zLRTrGV70Oe*2G9)ZTJx(nSV?R&`*L=VV(UPeCi$@+q8skG!^YED@bwuJY?7zJ=Gc6O%)bdaif##Q zglf4K>uQ}fY`vJHAam`bkpf~zk&BA>E^iOI^I9}Xy%2MO zdyb3n+}?0KTC>RmtqC)!$h>Ayk9n=M1p8Vu5Bq(RtLVP@8&GGb;GCF*A4Xgla{tG- z@6i3t^XP$^aX47!jCK9>cJz?)0Q__+1?$5H{m`FfDmW5k3%~3v#r~+f2#z_*us*i1 z8f`Eo!*SgdoajFUC+j=mRP}F${I0LJE78*zPNHXW&Y@@H!_jl+x~)Ettk__4;2W=eH%*3;Ks&uxao=t zZq7Xgg-J^2aUmLRiIPFj_yFi7-T}QMB30yhKDMrCUq64e?~h<8va#pXI72_fEZkaS zgyOay=zm=YB}KI`Amurv)3Z27y{Huy|NG(d@Ug^=-1XlcvGU)>{+e2`v}DR5Z^BMs z!6#Cy$al(?eb+(@0j^G1;YUTwsIWsaYCr3qedJ^#Y%hDUVV7ujOB}sTvRy(41d5{r IY4XkH4=c&|=l}o! diff --git a/src/cctz/testdata/zoneinfo/Europe/Helsinki b/src/cctz/testdata/zoneinfo/Europe/Helsinki deleted file mode 100644 index ff5e56530570974516d249927952c69da601b664..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 481 zcmWHE%1kq2AP5+NDnJ+nLI`V71}b9#V!{7F5WGumHi%wQoG%TcPoE1+0MTa-JWT+q zVGvcm+W?})gwKI#apwIH`tt@bE%A8$1fVp7S)C_<%vb+v z0;V;ds)A|Ft72eU>nJ;z*52|1OzSLp38re#ss%ZIH4SOdH1D6kud# zA_N&2#8W}m14&>|Y8fzc0KKZf!0Y21!r%eKuCBo#B7}hpNaz}YxH`VZdZu~?`o=oG Kh6Z4k2^RpC0aq3P diff --git a/src/cctz/testdata/zoneinfo/Europe/Isle_of_Man b/src/cctz/testdata/zoneinfo/Europe/Isle_of_Man deleted file mode 100644 index 9f5aaffd4f803b999658c91e3353d31d3d396076..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1599 zcmb8uc}SCC0LSrnPAiXenod*GnHSoeuXYecND`E$QaNZ@q!JmTgo;=e5&jWjM64*R z)O;&T%lj&`OVhk>orvb0={)i%YdW31&+nzb#ph*w-tTj~8!t>66dvYDtvPt?4)P&G zy7rMYcAF0SF=VU!;%iYbJ}$0V@CCrCv0zo7-_x1MpZ)My^QGm&x5biy(vB_jLZ zchA8Oy(i(v(hm5kK*Nyr&ksw`<;hmC;&KxFa%BZp%HmtOOu_~9Y}z&ST&NFv{(3O_mv0#S9efZj*lou8 zA1{0KUup)evgQ6Cs=+q&qGk;1OXWpq^*Hz5mak@^S8Cozk^dz>s#-+Uc9B7yW0`P+ z?moDYzQw7uhPr}C&RPxBn+<^ag_aD(4ue)2z4`7k+A!Y)Z4}*)7Ce$b3OH&G}8x!XlG%BoA&?-GY{tccIl#hJc*2&d!C~DiWd1Z8@}k z8UaO-G0-l-A8z-PLi3(h*KeiuF5&MqgVyS zbsf;{eh-wqDuM2?A0VBW#5v|bY4O&3@p=C*a+1G}^V;kEDlM(mRdo}26@~(yHj&!I tzGe~6fXqL^oe}%*l|j6@_03WZimUM>(6(qq%OZe?4YG+iU~q@#8%7`<^tk zL+gW{&{qJw{j7-*faZ4j>uX9k_rVRLpDDSEXC!_7&UM|3ozBb%#WR9z9=R+a^~>r-L0 zN(y(x3!zxVhcSU3DDjsx(ETOutx)=n2V)(7VBE_EC>xrA@s_tRp}oaL`x0C4qIaIW z4&_ysVN&@M%oQiPU~+mlOer`6cZHkaZpC4*D-}=~cDjM?tDMb5r+G@zd!ELi_fD(O zDytTzKaPOv3u34-Gccnj0PbrQx#)iTb@OO#@~ diff --git a/src/cctz/testdata/zoneinfo/Europe/Jersey b/src/cctz/testdata/zoneinfo/Europe/Jersey deleted file mode 100644 index c83814dd6ae9edc95de7d58f756eef687edeb948..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1611 zcmb8uX-E`d9LMqT&U-Vj)O5`YZCyvR2tgt(N>iy^Xt5V2ktOH4H1S z(JVEOJj?9TG!OFD717i+GhL57%380rd4BVzchxL2pZz}1e}-jXMPX5qUesR?HFkoW z=Hq6big3OJ2KAFo)*hJ@F z%tAj(YC{)<)WOGxH?aQ1={ziSX@Ny<0?s)lL!R@L>gSZ1VZB7L1WQ|EU|D+~EH4a! z&zMAp+*fgvMpxeLL03tFV0By-tT`owwE>bNWwWc4@agf7;^uok6q}| z<~8(K%`6-*H^;g>y#qZFcLIKnj>r1s88`G7krYmO8Njc;W!Rs#c7-#hBCOAB=%W=| zv2b>H0nUwv!uk4cxKO>$kl*#~VI_Jo`4W05_ZoURA^^Q|JskZ#FcSUQasLaYycfNun#TTmLp6G1hI?jhpf7Fn)@QIqPVyJbh2x{y4 zKppxPr@{v6@?tpKR8Vgz1nO5=F%)|k^w4O-v`w^8g$dd?b_~sXAcQ+lH$am_9^B=b z4^71@(9B^@O0kFep%!SN(FrXri#R8r!QIMR(5fj7T2B=6$bB}Y<#119Dzv>Vg?4$- zkRKBV?URGy-XIZli12`pf`ia0@T8PH&)L8d?c(N+c3Jg?u6o9tGIQvrScdy*lu*## z58cy;p|H3Xdc?nmbZQ3Yv?Hai_P-xZ4Sck4BX|9`M`-`s*dJ5s+uJH_@+ORUYMMl9 z2l-AJu3SNE1E&UBFZmRL>*`KKSoYA{Eo60J$8v^w*OelP2Hv FegniE_Q3!E diff --git a/src/cctz/testdata/zoneinfo/Europe/Kaliningrad b/src/cctz/testdata/zoneinfo/Europe/Kaliningrad deleted file mode 100644 index 0ec475647055bd235131c6620aa46da7f43209ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 904 zcma*jT}V@57zgm@w5{f_C5byur!8&H+^n^^TBWr*9xbcLVy}mCaPYfu?lh^CuRF?y0IxIOm&(HJzOm70uo4z#M%6aDC<9YE;ROGxj#afEr z1zFjc<@Y7|$ExRS@q!uWtyv|=xg>o9x%AoHMb5Sd*I-$)3zlC#3)ghUp#9VVxb{dB ztO##`mG#wdo!bf>HY?wbs`5?HY4FFnael3W)gNWJe%1(UUVMkHkp<`;%);86X}BRV z4mX}lK~Jn7ZaVskxV#-h(AO{w>-JxS{<5oZv-f1qU+pkZ+8yU6@IH#X_2+TqZR39A z?b#OO`k{TWVayG8bo=1WJ~Irq6~SEz7jf-YzacBJmB@{bIb>D&g4|>nLvF6jAUA)0 z1NZ74<(zm5TR!x{P$~(->4$M{B3CXTYhl-!Wzye6uhTC#{4;c7@qfn(JyBtRZ*H?o zqBj>%9#M@)5+7o-(`xarf|7+-s07FIa6}_Tjq*Vwl^azwk!YisA#!g z&JG~H)S1a(zVx02A3%JWH50+K?3^YrE!R^FrsZo=z_db6D414^aRbvzKIULr*+v6Q ztLR9AX;m36Fs;V@8$$OgJOG)m@l?D4L~CB<0MlAWeu8Q3Ew8||&XU_;T6fABFs;|J z7fkDytOL^qDf7X!VeDxJ5HOq;7{JKH%*w*b!pw#V*_q&w9q73^AT2yp`P(c#H|PHHzu!G~_`JUEE&~f$0>42`z-%G!4&%({7PrJQ~C zf}FE=2Xg~gFmLu4>PB~9e*X&8cTB^Amct;;8~Wy;v1}O@)(=9HdKeZNn*RK1gXY8m zKh2r%9mvI>KID?4OytsA3$kV14$BUbVEMQPS{E6#bw$96QB{!MtE_rLwzq#HJ2V%_ zRrUwuYHpPw#uCdXc?ub*mr=`?sW`RFu#b zdWDOO>E`LlY(0}QR$V8^`0uc>NZN%coJZp%+U@bO9KDgZiFYCMG&p#>n4E8UM)@zw C4T--1 diff --git a/src/cctz/testdata/zoneinfo/Europe/Kyiv b/src/cctz/testdata/zoneinfo/Europe/Kyiv deleted file mode 100644 index 753a6c86f38586797589233f4528837f5b09151c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 558 zcmWHE%1kq2AP5+NDnJ+nLI`V72P)$LVx|8;5Vq}j3W#1Mxg1PyT_TwP;-5OJcL7A7 zdG0L$qR*}rp8%rIEpi6)&z)US0J2Y1efb3tEhcft0Yr;)+ztTKzxWS;Xo**RV0p>g z&JG~H)S1a(zVx02A3%JWH50+K?3^YrE!R^FrsZo=z_db6D414^aRbvzKIULr*+v6Q ztLR9AX;m36Fs;V@8$$OgJOG)m@l?D4L~CB<0MlAWeu8Q3Ew8||&XU_;T6fABFs;|J z7fkDytOL^qDf7X!VeDxJ5HOq;7{JKH%*w*b!pw#V*_q&w9q73^AT2kI6G#R8}8#GCSkxFI6)HF>awim{rG!4pH zjAkS6&?xfAD}+?!6(J%k38{3?_x{s=+&gDK=lA=bb9VRctnlb5e@kk~i$$*>gIvO; zx5UuPR?>sJNMFZybM%Pu!!cpRB*(Ks@NX^Z_8FKTWPpA_ z@GV$)SRNKzI>8dvI>yCPSUM?%Wp%|e@;RTEJc2J$ywNYeABnmmQ3hXL3WSvbUa-pJ z5Uk$A4kG(&b_h_v+IbJwdSszr+t~-}<=Pmhc(7r>M@IHF7P&Hxr}dNib(kY#H}gE2 z60DIoRXLs@d2_G?d2>xU&S?qNMBb8h68$%>BF2nVo_vv*oYN}_g?;h< zus_@#ehNMa2YhVdpsNY|ypIcqEIDvk{|_AD8uQ3`UzBth7nI=W*l#%2H37di^uqCH zEpS3w0ly{Y!O2JolwH09r%sFDci$W_Ie*$s41d_g!5OP?_>+GD&T9CLTun_KO?9v)Pfq$`_)Lk#_AX9wfvqiQfq27 z!*z1yjMKSLYcLgRx5q=BstCv}%c01nnSJXeMfe<{@QJ z;Fk?8ygJpW6|Cjoa`f8&$8vYdFSSsfjhnT&IO|Kksfrp)o=7RsPnE|~CLKy0b4@2_ nA?0rGMqbFED?55(M>>jhOF%MHXDhR9W&(2yQ)deSnJNAQHdoT( diff --git a/src/cctz/testdata/zoneinfo/Europe/Ljubljana b/src/cctz/testdata/zoneinfo/Europe/Ljubljana deleted file mode 100644 index fdb9e86d4a9a51ee4f1ef24b61e2ca58c5f21738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 478 zcmWHE%1kq2AP5+NDnJ+nLI`V70V-n#V&4Bi5NGrC35Y($WcmO^pLy;r0HV*X6rTX1 z&n%p|-hMG`Exl*207zbD%{nkG zJ7+$amg|`SrsZoI!L&k75tvqtNe0tOJ|SRQ*~S%2tLT`4X;m3@Fs;TT0jAYiohN|I zSO01PrZt|bf@#gGVqjY9C_9+e-tq%X>nwQ*rgf*>0@Hder@^#-$sRCmkg^s`8^+!g zU}Pc;fx$QjWIvw(0}IfX3XB{+z99_Gt{@y7!oUS&=^BEVI=;qwrg{cCzJ>-MTHlxp E00cm4j{pDw diff --git a/src/cctz/testdata/zoneinfo/Europe/London b/src/cctz/testdata/zoneinfo/Europe/London deleted file mode 100644 index b9e95d92623c6cc4c35b16f7ceba3006f5ce4934..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1599 zcmb8uc}SCC0LSrnPAl(aIc=KGEM>Ols~w0Dk_2U`XboCMsYHe-F-0ts2>*ysB4!wN zXug`Im0Dh9YNcu3<~b3|vqR^RM_Kb)z0dEZzr$yY&-;CjcjIM~2Ze{ZQ~w=2b_aQr zA^-o840f9V`(FQt9imf)&BS|7`3&qa5EIkdXmomZ4ZNS04l`0kkhxkeCi^mDm(f{g z)6fs%8_?PQW$>Zb66POm3xPS#buiaO$~mEB$bFtrU7Tu5%sbIe`rF&3=&E}*u=-*ue0OOD)+pj&ZD2M-_P_TyiLUdkhV_ab z%-8oB!X}}UitKAjJpr3L>|o172EN_ET#fuF2Uf=H)qNfwip=UBKqh~{X&~sOU(LWA{!JonV;k<(> z)_-|9qJLA|IiL~pcizbSYNCvMlX$V&uuyWDSD;8LP`FYd}W=Os4r1KgMeJP z#?TY4rIR={w$M-z$=RTTMl=4@aDk(Wc4EXtU=QX!EE6wBU{mt`Dq&7I6Z& z!7U4JRLnt3#|ah14xvXKwBolyYwKLj&(Gi{Z4wmKBtx6w9056Jn^yogS0_Td>ndoU z83DzS(a<5m4{q_5L&s28xK+9bZaaKLMegThVvTlo*@1SR-vuQ`=A3FFbkWSh?Il_$ zZR~6l` diff --git a/src/cctz/testdata/zoneinfo/Europe/Luxembourg b/src/cctz/testdata/zoneinfo/Europe/Luxembourg deleted file mode 100644 index 682bcbf61ac74f99905a5ea01072d5868a5a0189..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1087 zcma*lZAep57zgmXbPXl-rZ$%@TdlRSxfi!dM4+_xA#^1)Q0xW45lK;FNK`~53{v#N zH3BQG-PUZ)oLXsVP0O6kD0}k-8-0*Oq=K>{h`!i;{_FcXhkJha|D5NX50`7NtT|M` z#2q4`gB}|8_(vQJEnTtvnHOKyrnp9QbN-k{t`j zuz!2Ti`*G0Lk>Roqrb~vfZWaR!G6#AOyoNaN3eg_sXs^e+;i1qzqd@wQ|{YUsUYv` zS>y)=Ct!ctkC;nyaNye{d^p{xp#DcQ-(hI%BOL6XfJ2@Jp7tMK>O+3gngfSVw!o){ z>)}YnDHtx&@zg)MbszGxZNo59F^zg8ngqvo=uv;UP{LCGcp!@-UwJLauP>P3o8vw3 ztxF2u?Jnl1Z=$&vd9p;w(SMQRtA?qK*(~KWw-uSKErcr_YM5@9!3^6@mijV{e~?!x zzd&im2bh&G9`olAl+AU+)e}6-9%+U-p+T1Jk#}~%HEkZ4+r+`OXX>Ehs0*&!Uk%rn z+M#m06>iWJLX}(%H?ELDwb;VZ{pw#PxM^MmH&01n-lzm_>HQ5gzE3d!ViaoKFQBeA z1oe&}G#q%(E)!uUCj9?gE*9p$bFtHLR)!IW@qHAcM21OanIu|8DO6+9Q4veR#-uL_dj^m`pt5>SH zeGi^Z&_#!|{}vY;JHRe6!H(P3mmE1T6W%5VWgA-di|C=wHXl77Reblr&)2X%zBq#Q ziIFOFKz3pM+1(uU^PU^4;Et)^}Ie`%^n4DR-O$nJ)ZAy_XhGJb0lNY9a^{2MN0o(Xfl4 zixcG{I_0#w2sA-gqNo?@An+yK+)(L46p8Snfs~4-o!{3#z^k6aIUl~i@ADkSf$=ph z&DYtvOCj%|n-+imk!pFHQoc2(@)D*3P2}s+0|5pXHc81hA12?7v3m0DlN0oP9s_z$ z{Ri~@okQpc>TaTc=hP#AZ7o5+@S~EW^NSyKBDpkRNB$;mAur#*3s>5-nERdnFzpMJ zSutO&@M9iK+ZSja%6o}EwA+P#P31;^X#0%$;rbkY-;u#D(Eg)wFXqR`UgW>8+{h<8 z%kcEks6gM1`9{KoqOlh_LaKqv@`o_;aXb2`g6A+=Z^JxBoeeMOv}bMu0n-4n=M!zgk>yM&y0yB9ghQOhxTCFhS2>{8Y)dTr8o zs8cSUxi<|{wuj;6fCuVlpTX40DUQw?20y_xsSl<<6=6n4H_U8pgIDVA!K+RlX5DhY zY|{;xV=%(p*c51tvWxV7z#EjLh(N?`Hvvsi)1Py8H?kX%IV^n-BCpko~h+Wp_QV^WiywUEhd-MLKfN7{{Zl9 BGR6P^ diff --git a/src/cctz/testdata/zoneinfo/Europe/Mariehamn b/src/cctz/testdata/zoneinfo/Europe/Mariehamn deleted file mode 100644 index ff5e56530570974516d249927952c69da601b664..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 481 zcmWHE%1kq2AP5+NDnJ+nLI`V71}b9#V!{7F5WGumHi%wQoG%TcPoE1+0MTa-JWT+q zVGvcm+W?})gwKI#apwIH`tt@bE%A8$1fVp7S)C_<%vb+v z0;V;ds)A|Ft72eU>nJ;z*52|1OzSLp38re#ss%ZIH4SOdH1D6kud# zA_N&2#8W}m14&>|Y8fzc0KKZf!0Y21!r%eKuCBo#B7}hpNaz}YxH`VZdZu~?`o=oG Kh6Z4k2^RpC0aq3P diff --git a/src/cctz/testdata/zoneinfo/Europe/Minsk b/src/cctz/testdata/zoneinfo/Europe/Minsk deleted file mode 100644 index 30d3a672bf64d0d787ac92bc75d9bc1cc62855c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 808 zcmWHE%1kq2AP5+NDnJ+nLI`Vd0V?AJVzvK35Vq}<28doIxyk}WZ(Smp0HROD6F zyy64POWt;N0P&^HOa}9%_bm7T;>)a=2&QG{G=XWko?>tsv|@}Km{#&J z2h++n8em#QM-oh{%5Z^c^{)~IAagaIiZ_60&8r+>TI#MKA1L)JzB diff --git a/src/cctz/testdata/zoneinfo/Europe/Monaco b/src/cctz/testdata/zoneinfo/Europe/Monaco deleted file mode 100644 index f30dfc7014f46670a12fab61dbd74d3b0349afbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1114 zcmb8tYe-XJ9LMo9-CXI^Gp)ItrMc$H<}PlNilAbRiZ&fIXjG=4NRq@Dz8F!EAk?ZC zTS!D&TQ={TcCpl)W|@~XyHb|)B8rkIY7s&7B0K+|y|>QcIUm0N^X!3*+4oddqwtFp@^*C=8nQ?m6L3U_~3=1?U-Nm{6_l&x#&P? z6TEax1RK>U@bX~`3>s@-(|);=&TCc}(Jjh)*y_l^yiIr%-S)+RZl5hdcTC%0Xlx4% z-*17PEppfuD00%dSB?wNS3L*eHD@;F*Ig%Iw~Y^P?9kx-P0a^%Pre2ACXdfM*9ZH) zw!>R5N~3gs|I1Mr8SjAuy{&N2U*e?qx6hqK51o&~JMJoY_dqcmb`-*Un*>hUKeA4X z9^G&jjyXb@kIgI&(EEwBy_iqDwZEaB3|FEb%m|~a0RO?oj_ASx>LNAqn zf|AtNFfDd!-tU7@`mPHudlrD{!#*gB46t-gMyL}mZ}7tvr@b)qNDa)Ya>14R%3!v| z4&@uoaFwb6Dl(KXMh}t`=D7ssjtJq}?w?Q<{0Q^vW}v!u5^Aa= zP+J~`y5d(XFE-|XZ+^_*J5KPgH^anzrf(3VWB3e{#PSwVF^Sx7mcagVF@uYTw)B#{Vp^Ff_g^s%Jj%UfhmShojppzDoJYKKzu?b64|_9x5IOUqcb4-l z3Z!6gRAIBLPUc|9Kf&HHpC}sAp+DwO6Wo88wRVcL$?O?>$F8x=C~UbgpMdi#bFAg- z3cR=G!wToM(^ruzrZNT2w!4GSe*FS;Tsi~So$rE`z58L+;V4`m+XkJ%YPg}+3SBl6 zbeAnakL*eE{+=HeSpB6u#d%}jv!d_k(f7Xi25Tl~U~Tpdth@FUZc0CZo6lyTuWJz2 zADJrfe*V)#upu-8x9sbOjrJ7W>OWNU_c7R1(U;_PO&=r3frSp_?N8juJMux~;Aj|z z9y?(3fD5(^6I8lO;m)+J!29h|XOY9l{~$+PuaVX8C*-Jn54qL(9JzJw72K`M7JWMo z_k13JZTBz3*!1lr?;pQ%3R#QUJ0)F-PG6#z4RWb$FdBr5u4VskFP>;J5IF;Ug1GC6 z>Mu%0@qCV-TZW|N;!7#gY9g?>D4-@p|eETzUGxTV7}Io^I*RAmUCdf&XSE_zV4I_V7^|| eh!6%YAfamn;_CPs>zV2q=o{Mk!L!FMhUW0LTA-e9xREawUGQ?o1h4!m7#Wnoct9`E z`R6S!^2>5NOw3u~>x2#_M;Z9mBY~;T6im0o;5!?I8FdJLFiC;#{j}vHegtbvG(lACkd_{V!NB=F8Bl+(kM6SfI^^#mdiWySi<#^)ubkoKYx!5cY8qJ*3+GMqxIftEU HbIN}KI)2g> diff --git a/src/cctz/testdata/zoneinfo/Europe/Paris b/src/cctz/testdata/zoneinfo/Europe/Paris deleted file mode 100644 index 00a27264c2cb3e28f2f46e5c267e12d575236a9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1105 zcmb8t?@Lor7zgmXxw*2bSIxQ9(p>YF&HYd(6+y)s6>Vq;E%U6wc@bvN7a^mq&J@ex>0La+5y~ z*cecGL!2%yqE!fJUJEu4~Q6ZJZCbm*%1#P#i}Nd@Vxmm@7x_oN>Zn zcpL1RXoKBt8rb7^2z2j_lXB#n4b||Lkc0Yd_bJ%xl)*c@4CvoAd_wLku)+Ss$b$0& zaNt`9y!WaiO7{=G9*3bw9~|m$hr>1-JdHeZDGDFdy5PgZWpK2#1U}j#7wG)h z1|#zLrVB7!8bm!jyVOtph>LqiKAGFil9Pcn5Bap&f;@Gu2u?fRw$UJX<1+gUodyzn=2s^$w+ zrM!h{F_R1a7>4Q(J#fVfKTIF>!i>-mOZQ|3yWz^lCb;UX2WB0sgV`=OT)n>%=Gb_s z*=&Vtbj47c$-!Ku8gg=rhwkTo7QwY2wQ$`_70eq`!1cYqpswXJ%s)R1_4SXTp(X^4 zRb9|j_J)%p|-hMG`Exl*207zbD%{nkG zJ7+$amg|`SrsZoI!L&k75tvqtNe0tOJ|SRQ*~S%2tLT`4X;m3@Fs;TT0jAYiohN|I zSO01PrZt|bf@#gGVqjY9C_9+e-tq%X>nwQ*rgf*>0@Hder@^#-$sRCmkg^s`8^+!g zU}Pc;85o2uK=$(qFt7l9sldqL;~T=@>n6S>(K|QN>!DsS}id!m568)i8~32&`2Z(8iT=r7z~E%5eAQn zSR@`x4U)2mMB@D@+So*-EE183h4cNpNEhekJHPw??l~v-NbP;SRouUWXDg^^NdIrC zXUh^vG^rc0hb!QuD z)uBa2nWjf#V>42rrMraPI zVA)X;EcbswaXkVn=EBf2aRMuc0?_K&g0{|(z{khMJP9#5_WPgAaf(U$F*YZ#>+AVs tj!PFf1@-t0ms{dmSvecqXp*=l7E;+ug^gOG+it10SVgzZN>jRu%j(UAnxsxp!w;~3O zq5f43Olv$92h*BYIl#2mk)L2%d&?^@t+V7dnAV+g22AU<>;=>MCF{VnLCSnEZ5Vr+ z0R)VE_kd|*+uZ^nhDp#gFl{P37fhQORY2&!^ z(I5viHpmPN;zb|>fFuh8gUTjG4q)IZFz_%iXc;g7t>6=25CMrWN-!{3I55hB#2FQR zd_x$5fY>KEgu&G{guyr1o52}KJG%k}e1lzpfW+Ipe1G3_#$hnA`C5Ag z+xJn(JLsiH-2aF}-j*!CnS1h6SG*~ZlCM`HN6&2~49~AocKHKQ^6?wiNEf9}#EhlEg+ z_AS<#G5^vK!aSV+N22*s$wTx@k=y9M9vnfxZF!CP_VNeZZ-);_w14NV7xP%miyVJ6 zg1o!20QdT4B>MfBe>zGit~@|aay3Kcg&vrE=LY(e(qVX@a~Si~^y|oJw(|)i4yZCZ z(5nJ9$ZAauvifBna>n;Hs2PaEL%}$Du3HB)J*)6=Qw(O=>p8mL5zAjEnOzux+N>3r zqYNhe^$zB)Pr;*$Zm4@d1oM2e9G&N1O~QQF7(6!UgvW38!h()2c%tPhJSm8O63_E>aNin6`Sa;oC9>%(-CZnUimS&0h{l}V9VYFbYE`a{X7f95f&Bw>ywzo z6o0pWUlUzoQADN};xWi1@fUDXEKy@CixX?c*9MtMZjYA=W+Ipe1G3_#$hnA`C5Ag z+xJn(JLsiH-2aF}-j*!CnS1h6SG*~ZlCM`HN6&2~49~AocKHKQ^6?wiNEf9}#EhlEg+ z_AS<#G5^vK!aSV+N22*s$wTx@k=y9M9vnfxZF!CP_VNeZZ-);_w14NV7xP%miyVJ6 zg1o!20QdT4B>MfBe>zGit~@|aay3Kcg&vrE=LY(e(qVX@a~Si~^y|oJw(|)i4yZCZ z(5nJ9$ZAauvifBna>n;Hs2PaEL%}$Du3HB)J*)6=Qw(O=>p8mL5zAjEnOzux+N>3r zqYNhe^$zB)Pr;*$Zm4@d1oM2e9G&N1O~QQF7(6!UgvW38!h()2c%tPhJSm81Rdme2w5p6cm{#MF0MqKM&J#f9 ztA8~C(;81z!L;U8F)*!llpRcKZ}|bHb(XvY)4Ee`foZ*#(_mV^WDl4&NLdS}4P$Q# zFftK_3=D!UAp7|Q7+8S5RAA)r@eN^cb_LKsBJAWgN;!E+ySR{-=l9*oX}_o6^XdD%9sd2D9RqGX3tIv|K~3chf5pO&NqEQo z^4esj6XdZsriHJuc+JW=nIQA)$i(Pd3;YxgN!bfKC*=Vn_LFX=krlqhM_O0zPD0h% z2uz;shbiN2Fm=!l)4EJB-H`(`%-KQ4D>F|H)k-PMiur;XiN-_wnhzPwxqEX_&b@p^ z)*ju%Jnt>cUpj*YQwOkcWCQB@7GP1gFG%$)IB3xdw-B?)z`>% z)<CmH>7_DHayM1#{D_yxY_d1`%Uvh$WDjKMY-MD>=DF>epILGY(F#U`F0Em`& z#Rry`yzT4&;!B;G4CYJkS?~eGmsv9rOv}z`0@HFm#b8>#CIw6@j}4 zrj>0pz_f~vB$!r};R4fYy?S6;^D0LJ$b79MKf$#2mRDd}XUT0atvlrmgg$ia0s|1} zwX81y(fTC|z_dZiL@;d_y8tY2RJ05v&0uW1TL46x1Wg0erm}Ovw3$%_g#KF(rY)qW zOaQ5~xSI&(TmCKs^R4zegZb9CBfxx{W$|FzcDEInwrg_))AqAvz_de}GMIL3u@nHA z=j6r;<~yfIgZVD1&%u0G=f7aS8|z6h-(C4WnD74X8JPBDJ_w=DodDBbj~9b!?{%xd zw9lFS6F}zs_Vs}Ierpzj`Tlu%V17VPGngM3-UX(Ea#F!`uz6eqNMDGLYyu+_Gb;-a zGP7YoCUy{nh=Z9B0URU;GXsPC50J6)4;Wa0i9~^c0~nPC3_J`Bd;$zW2gxWfiU0%G vfl(49&L|6FGw}HMhA;#Jv8!tcgKw}mgENqJb`1t`T!4Z=1{Y9R*O&_c^%u8U diff --git a/src/cctz/testdata/zoneinfo/Europe/Skopje b/src/cctz/testdata/zoneinfo/Europe/Skopje deleted file mode 100644 index 036361cfbaf439b133fffd4323561291de936663..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 478 zcmWHE%1kq2AP5+NDnJ+nLI`V70V-n#V&4Bi5NGo~14N%1Rdme2w5p6cm{#MF0MqKM&J#f9 ztA8~C(;81z!L;U8F)*!llpRcKZ}|bHb(XvY)4Ee`foZ*#(_mV^WDl4&NLdS}4P$Q# zFftK_3=AR?Ap7|Q7+8S5RAA)r@eN^cb_LeE~#^m?}O1(V{wU!F(~{ z0|g+yIL~=7U;Oii1`uE3@j@^yd3h3;mO9)Frlt3+2g))q$gEiare)_$1k-XoO<-ES zrWi~sohdrj>2X!L*8w2AEcrkp$CfJX~N}oz=7f#8Cgrl>nkOp1chJ z(VAD@B!FnGBj>?zV2q=o{%g?^ocUl{u4e+6mal09(+W97U|KOI8B8nrgn(&f8&@!`qGJZ8Rb|w{v>J~Dm{w)_AH4rZumMfoZLy>|k1Z%MUQEv*ab1)}3+-OzX9r2GjZ_d%(0o%33gO z7<*HIk%^fwWMB|@19AYL94K)41QgGv@$n5|2zCu&a0cVx5C$$FOV`lZH8@1a T*I3U~&p^l5&;Ug18*>2w?Gsu1 diff --git a/src/cctz/testdata/zoneinfo/Europe/Tallinn b/src/cctz/testdata/zoneinfo/Europe/Tallinn deleted file mode 100644 index fbebdc6255b547b1f3a547f0f92cc8148f05f186..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 675 zcmWHE%1kq2AP5+NDnJ+nLI`Uy0V?AFVx|8;5Vq~i84x`$QWrw+oG<~zpWiYaOfO{6 zE&%bD6zBVZ=o1^ZJ^<0Dj!h2$(Py4}3xMdeE5*U;&nnR4)@--=7S|KMCOe@B?foUZlb1bR@yFs*EJaI0iKyE-nynqrgf*B0n>Udd%?7R$vQA?kTM@k8^)ey00E<- zWnkLab}g7T3F-jTrn3ED+RUgz0K_o+TMwo!q^C>(@oh?E5*V48m>F4EnSc}%D;pYQ zXTb(pfFTQtUl0jo%P24cW13HZffvMP5M*G`GGGv8V6bpt1O|ha0i&#sZwNyO5IegD rgNP6YS0MHc_6A}XAR8#i1r*UW0x@-bjrC0R4D^k4d<_l2EE6sO`iG<- diff --git a/src/cctz/testdata/zoneinfo/Europe/Tirane b/src/cctz/testdata/zoneinfo/Europe/Tirane deleted file mode 100644 index 743a7337ffd8c404d1da0d2d078ea1cd8459affe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 604 zcmWHE%1kq2AP5+NDnJ+nLI`UCnaB*py#Ik<+A5O_5Pc%Iy#Pd?dG0L$qR*}rp8%$J zyqo|smqWwy1DJkqmjI% zOWux80P&^HtOv_W@7XH=;>)aA2c~7`%m>qQJrlsRd`%;mR>&y=(~2?4U|Pv11WYU2 zxPoaF9WyYkDx(gj)p#Vpv^uNv1d#daUroTY##2==t$9@pOluuw2h-YHet>D6C6Msb zopKAz*K0Wqru9qqfN6u2wP4yX_ND+M6RD7aL1+fZHGBdLEI>aiFmm|#hA=q0f^cvM b0~e5`YY1ZM_!{e(>KW+x8XACTePb>FP|$Lw diff --git a/src/cctz/testdata/zoneinfo/Europe/Tiraspol b/src/cctz/testdata/zoneinfo/Europe/Tiraspol deleted file mode 100644 index a60bddd7b2c96628f11598f143918915c98052cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1207 zcmajdYe=5u1 zG-;$S|411>wwh1Be|%(i5C0;s9K7mC-tBlLBJaoiFvFQ<*z@5G?6p+V8)2 z2|l=W8a}*O2?y#9!ABMO@Nr2Be3Gq!gS*4vQ?(R63)ldMT!e7A&uXUke}25mNRE6? zawcE2N*c(~Yg)9eF&vI1H<KZkZvg@7b;HD0ANR1U8daMyGFDgfe<+V@o<4ken z#2BfJzD=<3v^uErJO{Ta4lMZhFjTwOT49o+oaJCwq+-60ml$p`S`f_w?RwYa;&4Q+ge3-6}gc%YI%#^t=I46bKVl|_Y z{aR=t_s+TzET{XEh1@s(hhVuab}+B&JIERa`d0}st?^X60mRp= z*bkwv`~r(>9eE9=wYS^>(>hDef@$3;`@pnb%X%=aU$Ov98>CDG(}uBoK7hu)cS$4W6TmY;~jWYlM diff --git a/src/cctz/testdata/zoneinfo/Europe/Uzhgorod b/src/cctz/testdata/zoneinfo/Europe/Uzhgorod deleted file mode 100644 index 753a6c86f38586797589233f4528837f5b09151c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 558 zcmWHE%1kq2AP5+NDnJ+nLI`V72P)$LVx|8;5Vq}j3W#1Mxg1PyT_TwP;-5OJcL7A7 zdG0L$qR*}rp8%rIEpi6)&z)US0J2Y1efb3tEhcft0Yr;)+ztTKzxWS;Xo**RV0p>g z&JG~H)S1a(zVx02A3%JWH50+K?3^YrE!R^FrsZo=z_db6D414^aRbvzKIULr*+v6Q ztLR9AX;m36Fs;V@8$$OgJOG)m@l?D4L~CB<0MlAWeu8Q3Ew8||&XU_;T6fABFs;|J z7fkDytOL^qDf7X!VeDxJ5HOq;7{JKH%*w*b!pw#V*_q&w9q73^AT2p2YyB9~FY>)8Bo-^qE7! zAY&Osm0wQ)(PF}Pz_d8?SqS}kADEVSydF$TUS0sEr4CO7)6#qP3V`&HkkB;*admu+^-T2)bbJjBK(xLw7XYW+Ipe1G3_#$hnA`C5Ag z+xJn(JLsiH-2aF}-j*!CnS1h6SG*~ZlCM`HN6&2~49~AocKHKQ^6?wiNEf9}#EhlEg+ z_AS<#G5^vK!aSV+N22*s$wTx@k=y9M9vnfxZF!CP_VNeZZ-);_w14NV7xP%miyVJ6 zg1o!20QdT4B>MfBe>zGit~@|aay3Kcg&vrE=LY(e(qVX@a~Si~^y|oJw(|)i4yZCZ z(5nJ9$ZAauvifBna>n;Hs2PaEL%}$Du3HB)J*)6=Qw(O=>p8mL5zAjEnOzux+N>3r zqYNhe^$zB)Pr;*$Zm4@d1oM2e9G&N1O~QQF7(6!UgvW38!h()2c%tPhJSm8pBqoZg5T$0QpncSN#Ks7BRk% z0HQ^eUrzwhV#0U8v^euw2>p2R(O3 zw8m3aFs*r23`}bsWe3yRTYi9Poh2{9wC;e*#o8xQr3cL!`PbwOpN3~ z1_u5>u%8teSr{1j1Qk diff --git a/src/cctz/testdata/zoneinfo/Europe/Vilnius b/src/cctz/testdata/zoneinfo/Europe/Vilnius deleted file mode 100644 index 43c3d7f1089366e1c48297906c2693712ac6d99c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 676 zcmWHE%1kq2AP5+NDnJ+nLI`Uy1}ftOVzvK35Vq}%3y7ZMFCPG+7q)uM0MUy+8hilJ zi_>iMI;SCHxwpa!O2Ll7200R#&02LU37HAnTh=ACP5)2F$4vexO5k^HH-w=jy yAod1gXV(x0S0MHc_6D+pK@1n50Fc226xKBYF?D>6^-T2)^o@0V4Gq976D|N{`JSl& diff --git a/src/cctz/testdata/zoneinfo/Europe/Volgograd b/src/cctz/testdata/zoneinfo/Europe/Volgograd deleted file mode 100644 index 0715d58bc1873c8bae589a08752cbbae562692c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 753 zcmWHE%1kq2AP5+NDnJ+nLI`Vd1S(?(Vu}Aiu<)zf9T2^B33mWUzo`1m10Y&V;+z49 z7UwwY0H%L2ZUE5|uNV%1Xvy2AV0o!Ctzf?No=Fct;xcQR!L;n05-=^-lM1HgYr?>^ zLXJC_R*bO#(@H*?U|QKm;{yW_sOU(7X;m36Fs;V@8%(RSsuzId)xS!BY0WEd5;W|9n#dBNHYrAt;OA#L^iTEMk$>@(!jN|a=ce0z*QtNz?kLXBUfw}I zS7nf?9Ob6pN5)<; zimVsCFuU^s%(>qRk2c?cx!2q$=wdk|XdB7!15jxJ?_a(A)+nK8`}y)B;; z_&3Q_9OQpQU`dRbEQ%DWFm1I{V(0m=J8Ec>n1dD$zEJV3*h+QLX)~WPTSTYTLYCN6 F{{iE`PO1O^ diff --git a/src/cctz/testdata/zoneinfo/Europe/Zagreb b/src/cctz/testdata/zoneinfo/Europe/Zagreb deleted file mode 100644 index 8e13ede8d4a6424bb62b30044ac8a20935c19f61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 478 zcmWHE%1kq2AP5+NDnJ+nLI`V70V-n#V&4Bi5NGqH14N%1Rdme2w5p6cm{#MF0MqKM&J#f9 ztA8~C(;81z!L;U8F)*!llpRcKZ}|bHb(XvY)4Ee`foZ*#(_mV^WDl4&NLdS}4P$Q# zFftK_3=DifK=$(qFt7l9sldqL;~T=@>g z&JG~H)S1a(zVx02A3%JWH50+K?3^YrE!R^FrsZo=z_db6D414^aRbvzKIULr*+v6Q ztLR9AX;m36Fs;V@8$$OgJOG)m@l?D4L~CB<0MlAWeu8Q3Ew8||&XU_;T6fABFs;|J z7fkDytOL^qDf7X!VeDxJ5HOq;7{JKH%*w*b!pw#V*_q&w9q73^AT2@EtHM&U_X^f8GbCB_6K_(~_4LfN8126T!6fp1lGfeKKp- zfoa(}^TD)S&jc_nU(*Pt6>^Hev|>y$m{#%$0n^Ghu3%b4#|%uX%BX{BH695ttOls~w0Dk_2U`XboCMsYHe-F-0ts2>*ysB4!wN zXug`Im0Dh9YNcu3<~b3|vqR^RM_Kb)z0dEZzr$yY&-;CjcjIM~2Ze{ZQ~w=2b_aQr zA^-o840f9V`(FQt9imf)&BS|7`3&qa5EIkdXmomZ4ZNS04l`0kkhxkeCi^mDm(f{g z)6fs%8_?PQW$>Zb66POm3xPS#buiaO$~mEB$bFtrU7Tu5%sbIe`rF&3=&E}*u=-*ue0OOD)+pj&ZD2M-_P_TyiLUdkhV_ab z%-8oB!X}}UitKAjJpr3L>|o172EN_ET#fuF2Uf=H)qNfwip=UBKqh~{X&~sOU(LWA{!JonV;k<(> z)_-|9qJLA|IiL~pcizbSYNCvMlX$V&uuyWDSD;8LP`FYd}W=Os4r1KgMeJP z#?TY4rIR={w$M-z$=RTTMl=4@aDk(Wc4EXtU=QX!EE6wBU{mt`Dq&7I6Z& z!7U4JRLnt3#|ah14xvXKwBolyYwKLj&(Gi{Z4wmKBtx6w9056Jn^yogS0_Td>ndoU z83DzS(a<5m4{q_5L&s28xK+9bZaaKLMegThVvTlo*@1SR-vuQ`=A3FFbkWSh?Il_$ zZR~6l` diff --git a/src/cctz/testdata/zoneinfo/GB-Eire b/src/cctz/testdata/zoneinfo/GB-Eire deleted file mode 100644 index b9e95d92623c6cc4c35b16f7ceba3006f5ce4934..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1599 zcmb8uc}SCC0LSrnPAl(aIc=KGEM>Ols~w0Dk_2U`XboCMsYHe-F-0ts2>*ysB4!wN zXug`Im0Dh9YNcu3<~b3|vqR^RM_Kb)z0dEZzr$yY&-;CjcjIM~2Ze{ZQ~w=2b_aQr zA^-o840f9V`(FQt9imf)&BS|7`3&qa5EIkdXmomZ4ZNS04l`0kkhxkeCi^mDm(f{g z)6fs%8_?PQW$>Zb66POm3xPS#buiaO$~mEB$bFtrU7Tu5%sbIe`rF&3=&E}*u=-*ue0OOD)+pj&ZD2M-_P_TyiLUdkhV_ab z%-8oB!X}}UitKAjJpr3L>|o172EN_ET#fuF2Uf=H)qNfwip=UBKqh~{X&~sOU(LWA{!JonV;k<(> z)_-|9qJLA|IiL~pcizbSYNCvMlX$V&uuyWDSD;8LP`FYd}W=Os4r1KgMeJP z#?TY4rIR={w$M-z$=RTTMl=4@aDk(Wc4EXtU=QX!EE6wBU{mt`Dq&7I6Z& z!7U4JRLnt3#|ah14xvXKwBolyYwKLj&(Gi{Z4wmKBtx6w9056Jn^yogS0_Td>ndoU z83DzS(a<5m4{q_5L&s28xK+9bZaaKLMegThVvTlo*@1SR-vuQ`=A3FFbkWSh?Il_$ zZR~6l` diff --git a/src/cctz/testdata/zoneinfo/GMT b/src/cctz/testdata/zoneinfo/GMT deleted file mode 100644 index 157573b1d340e0f57a0dd4d9698bd3798cbf7136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? diff --git a/src/cctz/testdata/zoneinfo/GMT+0 b/src/cctz/testdata/zoneinfo/GMT+0 deleted file mode 100644 index 157573b1d340e0f57a0dd4d9698bd3798cbf7136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? diff --git a/src/cctz/testdata/zoneinfo/GMT-0 b/src/cctz/testdata/zoneinfo/GMT-0 deleted file mode 100644 index 157573b1d340e0f57a0dd4d9698bd3798cbf7136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? diff --git a/src/cctz/testdata/zoneinfo/GMT0 b/src/cctz/testdata/zoneinfo/GMT0 deleted file mode 100644 index 157573b1d340e0f57a0dd4d9698bd3798cbf7136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? diff --git a/src/cctz/testdata/zoneinfo/Greenwich b/src/cctz/testdata/zoneinfo/Greenwich deleted file mode 100644 index 157573b1d340e0f57a0dd4d9698bd3798cbf7136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0@2~_8^XW^Bn-F!Cr|}? diff --git a/src/cctz/testdata/zoneinfo/HST b/src/cctz/testdata/zoneinfo/HST deleted file mode 100644 index 40e3d492e6c22c30041c31f159d4fe0ee9451c03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 221 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I&Vv+wqQ1YN)ABf(~>g)lg6$>Lk^yyC96CnDM z@|OZIo#<%+qObNAdoVIFGP5wU{{NrD#J~U~BN$lz|F6nm;TbMoi>Qv;@<)_(UM|O=&QF`|UR{ zeP_pCFn#yz4KRIgk(33UG30Oo&oxL^TN_a#FJ%>Sye3C#cI{sqkcu387?{}4?C z^MA4?fcZbaI)nMYo;rc~zwgDb0GadWT-**2{db=unE!8`1DOARp7IJ%yfXAD?Eq1X zb*x}MQyvSL&m8+4%xCd^2IjN6vuJ?Sv6(YlfM|BLXJ9^ivn`m<$#w$F=lpgY%;$Qx z3e4xewi3+eIo1Q_3(mF#^M&$rRxmO#voJDI2pJf%xj+soXkcJrV5pnG$icu+-oeNV dVlxQ&_=Yfec!O{-hzJj1@B%WpfI_+!TmUPfblU&` diff --git a/src/cctz/testdata/zoneinfo/Iceland b/src/cctz/testdata/zoneinfo/Iceland deleted file mode 100644 index 2451aca76d7c555b06d358c2e30799c9b599fd1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 753 zcmbu->nlTH90%|-V`(I%CKMAxEj5>vBAMF@_Ci~UH(Npxg~&TJR&oh1cr}c?l3OW7 zd!ZCDw_!8GTxWAPmznEvp6~tuFFdE`e9!0i`#qgH9a&L%Sv>XUVlfkBlO_B6NG3Dp z$!vd`SsjWN4M}xxC`EEW-_}ENur|M${_t!P`lBh)=#S3Tp}!;vMt?aq znorIxn**mwu0&;Mkc&~M>o@{fH!eo59j>Fk-WdsRXs6)KN)EiG?uGTac6eJgf!qk%nYFpS;JIRRiw@&A=vs6gIv0!Dhc|ckVYJ53GUcAI=rRM;nPq%Sb)y$CEtx zL|FizcDdlQ;$--|$_!tKLtv{!3txtR!?q+7((V(C`W0^;zPkQ`ubpc6X4L}U8XMue zu?6^kRslb>kHC-p?(gQPXoa7eDs{Ut<=_lcpVylsDj;Cy`M?k%)>F#ZfuTGncuExWA5R Bu;Bmz diff --git a/src/cctz/testdata/zoneinfo/Indian/Antananarivo b/src/cctz/testdata/zoneinfo/Indian/Antananarivo deleted file mode 100644 index 0bf86f024a06fea7711882ff24cd2baf7e5d3ad8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 160 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}Xz#-v2-_@$=a)Ao`K e3>a7#7%UtZIedIW7+f7eI5>oX3&_$n<^lk6_Z_7G diff --git a/src/cctz/testdata/zoneinfo/Indian/Chagos b/src/cctz/testdata/zoneinfo/Indian/Chagos deleted file mode 100644 index 8b8ce226b6b7f67229577b837775e7d448348bde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%&{_9=4oIKDv%4D@filidKs>hq1{R=M Z2@D)Qz99_S2Btu4#=vC*B<*y~xB&JZ61xBZ diff --git a/src/cctz/testdata/zoneinfo/Indian/Christmas b/src/cctz/testdata/zoneinfo/Indian/Christmas deleted file mode 100644 index 766024b36c50c66e097b9811e5650468b1695746..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iVVEVl9qP#{?bq&ca8fyKu+ghAWDoPo;* KNZRR|a{&N$sSVcv diff --git a/src/cctz/testdata/zoneinfo/Indian/Cocos b/src/cctz/testdata/zoneinfo/Indian/Cocos deleted file mode 100644 index 117503410ce98195cd30ca4f63777465b2991e13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;uKz$#6RNfZC=hiAq&Yf+fyKu+ghAWD%-Dc| P%LYu_>6%#?8*l*t;+zj= diff --git a/src/cctz/testdata/zoneinfo/Indian/Comoro b/src/cctz/testdata/zoneinfo/Indian/Comoro deleted file mode 100644 index 640b3e884885b08cad45d3a3e11cbafaf955b5e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@$117rkBAjfPqEVz<@#9z?6Z@21wfJ HnsNaEVA2e| diff --git a/src/cctz/testdata/zoneinfo/Indian/Mahe b/src/cctz/testdata/zoneinfo/Indian/Mahe deleted file mode 100644 index e7fccf8296e7eb93c2d49f26570f68be2eeeb475..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iW=Sq1A~PF1BZ`q2!pnPDG-}5aM=J!J6#hl0MNJ<_W%F@ diff --git a/src/cctz/testdata/zoneinfo/Indian/Mayotte b/src/cctz/testdata/zoneinfo/Indian/Mayotte deleted file mode 100644 index 7a009c3122060329eed1af132b74937fd88f632b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~@$&@yBD$hrzJ@{>n6GhrE|{-*dJdSc zwNDAm*Isi0tY2q-m<33mZXYvPUaz4OEU%w$4wg4a+zXaB49Eh@8##Rd%NrZL2lGu- zOTm0o5oNG?Gq#mr^=4ng!1CtL?||hku62RsEl&!7<*jz|gZb90r-J!5vz)-{ZF^3D z)!S8V4a{g5~|HtikgB885){0nvG2`9SYnFh9ulGngN&vkpAfzV%un<(0`rqB9)Q&+Yo}Q-GBdHVurf1I2pJd*z*YlE76t};4@M3K215%5 vJ_ZK207el81`7uU2_N4Oh7cguHZU8zf{-F9D1(CrU99|M z5Xur7gV6;m3nExibc5xVNz1Z4UA)vL*oUT$($4$ri{JdxJ6?Y8?|J@b=kVGc2OD){ z(Iwy~=%&lQ_#+4Sv8DXZnCDmR{U>osH&cF=^5xzj0pniqRem>1Jun&pU*DKR-v2@h z20Plokk13YIeiKoI3H%|b8j1Z!NEf*$iof>9v;~Pf3JQDAClC=Kcr137zu$N`}E-O zgF^5VcM<&D*U!@bAMrc_x%Okoztkq)|JC1!{F~8<{JYx(A6;1jA8Vch$I}OpPbh9C zIB|krBN4Tm!{z3C=-1Y{IhwDN?MJ`f!Jywjir|WrN%V?$W0>C<3Bor$PC}nO7{z>! zPl|r?!v^%qa{_p7S0!BK^kH6oG8@jAo}t&6F2l72P3U!+yDq{nedZi`LwYCN@XL!n zPbgw(pBEGyrp%8yS;{TLvmE8t&?NG0w-WbLaIFVk*mK84`|WM5@S>Kh9QER(MtF(M z7XDxOx4KClt7fthJwzF=o6m@ic60p<&5 zx`X*5ky>EBsHY~FFJ{RD=8J1`gZUClnh6X*Aj$C-%$H)~PGDqW#sdHU-@(Md047=f i|KGWRf#d)G;|Cade0)O~yn)y?7>Hd$7`T88Q!W64fkAEn diff --git a/src/cctz/testdata/zoneinfo/Japan b/src/cctz/testdata/zoneinfo/Japan deleted file mode 100644 index 1aa066ce38fce7bd0a680f51d6f075718d153a77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 213 zcmWHE%1kq2AP5+NDnJ+nLI`W&1S(?&VxIp%ka}oI0f@eC#{{9@Mt%VCZ~XWL=HEPP z4d&lwXMoUaWx@2FXOF=2-Jbs+m>8jufuR{>FhkD*MivH!x(N&%KE5FgUM@f!9Kyf_ IBy=sg04jJ!hyVZp diff --git a/src/cctz/testdata/zoneinfo/Kwajalein b/src/cctz/testdata/zoneinfo/Kwajalein deleted file mode 100644 index 9416d522d0a3e19ab6b81317f5b94961c55e91fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 219 zcmWHE%1kq2AP5+NDnJ+nLI`VN11bYyiT^-QXC|Qlq7S|`y#S(5zT!#%(dXS7KY-}} zZPEcCb9Ku292l9H8Ch5v80I_xiOkx-z{0@Lvw(qvfuU{!1JD2e;SLM}3=As{Fo^j0 fhA?Ow8UnEagSLSsgRY?wkZr`kWdkJbfIKb$c@{B1 diff --git a/src/cctz/testdata/zoneinfo/Libya b/src/cctz/testdata/zoneinfo/Libya deleted file mode 100644 index e0c89971aabea2c87842a9276b043d0fd946e34e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 431 zcmWHE%1kq2AP5+NDnJ+nLI`V704ievV!{7Fu<+AC6%c)Q_eKE_eNTC90*HQCaS6mo0*F>~*be3!`F#ZQja|&Z>P<|u9)RQn=FS9B41pmx8$fhW=9UH~MlfWC y(hweq1d4zV0|QSCNUe+lBQU)91Q<9$YzAH*-w+08*I*D4!r%(TTtGtChzkG|lxEie diff --git a/src/cctz/testdata/zoneinfo/MET b/src/cctz/testdata/zoneinfo/MET deleted file mode 100644 index 31973271d2f87f7e9df4e8b0a1481f09a9e5407d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1103 zcmb8t{Yz6(7zgk>-LhoqO>@p^wOVUsb1!a_h#+h32XiZ-QDS9*B1JEZAyHA0FetGf zW&{eewrsjAon_86r)6eal=d>U96^wjMNn1*(l2(O@BRSmT+aF2?{l7e;9jn^^iX9k zGwo2o*}QD?X!_hsubkwr_9i6sD{mDGVHg=4ah!)3*N})!PbN`F~8|; zbk5D`{m8f86vMXA7TEsO2mL-7?C|WcQUC4p0^~b2hheA9?4kNydnfEFR>44Fsg&y7 z8W#Cp?s3?Y{4?g<6zu&z2JcVQN~yo^?GG3Xe}Mfx5jfzk@zDN*h5+(IS0)@hQ4b#- zya0zvPQu5V)gI~}-mnMx$;Lq#Dw#k%6kPi!_7 z$-Y8S>N}VoKN9oT02EJkz>J6oN`~rSX0V^7bF$j}a9N`pF2Cr6D^6EK=@C0zxwjmy zGFzc+lL@X?=0SOu0H;aOZ*G`0?%at diff --git a/src/cctz/testdata/zoneinfo/MST b/src/cctz/testdata/zoneinfo/MST deleted file mode 100644 index c2bd2f949b248b835c98216b4dc66f9f6eb0265e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 240 zcmWHE%1kq2AP5+NDnJ+nLI`W&1}b9#VuAla5XZu^0YuMRW;Fps&)?170HPPP$$r^U93H~J1!S0W0RTV0SUUg! diff --git a/src/cctz/testdata/zoneinfo/MST7MDT b/src/cctz/testdata/zoneinfo/MST7MDT deleted file mode 100644 index 09e54e5c7c5bb2384e37626d4b985cfad29ed29b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1042 zcmb`_OH30{6b9hiQfNDlGAban#Rn**we|%SS|6acqQ*voHJ}Sk6CS~hsIkU{I!e{B zFiez%O28Hf(HOPFji!l0jK;*rqHaVJL^moLW7LF7q2s-O)GZtDITiC{kFCT$_~lcinouj~eRN)v*ol1BtKpZeGUPrs^%XP$WA z^j$YBUo)`JBjl1^U`cT<%@R=_oq;nB>O^K$us~utvvyi!IjcGatLEg)8Y;y8vQxL= zqFpjvy#EY&1)-G5r>Wi8}n}UAzZg-}wcu>OKiqA9w+82zQIDv2jNX-qd&;_S!DMKJPx*_v4YE zRQ!1|RR7Aqt^bl`xu=WJ-}y#Fp`x`!G^lyJh3)z%dAeT N-QssRtPZQ4`wbnj4)_27 diff --git a/src/cctz/testdata/zoneinfo/Mexico/BajaNorte b/src/cctz/testdata/zoneinfo/Mexico/BajaNorte deleted file mode 100644 index 0d8c993bd1cf2fa2cbf002421ec9c0fb2b29645b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1367 zcmc)J$xo9(9LDi!Sqf!)WfxE@pruesTehMivS?)sAQi=fTM&bZ0Yr&h5EK)MK?-Q1 zF<{l0NKh6rh(Qr9L}T3QK@dbl1cL0MtWswl{s4|nGw-*bd4KPFX{tGpk**}GE*_m= zn=Q@ij}*}{Q@WiEblqzj&SI_3OF-+ULJF9h($nB4t{h=*7EVvHz8)#TeZ9vF?&~XS zasJ6Q6?2_skKt}2fV zy9J&qeGgBcYe#=&K0;>>-9>*VTt)wcT|{U7a?v@jI~;q@yv=@i!K?^gn7bfi=ZnMX z@KWb7`0vZz@N%;nHr)5-*zZWLOGGTZOO`PItOab8?WJYs#z(|DR+A(lY#MG33*@7) zpd=DD=ib8R4_}DrI1x_P!xnvYxNq6@hGXYeZDp|a(>mCux>m%_xf^Bhnqn<%o0kLI zWt@WTQ}@CS(Hht>Bp7y*1i{Yk$y!3!T61UEg&zpJOb6)Lxof`@?51~w*R{{X>l^0a z4Y#{tQLc}Oj+2dr&tdlzE7;@2XO5kF22Q}6VxGa99X`Nf?#L?SGJCB5%p z?~$XhPiq4#{g|(1bG}s-u&nVg?3aHAmRCf;isR)XI!2T^p0L0AG#rp@3I~c);2`BN z94t`5DmN33K1NhSE^x@=5WJ;h3EtZM3f@-ltfONjw50~#Ub+B>-7JB3WcI+}Mb%n1 z7m?5kN2Xndqx^L6&Zv{{E}QeP+A{%G&)pIcx}uF0aCB!O95Y}C$A;Dv@c2Bw5#QK^ zUjEmIZ!na{5n?b@YKgJIP+CCD*ms^KuJoTnzuU*fYe;;uh9t5bMfX0s6E#Fg4^;F( T8t*St%H+~`g+iu~$%X#_Z)Mmm diff --git a/src/cctz/testdata/zoneinfo/Mexico/BajaSur b/src/cctz/testdata/zoneinfo/Mexico/BajaSur deleted file mode 100644 index 5aa6039ea4cb36077f048782b54c6275c25e86b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 690 zcmb8r%PT~26bJA#jA)uNDI^=A6bj=pUV~v6!(7kn{hC1|r4S1n%tDHkp_KC6D38R( zm_k`9Q5MQ$V<9997DCeXJKujm&h7lp?{oV8Hdk)!cIxTRQi%jNm;Cn=qll?R>l9II zo~J&ZJ8yBA9%rqcy>BwYUTqre{TYAd{poYRUA(2Ft}z`?{XmF|XR^f!r&N8ysWHWH zn*Ihh_{YNO;U65Q^hYh6@qG z!}Kx`#b8v-Q2?Ti-6KF0gGtaUFyB<&3d}b%Is@jLv&(?_7Sb<1fEX6f{(;HiHw!8ble7pX8V7~qA0x;hp{{Wcp*wR}7)W+cCzX;5CPRR%J zUG!VPd{>u1FyD5|IfG3M6nD2Qb70mZ~{2k2q-r)}B`m zKSFd?0Z@WCfET7OC+6|HV8E4FCVnoxs5I|NrU*3>+Ym nk>~&aof{Yhz@&(eZwP~La0r7l5c|3SX%G$%Vc-G^m~jCBO_!h*^=&u`b^MgPM&pXdAVoCC+`C zvcm``=uOA5{41PrEJwHt{|M7CV(p{eibm4Z+xxqm)QESkgF4hS$5Ers1p1CDfgU!6 z(IZ)5bWGt#$39H)^!(i)9`xw55c*!K1$}=ujec-*F-^}soP3HN>rSEL!2$I6@lo_d zXE%D%eg*yL@JaL(>q9@b1~~eigp5NcH7C%?@25NH{>4hy{Puuypxu5#|lxYP!VOcfdDJ2@hZqGWf* z#1XifQD+S8f@|L9!Q!rRxHkR~D%*46x~tQ0ee(h=ITL{!bP}EjqjJB1rSkW1Bg=5Y zHrXUol0-UpWk5fl8X~DqO5;i+2a4d2nnW$ zFoQ`(Ovtqukr2`sr|aQqMn=~}Y_&Ov-F1LIu(CLal(trHu)8b{jjfigVRaf?HLGWJ Hl~vNe?I}r+ diff --git a/src/cctz/testdata/zoneinfo/NZ-CHAT b/src/cctz/testdata/zoneinfo/NZ-CHAT deleted file mode 100644 index f06065ebd18315683f60cf87839d477a1d699f01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 808 zcmbu-xl0^T90%|>Uf_7F7mGw)vmR0R7wQJAa>;eXql%c_?1YYrH2--=QZTZNiknW0<-&2Tk1@ zFm37!Ojl=N#y~I3w2Z*44{r@0dZ4+|Zg@JZF-o?z#c<~%d?DBj7n)(t?_`+!wG8HM zoI^`*63n03gD;!Tpmk^k7Pu01Mkx&M!XndOSS$$|ZL?P~_2?xjCmK~&@~24WmY!{E z+_J3%oooBKpmFVyLg-i?h0d{fD2?~Q@=vGG)gOfNyB|>L21S=25VAbIjtd91>n)OtTQT!9_=&z?Q(bdl~`kTRh^xCfXu&($x^FPKScZ{+W;6LAHmmo40ZDVO|!4R{{itMG??cuXR iv*?GaQ&y@yUMh5?I)YV_S8|o}El1EJ$+ULUT6_eHWtUF? diff --git a/src/cctz/testdata/zoneinfo/Navajo b/src/cctz/testdata/zoneinfo/Navajo deleted file mode 100644 index 09e54e5c7c5bb2384e37626d4b985cfad29ed29b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1042 zcmb`_OH30{6b9hiQfNDlGAban#Rn**we|%SS|6acqQ*voHJ}Sk6CS~hsIkU{I!e{B zFiez%O28Hf(HOPFji!l0jK;*rqHaVJL^moLW7LF7q2s-O)GZtDITiC{kFCT$_~lcinouj~eRN)v*ol1BtKpZeGUPrs^%XP$WA z^j$YBUo)`JBjl1^U`cT<%@R=_oq;nB>O^K$us~utvvyi!IjcGatLEg)8Y;y8vQxL= zqFpjvy#EY&1)-G5r>Wi8}n}UAzZg-}wcu>OKiqA9w+82zQIDv2jNX-qd&;_S!DMKJPx*_v4YE zRQ!1|RR7Aqt^bl`xu=WJ-}y#Fp`x`!G^lyJh3)z%dAeT N-QssRtPZQ4`wbnj4)_27 diff --git a/src/cctz/testdata/zoneinfo/PRC b/src/cctz/testdata/zoneinfo/PRC deleted file mode 100644 index d6b66984a2f36ae36b35e174756707aa7286c292..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 393 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%P-o_>38EKFU(^7i7gn--0MRERr?p`IRaYgj{57BbVE%QR{b2qL zwzL9}IX7iLfz{u1toZ$;V7>;sJD9I=$w7dL5f5ZwD7+3bpl$*q3j;$z0|SSTZwQ04 P3lIl~FmM40T?;M%d{}{0 diff --git a/src/cctz/testdata/zoneinfo/PST8PDT b/src/cctz/testdata/zoneinfo/PST8PDT deleted file mode 100644 index aaf07787ad92b65eadae63b64bba290f9f961507..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1294 zcmci9*H2Sn9LDieD5GT^k!3}#fRvU}+Ol293PTAX6-Nw;QA|w?AV~B=#E63!iUt?{e^uDUh_zbTc#Chy5ydf$}g%hG-_ z7wo2OE3Uy@hxsMi*~H;~SN9$GbM*tXyYU?QrSu}&Q>jP4>T}WFqRr^H#I5M}%mDO< zJQ(eZPh#os^*g7b12W}8$Ai#88^?v3T+yF>W9U%*6gu2uLPrek=xFT-N8dM=*8u-2 z{{WAlY(^(?9-)(aZlk|bE~9@U&!AI*h3K^3EtbA##%TvUYg+=(PM?<2^SOa+c)slb z{P$G?Yr>C<-P8(r^yXo(L4jMte=KgRdvGB zLVqb4XI7tj4tr%dz}|;CSbFXgG77IrdItNteuQO;N?2wdHj*($E-r@U-S1(=;6B*D zu^v{o7IAbgpt1s1J>Clk79EAv716Nf;3X*;W3>4`a8P^!9Gq?qhsZMEQ0)L5W)lvF zds?yNF($lU0!PgC!)sgS;dPy_;q`SMMl!~1Xt)n=ET4rVub07_a=PHCl4_35MW-~v zG5asTv4KW7F7_}SH_{J~iCI}~o%H$xGR;5-ZYcwj2N-h2ezA3}w diff --git a/src/cctz/testdata/zoneinfo/Pacific/Apia b/src/cctz/testdata/zoneinfo/Pacific/Apia deleted file mode 100644 index a6b835aab4c5e2e2a31bda0afdc8646b57d19a87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 407 zcmWHE%1kq2AP5+NDnJ+nLI`V-0xDw%VyXW?kY{_60Ypz^{R5_NC9zn5%<-A8z5zu0 zPS<__qWx+gC4lL_-3vgpe>v|15FL>A4@?IpXeEI7L2eJg{9p$jFh4}?5SSk-{|?L# zV_O2|hyA|*=7&FP1M?&9Zvyipk7a=QQTwNW`O)iJ!F0@u4Pf!u{&X-uu459IAD{0D z<|ky7JYZyEVP;`wW5t9F3>z94fc}eT0FiMX3@rcu7bh@s{r{gDz`)1Au!h*^=&u`b^MgPM&pXdAVoCC+`C zvcm``=uOA5{41PrEJwHt{|M7CV(p{eibm4Z+xxqm)QESkgF4hS$5Ers1p1CDfgU!6 z(IZ)5bWGt#$39H)^!(i)9`xw55c*!K1$}=ujec-*F-^}soP3HN>rSEL!2$I6@lo_d zXE%D%eg*yL@JaL(>q9@b1~~eigp5NcH7C%?@25NH{>4hy{Puuypxu5#|lxYP!VOcfdDJ2@hZqGWf* z#1XifQD+S8f@|L9!Q!rRxHkR~D%*46x~tQ0ee(h=ITL{!bP}EjqjJB1rSkW1Bg=5Y zHrXUol0-UpWk5fl8X~DqO5;i+2a4d2nnW$ zFoQ`(Ovtqukr2`sr|aQqMn=~}Y_&Ov-F1LIu(CLal(trHu)8b{jjfigVRaf?HLGWJ Hl~vNe?I}r+ diff --git a/src/cctz/testdata/zoneinfo/Pacific/Bougainville b/src/cctz/testdata/zoneinfo/Pacific/Bougainville deleted file mode 100644 index 7c667093c50d33ce9161662a732fcf6c5092a38b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 201 zcmWHE%1kq2AP5+NDnJ+nLI`VN1u6q!(f>dYwk=2lL>IkXG66)NaW+c;(U-JyK7h@e zcfEm;iJ6IofnnkekU-}L1|Yj<0RtxkL)`=hUIvC)8yEzAd_x!le1U|vp#g)ofhCYO OWZ<#^l6Ja=hFky?{3-7M diff --git a/src/cctz/testdata/zoneinfo/Pacific/Chatham b/src/cctz/testdata/zoneinfo/Pacific/Chatham deleted file mode 100644 index f06065ebd18315683f60cf87839d477a1d699f01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 808 zcmbu-xl0^T90%|>Uf_7F7mGw)vmR0R7wQJAa>;eXql%c_?1YYrH2--=QZTZNiknW0<-&2Tk1@ zFm37!Ojl=N#y~I3w2Z*44{r@0dZ4+|Zg@JZF-o?z#c<~%d?DBj7n)(t?_`+!wG8HM zoI^`*63n03gD;!Tpmk^k7Pu01Mkx&M!XndOSS$$|ZL?P~_2?xjCmK~&@~24WmY!{E z+_J3%oooBKpmFVyLg-i?h0d{fD2?~Q@=vGG)gOfNyB|>L21S=25VAbIjtd91>n)OtTQT!9_=&z?Q(bdl~`kTRh^xCfXu&($x^FPKScZ{+W;6LAHmmo40ZDVO|!4R{{itMG??cuXR iv*?GaQ&y@yUMh5?I)YV_S8|o}El1EJ$+ULUT6_eHWtUF? diff --git a/src/cctz/testdata/zoneinfo/Pacific/Chuuk b/src/cctz/testdata/zoneinfo/Pacific/Chuuk deleted file mode 100644 index ea3fb5cd3c9e5e132c19a5320516dbc45a089135..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 195 zcmWHE%1kq2AP5+NDnJ+nLI`VN11e(yVxIp%Ao6g(35c#UQ`-WfX9zBS0HPOI{`>%< zPrl+x0MVBO`93f*F$3ZM|2AhpHud>{$esltv+5==aQOI!FlZYZFlZZCGH}@dS$4XH G23!C=%Q2|{ diff --git a/src/cctz/testdata/zoneinfo/Pacific/Easter b/src/cctz/testdata/zoneinfo/Pacific/Easter deleted file mode 100644 index 54dff005b876339f5c1ff3dc0aeae1519c29b368..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1174 zcmb``Nla5w6b9himPtwl1QAda2M{eoCrUvm&q}2T1(Yg+6cG$k7M2hsCX%Quq`HtH z7(*g)SQtbD4_p8VgcoBRap-~|iNuW|(HI*viX+c^|GG77JTK>+`@M5cy1BKLJ8HFL z*^tl)mMm<`uNi4j0-YtK@iotiry5Uu|BXC$kGaSCV2VNc8#k0AH_)~DiLK7V6XNM!*2jHmr zY&d$z0Iz*f!4VqkI-}v3K_k4r;TOE2Jr<5VEmN_%jZP`NDg7tBx$rH#C29_iGZ2B$ zi2FVX$A9_;Z=JmkCoJBFx80lI+1&P-o3Qf6RXB0P1t+zhg_AGW!ztA@u{0@fVEjOD)wE+<-@7+99XXyh12||F>fHju;FO{`sweK0-=%7{~q4)SOI5Vn1ZwV zJg~8T0M2%~VXou}PuIxKy1TGRdk5ZSxdi8gU4+f*VUCUw^XCRQH?$kh^+;9hyJevn z&Kq~ad)x=%{857Wf}sr9`oJIk!s1qe&?vexfPS%Q7T(*^0q;|O`dr+jF*HISZ%~iGfAbV gnMN~}1ZGkh_4J);OthvatCRI98cm{A_xBX|2T4)%{r~^~ diff --git a/src/cctz/testdata/zoneinfo/Pacific/Efate b/src/cctz/testdata/zoneinfo/Pacific/Efate deleted file mode 100644 index bf7471dd3fc26b7fba883acf0e0bf0a69687b31e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 342 zcmWHE%1kq2AP5+NDnJ+nLI`US2P$I*VxIp%FzM@|Eg*gDl`|c{^sh5uTJqBO3n0GK zp<4$)wDhK%V7|~8@eak-{>V7`3y4KQCJd$$8fTrqkVn6KnL7tB|-o&)Bq zXxD@Js?v2}z8ZHTn6LIb0nAr_?F{B?JgK?B00f$ifndJYOAjz#JJHyIi4iMgV3>Ob kq-DhcMivH!SsNHQe0)O~v<;1b*pPwC21wfJ8X9r|0JO|FDgXcg diff --git a/src/cctz/testdata/zoneinfo/Pacific/Enderbury b/src/cctz/testdata/zoneinfo/Pacific/Enderbury deleted file mode 100644 index 2b6a06088ef603f03fb482b628347ff72970fe3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#VuAlaa9HPd1CY%i6vlD@MC-F!ZeU~rDFK52 t|HB;^SpNS{4PfA4VAytnfk)TCfI-*L2#5_Cv<;0JxNLx=ovxuV7XW_87Tf>; diff --git a/src/cctz/testdata/zoneinfo/Pacific/Fakaofo b/src/cctz/testdata/zoneinfo/Pacific/Fakaofo deleted file mode 100644 index b7b30213e154012a5275c1384b41dbff29860644..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VxIp%P-h<60n+F9cjg90rvLxrD;OC5|4$8I hU}0d`c7cJz$2WvQ*U*qb+t8SS%LYi==^7ey0RV5D7HR+h diff --git a/src/cctz/testdata/zoneinfo/Pacific/Fiji b/src/cctz/testdata/zoneinfo/Pacific/Fiji deleted file mode 100644 index 610b850b1dec4966d570eb36f9a8b35fd6aacd68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 396 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0(VxIp%FiUvj0U(>f%v$^bn7;li0YqDj8)kGdY<6rf2y)0MQY$Pa$-b9+-~&dmKzhMG1iE=({Vybd2RE zFdcjBSONnO#7SNO^W*QagZT+e9}}1u@jwQK3@kprAq?7vh74Rb LK+;av(2xrNoShE_ diff --git a/src/cctz/testdata/zoneinfo/Pacific/Guam b/src/cctz/testdata/zoneinfo/Pacific/Guam deleted file mode 100644 index bf9a2d955fc23bb6c2043472e8292d4adc20d4ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350 zcmWHE%1kq2AP5+NDnJ+nLI`US1uA0$V$uIVAoB3&84z7(rt1TuPn%DD0HQDGb$$TR zZ_M{Gfav#TKfwIovl+nrfA;D>LxI7Ffh#8z{mp@5%BR1VQ>!)VbC_PWN>#0VQ|g>a=1XGuAu=J0D+8M A761SM diff --git a/src/cctz/testdata/zoneinfo/Pacific/Honolulu b/src/cctz/testdata/zoneinfo/Pacific/Honolulu deleted file mode 100644 index 40e3d492e6c22c30041c31f159d4fe0ee9451c03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 221 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I&Vv+wqQ1YN)ABf(~>g)lg6$>Lk^yyC96CnDM z@|OZIo#<%+qObNAdoVIFGP5wU{{NrD#J~U~BN$lz|F6nmg)lg6$>Lk^yyC96CnDM z@|OZIo#<%+qObNAdoVIFGP5wU{{NrD#J~U~BN$lz|F6nm; diff --git a/src/cctz/testdata/zoneinfo/Pacific/Kiritimati b/src/cctz/testdata/zoneinfo/Pacific/Kiritimati deleted file mode 100644 index 2f676d3bf5c8599994bcabd402ca30efa4cde5dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#Vxj*)P-pJZ0Aw==g?<824En6v3mBQ0|NqZv xU|{(FKMSbz|Nr6y1}+AMBM%t(e0)O~bPWwm3_v7%< z556@8^H09wN&xXM3G#u(|F=m8fb28tPIq8rVrF7tW@2Uf|KHsQBsk*?h@7>7frWvg uZUO@b14GXO1|9~66$cmue0)O~v<(dzv<)nQv;hzsF>u)cMeKA94Y>e{!9$S% diff --git a/src/cctz/testdata/zoneinfo/Pacific/Kwajalein b/src/cctz/testdata/zoneinfo/Pacific/Kwajalein deleted file mode 100644 index 9416d522d0a3e19ab6b81317f5b94961c55e91fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 219 zcmWHE%1kq2AP5+NDnJ+nLI`VN11bYyiT^-QXC|Qlq7S|`y#S(5zT!#%(dXS7KY-}} zZPEcCb9Ku292l9H8Ch5v80I_xiOkx-z{0@Lvw(qvfuU{!1JD2e;SLM}3=As{Fo^j0 fhA?Ow8UnEagSLSsgRY?wkZr`kWdkJbfIKb$c@{B1 diff --git a/src/cctz/testdata/zoneinfo/Pacific/Majuro b/src/cctz/testdata/zoneinfo/Pacific/Majuro deleted file mode 100644 index 9228ee02ede240cc6c5831c8e54ed8216216ff23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 218 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I)Vv+wqP-iC60HS9IPQ3u47g+xM0HP1RH3joe zzT!#%@z2}37l7#hZPEdZOpMG-j4TWc3mSmNFwEM(0A$xqVBlb2=vlzP!@#iO0E2*! dZwQ07p&^5|fhCYO0AeEsE*l_er)y}$1pw{IITio_ diff --git a/src/cctz/testdata/zoneinfo/Pacific/Marquesas b/src/cctz/testdata/zoneinfo/Pacific/Marquesas deleted file mode 100644 index 6ea24b72cd9552c973510d1c17ace66fd35e1cc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;uKz$VCBVmn@&Er?3kHV&|En?>SbTg#7<3IR RjSU#MY{0agrIoP(7XUx`61@Nb diff --git a/src/cctz/testdata/zoneinfo/Pacific/Midway b/src/cctz/testdata/zoneinfo/Pacific/Midway deleted file mode 100644 index b25364c599463a5683e33c16577545ee8d028908..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 169 zcmWHE%1kq2AP5+NDnJ+nLI`VN1}b9#VuAlaP-h z7?~Lu=G1`r3wMC@)Jvyq$^g?_pM&Wz z{%2r1R$@~CBNHV9bZEOJwrVM9bXd=rEkmy0OZOh*Z=?k diff --git a/src/cctz/testdata/zoneinfo/Pacific/Noumea b/src/cctz/testdata/zoneinfo/Pacific/Noumea deleted file mode 100644 index 824f814160ee4a95cc6a6d5553b3c1aacc907895..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I*VxIp%FzM@&5|BQ=XS)JGG=JFc10Y)9*c>ol z(EPmvh;OvO`vZtJmT)OxVgy45hB-VSp%n)hSr`~*ZD8Q=@eN_nHZ%faLk2DzAZe#- HXvhTsP@Wrk diff --git a/src/cctz/testdata/zoneinfo/Pacific/Pago_Pago b/src/cctz/testdata/zoneinfo/Pacific/Pago_Pago deleted file mode 100644 index 001289ceecff85fe0d0f376a6bc394329445f13f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 146 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VvhenkY{@WOiyI}&A|wi*;v8A@c)1O4-lCe Uz`)|;8^RDA9Kyf_Bn%C?07{q{2><{9 diff --git a/src/cctz/testdata/zoneinfo/Pacific/Palau b/src/cctz/testdata/zoneinfo/Pacific/Palau deleted file mode 100644 index bc8eb7a55b8a20a8c800507b620d0afef1d477a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VvhenAoB2h4v4NZGke3x^#8xk6p$%(B4Ba? W1B;Ju2!pnPB?FfYkhIgaO%~b! diff --git a/src/cctz/testdata/zoneinfo/Pacific/Pitcairn b/src/cctz/testdata/zoneinfo/Pacific/Pitcairn deleted file mode 100644 index 8a4ba4d30a6b7da8399f20a8b98c91169e04ae40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$V!r=CP-m|91*Ff^#fgKF>Hq&W9tMX0|2rxe eSpNU-Z(!i^@eN_nHLx%?0Few_HbBzOf(rmy=N5|q diff --git a/src/cctz/testdata/zoneinfo/Pacific/Pohnpei b/src/cctz/testdata/zoneinfo/Pacific/Pohnpei deleted file mode 100644 index b92b254a9af107fc4e40c4ca38d1ddc110effefc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214 zcmWHE%1kq2AP5+NDnJ+nLI`VN2P$I)VuAlaAo6gh4v4NZQ&%< z556@8^H09wN&xXM3G#hlWMXDwVP^XO-{}g-$|)fra@Gb076yj82@D(z3_S}Nczk?A Z7_%< z556@8^H09wN&xXM3G#hlWMXDwVP^XO-{}g-$|)fra@Gb076yj82@D(z3_S}Nczk?A Z7_1;1{MZ} do&^k?KE5Fg0lq*&+t7f4%LYi==^7ev0RZ8E7y$qP diff --git a/src/cctz/testdata/zoneinfo/Pacific/Rarotonga b/src/cctz/testdata/zoneinfo/Pacific/Rarotonga deleted file mode 100644 index 7220bda0adb9f04d704cb893a5d1ee8bd9173b82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmWHE%1kq2AP5+NDnJ+nLI`V-0V-n!Vv+wqP~&sw1c<)BFyRD9zrY%44G=A8zf}T6 z3sp8MfM{X)>0rJ{WHOj9^1l+y7qfH)^Tl3FodHrOp_I4)OrIzR^QD-a!F;I|kzl^` zBULb8ro$S{mp#M|=F4Tsg8A|bUxN7x?*GAj#m3WMzLKGg1OpH#XT4AW(JBJ}zt-9Wiayj c_=Yg(8X6cIfJg>i14|%_%Ld4{Gc@1=03*mq1poj5 diff --git a/src/cctz/testdata/zoneinfo/Pacific/Saipan b/src/cctz/testdata/zoneinfo/Pacific/Saipan deleted file mode 100644 index 9539353b2cbe7140e9aaa6f0245b4d5a4e8b090c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 341 zcmWHE%1kq2AP5+NDnJ+nLI`US0V-nyV$uIVAoB3Y9S~h-rV|6AF9>#g0MT#E_c4Iz z_hvu9{NJ+~!2Eyq>OCOw|BP~A{{PsB4}M{5)$?#n1oL@n+QAxm_fKg63Gk&Z2CKJnj!R%q6Bt++ t7-nr?<{9 diff --git a/src/cctz/testdata/zoneinfo/Pacific/Tahiti b/src/cctz/testdata/zoneinfo/Pacific/Tahiti deleted file mode 100644 index 50a064fa0166a0dc22f89cdadf957a545d3f6544..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iU~B_MPM~sx{xd3&SC+7eF diff --git a/src/cctz/testdata/zoneinfo/Pacific/Truk b/src/cctz/testdata/zoneinfo/Pacific/Truk deleted file mode 100644 index ea3fb5cd3c9e5e132c19a5320516dbc45a089135..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 195 zcmWHE%1kq2AP5+NDnJ+nLI`VN11e(yVxIp%Ao6g(35c#UQ`-WfX9zBS0HPOI{`>%< zPrl+x0MVBO`93f*F$3ZM|2AhpHud>{$esltv+5==aQOI!FlZYZFlZZCGH}@dS$4XH G23!C=%Q2|{ diff --git a/src/cctz/testdata/zoneinfo/Pacific/Wake b/src/cctz/testdata/zoneinfo/Pacific/Wake deleted file mode 100644 index 71cca8877d33561091fe0faf319f3d3a4f14bbc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 134 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;j{iVVXC`q5C@{waq%< zPrl+x0MVBO`93f*F$3ZM|2AhpHud>{$esltv+5==aQOI!FlZYZFlZZCGH}@dS$4XH G23!C=%Q2|{ diff --git a/src/cctz/testdata/zoneinfo/Poland b/src/cctz/testdata/zoneinfo/Poland deleted file mode 100644 index efe1a40f2a8ffd499d22cd83e6b5df6c6c1e8e5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 923 zcmbu+?@Lor7zgk(byj2M)#;{7OYrAt;OA#L^iTEMk$>@(!jN|a=ce0z*QtNz?kLXBUfw}I zS7nf?9Ob6pN5)<; zimVsCFuU^s%(>qRk2c?cx!2q$=wdk|XdB7!15jxJ?_a(A)+nK8`}y)B;; z_&3Q_9OQpQU`dRbEQ%DWFm1I{V(0m=J8Ec>n1dD$zEJV3*h+QLX)~WPTSTYTLYCN6 F{{iE`PO1O^ diff --git a/src/cctz/testdata/zoneinfo/Portugal b/src/cctz/testdata/zoneinfo/Portugal deleted file mode 100644 index 7e9aae727b2b660e7f5e383121f445daf033a9c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1463 zcma*mdoWZ{90%~bu{BtaC}F8(lSr&bN>kI6G#R8}8#GCSkxFI6)HF>awim{rG!4pH zjAkS6&?xfAD}+?!6(J%k38{3?_x{s=+&gDK=lA=bb9VRctnlb5e@kk~i$$*>gIvO; zx5UuPR?>sJNMFZybM%Pu!!cpRB*(Ks@NX^Z_8FKTWPpA_ z@GV$)SRNKzI>8dvI>yCPSUM?%Wp%|e@;RTEJc2J$ywNYeABnmmQ3hXL3WSvbUa-pJ z5Uk$A4kG(&b_h_v+IbJwdSszr+t~-}<=Pmhc(7r>M@IHF7P&Hxr}dNib(kY#H}gE2 z60DIoRXLs@d2_G?d2>xU&S?qNMBb8h68$%>BF2nVo_vv*oYN}_g?;h< zus_@#ehNMa2YhVdpsNY|ypIcqEIDvk{|_AD8uQ3`UzBth7nI=W*l#%2H37di^uqCH zEpS3w0ly{Y!O2JolwH09r%sFDci$W_Ie*$s41d_g!5OP?_>+GD&T9CLTun_KO?9v)Pfq$`_)Lk#_AX9wfvqiQfq27 z!*z1yjMKSLYcLgRx5q=BstCv}%c01nnSJXeMfe<{@QJ z;Fk?8ygJpW6|Cjoa`f8&$8vYdFSSsfjhnT&IO|Kksfrp)o=7RsPnE|~CLKy0b4@2_ nA?0rGMqbFED?55(M>>jhOF%MHXDhR9W&(2yQ)deSnJNAQHdoT( diff --git a/src/cctz/testdata/zoneinfo/ROC b/src/cctz/testdata/zoneinfo/ROC deleted file mode 100644 index 35d89d036d07c3f28dec64092ab1b533c21ae2bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 511 zcmWHE%1kq2AP5+NDnJ+nLI`Wo1S(?zVuAlaP;%~r1c*Ky>e&FIFNH*c>C4^KVET&F z+7BS{tFB56Ao`lmelY*K&3-Wd23uMINc^VkC$RdP&u4<=Z~a#T%ilh67A$|~0mR(9 zs~EuY_lk>Q6a&ZGE-;_-Zf66C&vkC^2M{fIdtn2J77Dprz{teNOcZ2bD0~6ZRL}s5 hfVv3`93YaB$HzB>!8tgD!3&6;T|yYRfE-;5E&yjg_Y?pC diff --git a/src/cctz/testdata/zoneinfo/ROK b/src/cctz/testdata/zoneinfo/ROK deleted file mode 100644 index 1755147fab44e07b7527ce1eaf3ae991473fb222..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 415 zcmWHE%1kq2AP5+NDnJ+nLI`V-1uA0$VuAla(0%$Nf%!Mj>OKJRZ(Z*KtGm6HAI!h=>=BrMx9206|Hxkx%zu)-9c=DXVTlZo zzGq3yVEdj6`n&+~U+5Qr`7fS-0n5MQ4+8UF9lr+VzkY85=D%6K1I&MWUJT5C*FFo( z|6p2J0rI!P;)DqxS}`vjOe-}zfoWww&k2l7EX+{I$chBPVhjxB93YM59SkfC40RJ2 mfV`dsj67gAP^5JRBae@72!nTU2!j_8d%J`%Z~-~GmRtaloVXbP diff --git a/src/cctz/testdata/zoneinfo/Singapore b/src/cctz/testdata/zoneinfo/Singapore deleted file mode 100644 index dbbdea3c8149004cfd525a0fc26e5da72b20e8a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmWHE%1kq2AP5+NDnJ+nLI`W&04f7vh5tZMXBNB|M7K4!g6Uo9eiK0a16)rMK=i52 zPr>x*iSZmD{w0sx40Pj65Kc0Z3+6 wFbFX))JI+5H>OZk;Wj>5{NArxNLx=ovsBJ0BYwwz5oCK diff --git a/src/cctz/testdata/zoneinfo/Turkey b/src/cctz/testdata/zoneinfo/Turkey deleted file mode 100644 index c89186687300068ac4e8505cc0012a1dbf6a9960..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1200 zcmb8tYe-XZ7{~E5FSAXTNrVmOrEG3GwK*+k&CQxqv}sGHf@y>|j6@_03WZimUM>(6(qq%OZe?4YG+iU~q@#8%7`<^tk zL+gW{&{qJw{j7-*faZ4j>uX9k_rVRLpDDSEXC!_7&UM|3ozBb%#WR9z9=R+a^~>r-L0 zN(y(x3!zxVhcSU3DDjsx(ETOutx)=n2V)(7VBE_EC>xrA@s_tRp}oaL`x0C4qIaIW z4&_ysVN&@M%oQiPU~+mlOer`6cZHkaZpC4*D-}=~cDjM?tDMb5r+G@zd!ELi_fD(O zDytTzKaPOv3u34-Gccnj0PbrQx#)iTb@OO#@~ diff --git a/src/cctz/testdata/zoneinfo/UCT b/src/cctz/testdata/zoneinfo/UCT deleted file mode 100644 index 00841a62213e6cccf7f0b7353e5e8ae214185486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S diff --git a/src/cctz/testdata/zoneinfo/US/Alaska b/src/cctz/testdata/zoneinfo/US/Alaska deleted file mode 100644 index cdf0572be31d3052a98494e3d01802b83737f23c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 977 zcmb8sUr1AN6bJC%=G>o~)yl0u(`-5CoUZHL{FCdS_s%U>Hqtf9i&gJ(z=X374+=r7m(tA9> zmJJ=BphJ;Z{*weB6Zol8c{EQizNCEaiV~%q8*a=}&bxjjk-I|@6y>Ey$7IUt zojnr$kKKyMlyq0CVEv#6F6a+usBh?Q$x<%tsDzD*8#ejPu<80y*kYZBE$LaAk2B%x z3wXtc9NrhbnUko$GMk21P37R#cV}ekTgTGyn&C-!?U_-yxOW7$b@s#dy-9doFb=Qx z9)vfP_hlH5jh1@Yq3?hlH8v~t9p6H5$tQP;T$-{(jK(41EofxYkE!qxLhxaP@I*!SvMijT3a zw*uFL;|t+iz28v6Jy=`mF6Y zxbPF+{#?NPj@j4n&WyI-U5}^W-8Z!THjj_Pa-X(e_f0T6k0)xKL_^-!gG5_Dg*t6e^sp`NW?k;9f)uE)$jJt^UyO@1%{2b<|ou4Qn8cwiID%yCVwDC%yJ4p7$>coI3`C@**=ocm7FFwuL-T(jq diff --git a/src/cctz/testdata/zoneinfo/US/Aleutian b/src/cctz/testdata/zoneinfo/US/Aleutian deleted file mode 100644 index b1497bda631efdcb6635ffb6b0ee6f7da9e2a280..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 969 zcmb8sT}V@57zgloA38U!R&8r8EjOz%UGtnxm-gk^nrPAL*iJ>eFc*Db5NSdbO?olJ9< z&oAKe*9H7uQJ9seKTplU^B)x81tZg#w_eV{3p3;JqLbI)#XZBYZO>`gzBvs$T2k;5 zUpMUZ45*B+N^=x;>G#5}dQT1YU0-B)=}ag~uF41D>Ipl%?5+)7eq$D{Io>YuG3FjD zz@A+`xc2aOf%+@LmrF*ScM_}n_@qHs_9%rc^-Clg(P5W=cv4)2# z_1j_@xb5pFNvAg$^(CeM`b_4s|N9ubJ;Ru$CHK*JKxRfw>+jZ;;jBQ%irPjeb86aP yudW((<<_{uwk7!9&9|(uD6gY2g+)4e(ZLG~FGPV?{&*-53<&r^U93H~J1!S0W0RTV0SUUg! diff --git a/src/cctz/testdata/zoneinfo/US/Central b/src/cctz/testdata/zoneinfo/US/Central deleted file mode 100644 index b016880653929aa40dd5ac0e82e4094a9d787cdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1754 zcmb``YfzL`7{Kwv{UQjZBm$vHxgogR;v%kz!4Ba>SgseW(IHKuX<|#1ai+m_B26cw zG{@}1#anoxMK?ksVMQVaYbHU74c!*9l`v%$Qv}*=&;OI(^h4*J^FHVIT+aLH)vPF3 z8!zs=T$~+p%cZ&hh~C-e>D<8%=UVAzuavR;P_$0Qitp}fWvtvX5m$ZIi}#%^5;DL4 z-8(iJ52!n-A6#w1hZdWte-*Tc{_2EATx~Z{KQie{e8jvPA06I=k2MwJnyx(jb$Kq< z8`5!Y$y|K=i&Z-L-4prCwK5vsS%AOEOvQCCN8oQ2VYpu9flqqcaYN`8++elfMh|x( z?`dpn!QWrD;!}FFP3D_g+i`Q55gS)@~%Uh-)mflFPit@ONT$w%DlO0BmRBc+t^b667DO|;Qo?%_>Zh4 ze0k+G{O2;2P0m|0RYJxq$>DfF5sv?wBJiM>z=OB@@l|U-{=2&sUu$c{*PHva@}42R zMJJ=J;tak~)`D+tI*5l058zv?w&H(sw&2_I3-Fzo*YL=b@7d%%cLNsUQSW>_I+8DB zerzBMkN0HZf7_$5{bUq&RQucH|0F*3C%9}K!mhJ2I~3R_@C5d$*)Q9Luk8~&!Lp0GpQ+X+^Zv&5cw)m&9B_E2OpCz1Mfjm@Mfl;3 zOYx+FrFe2~3J%Ij!H>)d!BZkbaPW*|tvpQi9>*cBQ*p@6V4X~a_Ko4NbEEjt)0c4g z@r!s`RWqKxAwaf^$2M2t8B1>9h}TcqVA zC!FjRhEqZZZ1Rv|wc|Ns9XPekg6H-g!z%r_PA29xeu$qgGvoQ6YjIkk5icm+p_P5l z- z&bkfep9)t3^H1Gy2lG#N`~&kZDSrX;FC}t*0O`A2`k4VlUvYR1=3foH3g%x^I1A=q zH{A~A-(Xk|=HC>Z3FhB?FcHkZ^>1qfNdN5v#bExOd(*-EyDKLYfW+_Zs|54!cNT&9 z59URK`42Ng!2CybwqX8aPctz8Nt`^G|KgL_2ax_(K%ax?e>-Hr{Qt}UKLCaW1H<%x zA3zji`@;ty+C{&t07SdGI46MV&nrGKF@hm83zPxjLP%C7RyGLy|9`y|$c~*G7+L=R zU%h~V1I*?DlL8=;LFE7c;|CZee0)O~oLzu87>L7xI3R?<707l4ig5uMra*>{ud$wy Po`H_9p`o6ko&gsCE#d-; diff --git a/src/cctz/testdata/zoneinfo/US/Eastern b/src/cctz/testdata/zoneinfo/US/Eastern deleted file mode 100644 index 2b6c2eea14df07392729ae9f5712a44ec4f02bae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1744 zcmb8vc~FdD90%~HLuD)FSXb_AZECl}O63S8VJF8nxh5}Dn&pq)VT2iS6v+%R8pbh8 zbU9ZSR%{`w$+%iaIr5f-h*vpM?0TNB|CxR}&wlswdw;)Y|Jv0o(ys6$|1BFj!450U z|5x;MtP4H8th8e6#JwzaIfHnX$F6+fSRUU&;LO8!;S+K7@X6%&0(+jd@;sca%Ej}X z`IRE;=StJyJpZ$Bo+TUer+e;!PuHfxXIgpqtWgV}GtYz1>t@0F!m;p$ByTwX=vNYrz$W!Zp51fXEeNjgj)5!MqB+*D zbPa(ks{`RXJ4Lu^_}9P5bzslDwn1d`k3wF;kE2ZRlOd(>Q&k>ZO)}vc=`OfNNQR$T za(TA@yetlWQJV(8JhhEu{aWKH_*GggEa=p5opw50pQMCeM~sFWV!Fd`q7?$$Zw&Vq zS-uT$hu_KE;P<^-;3kJJaMSlk@P|e-{PD>}xY<+;e=0R|?4Hm1DxRfytQh{1UIe#n zJ_xra9Du(r-2i`!Tn~SrycqtWTm-j`UMH}7e!5M7+npA|?QIK0*6(;14F9SQf`3;G zge{i`z}8%=Kz}2I9JGimY*On4mbU8z*p9bw%=X-Go@JLg0>{!JY zr4e$tcc2U0NA3*w9VX`pt$t3;aDQ88xPOa;XMK;lW_ZBEkMO|j_u)bL_u#>q`S6fL zg8iXe_rt@Y>fzxl^#Y+aLRAiroVgDkCC!0lo@-#4g)lg6$>Lk^yyC96CnDM z@|OZIo#<%+qObNAdoVIFGP5wU{{NrD#J~U~BN$lz|F6nm%jrfD_Iu{Og$fkDtD77dK1QjsA+v7UaF8NS4P$$W^) zg0cs<5kwND1!4xJl|&RlGc=cf+N^9?x}WBQscqf!?bY!9IQN{-`JH=Ten0mi&+!7b z;*#(Q3R>=!j~wA+NjwY*zN%$$Kjqdt7B6Mrlivbm|AkaIaBCQTdod38=gz_XH7b$j z1}X*^<-zQC@W;X~c!;&bA$k=U^W^ z^{Nk^?uiI=Ppm!cr7Zeh!ZVj&z;j0%;f47Vm|u)KaeisY3IBPW562(p!->0Ek-iVR zsYQ}B#$f5W7%V%b5vY*YqiSA}ji(Y$KUf0moh5L_4kNra&j=fGiUle% zlb2wlG!r(?8obn47g>bY2N&QC&qra?!x12 z58lu()!iYHCldGkEE%;1yN-62zR%@myB$0Z@TlTZ?q+4YR`W&?e_?TLw-#7!7MI;_ IwOeiKzt^*oeEd=SfEud|~LmP<>G3sVCKvOnOG$C<=8o@`R zQ3D%dLPXGDTp+k23c*Lv#6(3F;3GP+FvN&X#FbUYdq4gFHlE43XMXp7cUB`Gj5Ygc z$uhA7Z(j1!SL#_TiM8Ee)iLTg#AkPT7xDT0ysq;3I``+|RN@-0`0H?K3*xw{^bh;CEG|a-eErS}d+8lTS=ha<>w`AOc zov!1s^Y3Go=R~0a7C+pCU0;ge{IPSedrDSVjJEc~VCh~VT+p@)_H^1|Z#1g&obT8# z*k4@>Z`=DG4mk7SLf;r%l$;6|XTQ~mRq^NVa7p|DTskocm%ZzO%Ll)yJh%P+DY)YD zE4cF75xDB;FubGvq{3pfb59o>Y&;By3R>ZCC8=oJZ_0zH^-t z4P)dkr5MK3ag!CR4Qu-Dh)ltKGKG2XXI;-aB$L240_?>d@k>6*ITiC{kFCT$_~lcinouj~eRN)v*ol1BtKpZeGUPrs^%XP$WA z^j$YBUo)`JBjl1^U`cT<%@R=_oq;nB>O^K$us~utvvyi!IjcGatLEg)8Y;y8vQxL= zqFpjvy#EY&1)-G5r>Wi8}n}UAzZg-}wcu>OKiqA9w+82zQIDv2jNX-qd&;_S!DMKJPx*_v4YE zRQ!1|RR7Aqt^bl`xu=WJ-}y#Fp`x`!G^lyJh3)z%dAeT N-QssRtPZQ4`wbnj4)_27 diff --git a/src/cctz/testdata/zoneinfo/US/Pacific b/src/cctz/testdata/zoneinfo/US/Pacific deleted file mode 100644 index aaf07787ad92b65eadae63b64bba290f9f961507..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1294 zcmci9*H2Sn9LDieD5GT^k!3}#fRvU}+Ol293PTAX6-Nw;QA|w?AV~B=#E63!iUt?{e^uDUh_zbTc#Chy5ydf$}g%hG-_ z7wo2OE3Uy@hxsMi*~H;~SN9$GbM*tXyYU?QrSu}&Q>jP4>T}WFqRr^H#I5M}%mDO< zJQ(eZPh#os^*g7b12W}8$Ai#88^?v3T+yF>W9U%*6gu2uLPrek=xFT-N8dM=*8u-2 z{{WAlY(^(?9-)(aZlk|bE~9@U&!AI*h3K^3EtbA##%TvUYg+=(PM?<2^SOa+c)slb z{P$G?Yr>C<-P8(r^yXo(L4jMte=KgRdvGB zLVqb4XI7tj4tr%dz}|;CSbFXgG77IrdItNteuQO;N?2wdHj*($E-r@U-S1(=;6B*D zu^v{o7IAbgpt1s1J>Clk79EAv716Nf;3X*;W3>4`a8P^!9Gq?qhsZMEQ0)L5W)lvF zds?yNF($lU0!PgC!)sgS;dPy_;q`SMMl!~1Xt)n=ET4rVub07_a=PHCl4_35MW-~v zG5asTv4KW7F7_}SH_{J~iCI}~o%H$xGR;5-ZYcwj2N-h2ezA3}w diff --git a/src/cctz/testdata/zoneinfo/US/Samoa b/src/cctz/testdata/zoneinfo/US/Samoa deleted file mode 100644 index 001289ceecff85fe0d0f376a6bc394329445f13f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 146 zcmWHE%1kq2AP5+NDnJ+nLI`VN0xDw$VvhenkY{@WOiyI}&A|wi*;v8A@c)1O4-lCe Uz`)|;8^RDA9Kyf_Bn%C?07{q{2><{9 diff --git a/src/cctz/testdata/zoneinfo/UTC b/src/cctz/testdata/zoneinfo/UTC deleted file mode 100644 index 00841a62213e6cccf7f0b7353e5e8ae214185486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S diff --git a/src/cctz/testdata/zoneinfo/Universal b/src/cctz/testdata/zoneinfo/Universal deleted file mode 100644 index 00841a62213e6cccf7f0b7353e5e8ae214185486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S diff --git a/src/cctz/testdata/zoneinfo/W-SU b/src/cctz/testdata/zoneinfo/W-SU deleted file mode 100644 index 5e6b6de6451b4408fb71ef73950712a0827d49a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 908 zcmajdT}V@57zgm@xShFX^l`D=a$DNkW>agVF@uYTw)B#{Vp^Ff_g^s%Jj%UfhmShojppzDoJYKKzu?b64|_9x5IOUqcb4-l z3Z!6gRAIBLPUc|9Kf&HHpC}sAp+DwO6Wo88wRVcL$?O?>$F8x=C~UbgpMdi#bFAg- z3cR=G!wToM(^ruzrZNT2w!4GSe*FS;Tsi~So$rE`z58L+;V4`m+XkJ%YPg}+3SBl6 zbeAnakL*eE{+=HeSpB6u#d%}jv!d_k(f7Xi25Tl~U~Tpdth@FUZc0CZo6lyTuWJz2 zADJrfe*V)#upu-8x9sbOjrJ7W>OWNU_c7R1(U;_PO&=r3frSp_?N8juJMux~;Aj|z z9y?(3fD5(^6I8lO;m)+J!29h|XOY9l{~$+PuaVX8C*-Jn54qL(9JzJw72K`M7JWMo z_k13JZTBz3*!1lr?;pQ%3R#QUJ0)F-PG6#z4RWb$FdBr5u4VskFP>;J5IF;Ug1GC6 z>Mu%0@qCV-TZW|N;!7#gY9g?>D4-@p|eEkI6G#R8}8#GCSkxFI6)HF>awim{rG!4pH zjAkS6&?xfAD}+?!6(J%k38{3?_x{s=+&gDK=lA=bb9VRctnlb5e@kk~i$$*>gIvO; zx5UuPR?>sJNMFZybM%Pu!!cpRB*(Ks@NX^Z_8FKTWPpA_ z@GV$)SRNKzI>8dvI>yCPSUM?%Wp%|e@;RTEJc2J$ywNYeABnmmQ3hXL3WSvbUa-pJ z5Uk$A4kG(&b_h_v+IbJwdSszr+t~-}<=Pmhc(7r>M@IHF7P&Hxr}dNib(kY#H}gE2 z60DIoRXLs@d2_G?d2>xU&S?qNMBb8h68$%>BF2nVo_vv*oYN}_g?;h< zus_@#ehNMa2YhVdpsNY|ypIcqEIDvk{|_AD8uQ3`UzBth7nI=W*l#%2H37di^uqCH zEpS3w0ly{Y!O2JolwH09r%sFDci$W_Ie*$s41d_g!5OP?_>+GD&T9CLTun_KO?9v)Pfq$`_)Lk#_AX9wfvqiQfq27 z!*z1yjMKSLYcLgRx5q=BstCv}%c01nnSJXeMfe<{@QJ z;Fk?8ygJpW6|Cjoa`f8&$8vYdFSSsfjhnT&IO|Kksfrp)o=7RsPnE|~CLKy0b4@2_ nA?0rGMqbFED?55(M>>jhOF%MHXDhR9W&(2yQ)deSnJNAQHdoT( diff --git a/src/cctz/testdata/zoneinfo/Zulu b/src/cctz/testdata/zoneinfo/Zulu deleted file mode 100644 index 00841a62213e6cccf7f0b7353e5e8ae214185486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 jcmWHE%1kq2AP5+NDnJ+nLWtMG0?`o~;>^GWBn-F!C&C4S diff --git a/src/cctz/testdata/zoneinfo/iso3166.tab b/src/cctz/testdata/zoneinfo/iso3166.tab deleted file mode 100644 index 4ae35234b..000000000 --- a/src/cctz/testdata/zoneinfo/iso3166.tab +++ /dev/null @@ -1,279 +0,0 @@ -# ISO 3166 alpha-2 country codes -# -# This file is in the public domain, so clarified as of -# 2009-05-17 by Arthur David Olson. -# -# From Paul Eggert (2025-07-01): -# This file contains a table of two-letter country codes. Columns are -# separated by a single tab. Lines beginning with ‘#’ are comments. -# All text uses UTF-8 encoding. The columns of the table are as follows: -# -# 1. ISO 3166-1 alpha-2 country code, current as of -# ISO/TC 46 N1127 (2024-02-29). See: ISO/TC 46 Documents -# https://www.iso.org/committee/48750.html?view=documents -# 2. The usual English name for the coded region. This sometimes -# departs from ISO-listed names, sometimes so that sorted subsets -# of names are useful (e.g., “Samoa (American)” and “Samoa -# (western)” rather than “American Samoa” and “Samoa”), -# sometimes to avoid confusion among non-experts (e.g., -# “Czech Republic” and “Turkey” rather than “Czechia” and “Türkiye”), -# and sometimes to omit needless detail or churn (e.g., “Netherlands” -# rather than “Netherlands (the)” or “Netherlands (Kingdom of the)”). -# -# The table is sorted by country code. -# -# This table is intended as an aid for users, to help them select time -# zone data appropriate for their practical needs. It is not intended -# to take or endorse any position on legal or territorial claims. -# -#country- -#code name of country, territory, area, or subdivision -AD Andorra -AE United Arab Emirates -AF Afghanistan -AG Antigua & Barbuda -AI Anguilla -AL Albania -AM Armenia -AO Angola -AQ Antarctica -AR Argentina -AS Samoa (American) -AT Austria -AU Australia -AW Aruba -AX Åland Islands -AZ Azerbaijan -BA Bosnia & Herzegovina -BB Barbados -BD Bangladesh -BE Belgium -BF Burkina Faso -BG Bulgaria -BH Bahrain -BI Burundi -BJ Benin -BL St Barthelemy -BM Bermuda -BN Brunei -BO Bolivia -BQ Caribbean NL -BR Brazil -BS Bahamas -BT Bhutan -BV Bouvet Island -BW Botswana -BY Belarus -BZ Belize -CA Canada -CC Cocos (Keeling) Islands -CD Congo (Dem. Rep.) -CF Central African Rep. -CG Congo (Rep.) -CH Switzerland -CI Côte d’Ivoire -CK Cook Islands -CL Chile -CM Cameroon -CN China -CO Colombia -CR Costa Rica -CU Cuba -CV Cape Verde -CW Curaçao -CX Christmas Island -CY Cyprus -CZ Czech Republic -DE Germany -DJ Djibouti -DK Denmark -DM Dominica -DO Dominican Republic -DZ Algeria -EC Ecuador -EE Estonia -EG Egypt -EH Western Sahara -ER Eritrea -ES Spain -ET Ethiopia -FI Finland -FJ Fiji -FK Falkland Islands -FM Micronesia -FO Faroe Islands -FR France -GA Gabon -GB Britain (UK) -GD Grenada -GE Georgia -GF French Guiana -GG Guernsey -GH Ghana -GI Gibraltar -GL Greenland -GM Gambia -GN Guinea -GP Guadeloupe -GQ Equatorial Guinea -GR Greece -GS South Georgia & the South Sandwich Islands -GT Guatemala -GU Guam -GW Guinea-Bissau -GY Guyana -HK Hong Kong -HM Heard Island & McDonald Islands -HN Honduras -HR Croatia -HT Haiti -HU Hungary -ID Indonesia -IE Ireland -IL Israel -IM Isle of Man -IN India -IO British Indian Ocean Territory -IQ Iraq -IR Iran -IS Iceland -IT Italy -JE Jersey -JM Jamaica -JO Jordan -JP Japan -KE Kenya -KG Kyrgyzstan -KH Cambodia -KI Kiribati -KM Comoros -KN St Kitts & Nevis -KP Korea (North) -KR Korea (South) -KW Kuwait -KY Cayman Islands -KZ Kazakhstan -LA Laos -LB Lebanon -LC St Lucia -LI Liechtenstein -LK Sri Lanka -LR Liberia -LS Lesotho -LT Lithuania -LU Luxembourg -LV Latvia -LY Libya -MA Morocco -MC Monaco -MD Moldova -ME Montenegro -MF St Martin (French) -MG Madagascar -MH Marshall Islands -MK North Macedonia -ML Mali -MM Myanmar (Burma) -MN Mongolia -MO Macau -MP Northern Mariana Islands -MQ Martinique -MR Mauritania -MS Montserrat -MT Malta -MU Mauritius -MV Maldives -MW Malawi -MX Mexico -MY Malaysia -MZ Mozambique -NA Namibia -NC New Caledonia -NE Niger -NF Norfolk Island -NG Nigeria -NI Nicaragua -NL Netherlands -NO Norway -NP Nepal -NR Nauru -NU Niue -NZ New Zealand -OM Oman -PA Panama -PE Peru -PF French Polynesia -PG Papua New Guinea -PH Philippines -PK Pakistan -PL Poland -PM St Pierre & Miquelon -PN Pitcairn -PR Puerto Rico -PS Palestine -PT Portugal -PW Palau -PY Paraguay -QA Qatar -RE Réunion -RO Romania -RS Serbia -RU Russia -RW Rwanda -SA Saudi Arabia -SB Solomon Islands -SC Seychelles -SD Sudan -SE Sweden -SG Singapore -SH St Helena -SI Slovenia -SJ Svalbard & Jan Mayen -SK Slovakia -SL Sierra Leone -SM San Marino -SN Senegal -SO Somalia -SR Suriname -SS South Sudan -ST Sao Tome & Principe -SV El Salvador -SX St Maarten (Dutch) -SY Syria -SZ Eswatini (Swaziland) -TC Turks & Caicos Is -TD Chad -TF French S. Terr. -TG Togo -TH Thailand -TJ Tajikistan -TK Tokelau -TL East Timor -TM Turkmenistan -TN Tunisia -TO Tonga -TR Turkey -TT Trinidad & Tobago -TV Tuvalu -TW Taiwan -TZ Tanzania -UA Ukraine -UG Uganda -UM US minor outlying islands -US United States -UY Uruguay -UZ Uzbekistan -VA Vatican City -VC St Vincent -VE Venezuela -VG Virgin Islands (UK) -VI Virgin Islands (US) -VN Vietnam -VU Vanuatu -WF Wallis & Futuna -WS Samoa (western) -YE Yemen -YT Mayotte -ZA South Africa -ZM Zambia -ZW Zimbabwe diff --git a/src/cctz/testdata/zoneinfo/zone1970.tab b/src/cctz/testdata/zoneinfo/zone1970.tab deleted file mode 100644 index cd43e3d2e..000000000 --- a/src/cctz/testdata/zoneinfo/zone1970.tab +++ /dev/null @@ -1,375 +0,0 @@ -# tzdb timezone descriptions -# -# This file is in the public domain. -# -# From Paul Eggert (2025-05-15): -# This file contains a table where each row stands for a timezone where -# civil timestamps have agreed since 1970. Columns are separated by -# a single tab. Lines beginning with ‘#’ are comments. All text uses -# UTF-8 encoding. The columns of the table are as follows: -# -# 1. The countries that overlap the timezone, as a comma-separated list -# of ISO 3166 2-character country codes. -# 2. Latitude and longitude of the timezone’s principal location -# in ISO 6709 sign-degrees-minutes-seconds format, -# either ±DDMM±DDDMM or ±DDMMSS±DDDMMSS, -# first latitude (+ is north), then longitude (+ is east). -# 3. Timezone name used in value of TZ environment variable. -# Please see the theory.html file for how these names are chosen. -# If multiple timezones overlap a country, each has a row in the -# table, with each column 1 containing the country code. -# 4. Comments; present if and only if countries have multiple timezones, -# and useful only for those countries. For example, the comments -# for the row with countries CH,DE,LI and name Europe/Zurich -# are useful only for DE, since CH and LI have no other timezones. -# -# If a timezone covers multiple countries, the most-populous city is used, -# and that country is listed first in column 1; any other countries -# are listed alphabetically by country code. The table is sorted -# first by country code, then (if possible) by an order within the -# country that (1) makes some geographical sense, and (2) puts the -# most populous timezones first, where that does not contradict (1). -# -# This table is intended as an aid for users, to help them select timezones -# appropriate for their practical needs. It is not intended to take or -# endorse any position on legal or territorial claims. -# -#country- -#codes coordinates TZ comments -AD +4230+00131 Europe/Andorra -AE,OM,RE,SC,TF +2518+05518 Asia/Dubai Crozet -AF +3431+06912 Asia/Kabul -AL +4120+01950 Europe/Tirane -AM +4011+04430 Asia/Yerevan -AQ -6617+11031 Antarctica/Casey Casey -AQ -6835+07758 Antarctica/Davis Davis -AQ -6736+06253 Antarctica/Mawson Mawson -AQ -6448-06406 Antarctica/Palmer Palmer -AQ -6734-06808 Antarctica/Rothera Rothera -AQ -720041+0023206 Antarctica/Troll Troll -AQ -7824+10654 Antarctica/Vostok Vostok -AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF) -AR -3124-06411 America/Argentina/Cordoba most areas: CB, CC, CN, ER, FM, MN, SE, SF -AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN) -AR -2411-06518 America/Argentina/Jujuy Jujuy (JY) -AR -2649-06513 America/Argentina/Tucuman Tucumán (TM) -AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH) -AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR) -AR -3132-06831 America/Argentina/San_Juan San Juan (SJ) -AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ) -AR -3319-06621 America/Argentina/San_Luis San Luis (SL) -AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC) -AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF) -AS,UM -1416-17042 Pacific/Pago_Pago Midway -AT +4813+01620 Europe/Vienna -AU -3133+15905 Australia/Lord_Howe Lord Howe Island -AU -5430+15857 Antarctica/Macquarie Macquarie Island -AU -4253+14719 Australia/Hobart Tasmania -AU -3749+14458 Australia/Melbourne Victoria -AU -3352+15113 Australia/Sydney New South Wales (most areas) -AU -3157+14127 Australia/Broken_Hill New South Wales (Yancowinna) -AU -2728+15302 Australia/Brisbane Queensland (most areas) -AU -2016+14900 Australia/Lindeman Queensland (Whitsunday Islands) -AU -3455+13835 Australia/Adelaide South Australia -AU -1228+13050 Australia/Darwin Northern Territory -AU -3157+11551 Australia/Perth Western Australia (most areas) -AU -3143+12852 Australia/Eucla Western Australia (Eucla) -AZ +4023+04951 Asia/Baku -BB +1306-05937 America/Barbados -BD +2343+09025 Asia/Dhaka -BE,LU,NL +5050+00420 Europe/Brussels -BG +4241+02319 Europe/Sofia -BM +3217-06446 Atlantic/Bermuda -BO -1630-06809 America/La_Paz -BR -0351-03225 America/Noronha Atlantic islands -BR -0127-04829 America/Belem Pará (east), Amapá -BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB) -BR -0803-03454 America/Recife Pernambuco -BR -0712-04812 America/Araguaina Tocantins -BR -0940-03543 America/Maceio Alagoas, Sergipe -BR -1259-03831 America/Bahia Bahia -BR -2332-04637 America/Sao_Paulo Brazil (southeast: GO, DF, MG, ES, RJ, SP, PR, SC, RS) -BR -2027-05437 America/Campo_Grande Mato Grosso do Sul -BR -1535-05605 America/Cuiaba Mato Grosso -BR -0226-05452 America/Santarem Pará (west) -BR -0846-06354 America/Porto_Velho Rondônia -BR +0249-06040 America/Boa_Vista Roraima -BR -0308-06001 America/Manaus Amazonas (east) -BR -0640-06952 America/Eirunepe Amazonas (west) -BR -0958-06748 America/Rio_Branco Acre -BT +2728+08939 Asia/Thimphu -BY +5354+02734 Europe/Minsk -BZ +1730-08812 America/Belize -CA +4734-05243 America/St_Johns Newfoundland, Labrador (SE) -CA +4439-06336 America/Halifax Atlantic - NS (most areas), PE -CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton) -CA +4606-06447 America/Moncton Atlantic - New Brunswick -CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas) -CA,BS +4339-07923 America/Toronto Eastern - ON & QC (most areas) -CA +6344-06828 America/Iqaluit Eastern - NU (most areas) -CA +4953-09709 America/Winnipeg Central - ON (west), Manitoba -CA +744144-0944945 America/Resolute Central - NU (Resolute) -CA +624900-0920459 America/Rankin_Inlet Central - NU (central) -CA +5024-10439 America/Regina CST - SK (most areas) -CA +5017-10750 America/Swift_Current CST - SK (midwest) -CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W) -CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west) -CA +682059-1334300 America/Inuvik Mountain - NT (west) -CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John) -CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson) -CA +6043-13503 America/Whitehorse MST - Yukon (east) -CA +6404-13925 America/Dawson MST - Yukon (west) -CA +4916-12307 America/Vancouver Pacific - BC (most areas) -CH,DE,LI +4723+00832 Europe/Zurich Büsingen -CI,BF,GH,GM,GN,IS,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan -CK -2114-15946 Pacific/Rarotonga -CL -3327-07040 America/Santiago most of Chile -CL -4534-07204 America/Coyhaique Aysén Region -CL -5309-07055 America/Punta_Arenas Magallanes Region -CL -2709-10926 Pacific/Easter Easter Island -CN +3114+12128 Asia/Shanghai Beijing Time -CN +4348+08735 Asia/Urumqi Xinjiang Time -CO +0436-07405 America/Bogota -CR +0956-08405 America/Costa_Rica -CU +2308-08222 America/Havana -CV +1455-02331 Atlantic/Cape_Verde -CY +3510+03322 Asia/Nicosia most of Cyprus -CY +3507+03357 Asia/Famagusta Northern Cyprus -CZ,SK +5005+01426 Europe/Prague -DE,DK,NO,SE,SJ +5230+01322 Europe/Berlin most of Germany -DO +1828-06954 America/Santo_Domingo -DZ +3647+00303 Africa/Algiers -EC -0210-07950 America/Guayaquil Ecuador (mainland) -EC -0054-08936 Pacific/Galapagos Galápagos Islands -EE +5925+02445 Europe/Tallinn -EG +3003+03115 Africa/Cairo -EH +2709-01312 Africa/El_Aaiun -ES +4024-00341 Europe/Madrid Spain (mainland) -ES +3553-00519 Africa/Ceuta Ceuta, Melilla -ES +2806-01524 Atlantic/Canary Canary Islands -FI,AX +6010+02458 Europe/Helsinki -FJ -1808+17825 Pacific/Fiji -FK -5142-05751 Atlantic/Stanley -FM +0519+16259 Pacific/Kosrae Kosrae -FO +6201-00646 Atlantic/Faroe -FR,MC +4852+00220 Europe/Paris -GB,GG,IM,JE +513030-0000731 Europe/London -GE +4143+04449 Asia/Tbilisi -GF +0456-05220 America/Cayenne -GI +3608-00521 Europe/Gibraltar -GL +6411-05144 America/Nuuk most of Greenland -GL +7646-01840 America/Danmarkshavn National Park (east coast) -GL +7029-02158 America/Scoresbysund Scoresbysund/Ittoqqortoormiit -GL +7634-06847 America/Thule Thule/Pituffik -GR +3758+02343 Europe/Athens -GS -5416-03632 Atlantic/South_Georgia -GT +1438-09031 America/Guatemala -GU,MP +1328+14445 Pacific/Guam -GW +1151-01535 Africa/Bissau -GY +0648-05810 America/Guyana -HK +2217+11409 Asia/Hong_Kong -HN +1406-08713 America/Tegucigalpa -HT +1832-07220 America/Port-au-Prince -HU +4730+01905 Europe/Budapest -ID -0610+10648 Asia/Jakarta Java, Sumatra -ID -0002+10920 Asia/Pontianak Borneo (west, central) -ID -0507+11924 Asia/Makassar Borneo (east, south), Sulawesi/Celebes, Bali, Nusa Tengarra, Timor (west) -ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya), Malukus/Moluccas -IE +5320-00615 Europe/Dublin -IL +314650+0351326 Asia/Jerusalem -IN +2232+08822 Asia/Kolkata -IO -0720+07225 Indian/Chagos -IQ +3321+04425 Asia/Baghdad -IR +3540+05126 Asia/Tehran -IT,SM,VA +4154+01229 Europe/Rome -JM +175805-0764736 America/Jamaica -JO +3157+03556 Asia/Amman -JP,AU +353916+1394441 Asia/Tokyo Eyre Bird Observatory -KE,DJ,ER,ET,KM,MG,SO,TZ,UG,YT -0117+03649 Africa/Nairobi -KG +4254+07436 Asia/Bishkek -KI,MH,TV,UM,WF +0125+17300 Pacific/Tarawa Gilberts, Marshalls, Wake -KI -0247-17143 Pacific/Kanton Phoenix Islands -KI +0152-15720 Pacific/Kiritimati Line Islands -KP +3901+12545 Asia/Pyongyang -KR +3733+12658 Asia/Seoul -KZ +4315+07657 Asia/Almaty most of Kazakhstan -KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda -KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay -KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe -KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau -KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur’yev -KZ +5113+05121 Asia/Oral West Kazakhstan -LB +3353+03530 Asia/Beirut -LK +0656+07951 Asia/Colombo -LR +0618-01047 Africa/Monrovia -LT +5441+02519 Europe/Vilnius -LV +5657+02406 Europe/Riga -LY +3254+01311 Africa/Tripoli -MA +3339-00735 Africa/Casablanca -MD +4700+02850 Europe/Chisinau -MH +0905+16720 Pacific/Kwajalein Kwajalein -MM,CC +1647+09610 Asia/Yangon -MN +4755+10653 Asia/Ulaanbaatar most of Mongolia -MN +4801+09139 Asia/Hovd Bayan-Ölgii, Hovd, Uvs -MO +221150+1133230 Asia/Macau -MQ +1436-06105 America/Martinique -MT +3554+01431 Europe/Malta -MU -2010+05730 Indian/Mauritius -MV,TF +0410+07330 Indian/Maldives Kerguelen, St Paul I, Amsterdam I -MX +1924-09909 America/Mexico_City Central Mexico -MX +2105-08646 America/Cancun Quintana Roo -MX +2058-08937 America/Merida Campeche, Yucatán -MX +2540-10019 America/Monterrey Durango; Coahuila, Nuevo León, Tamaulipas (most areas) -MX +2550-09730 America/Matamoros Coahuila, Nuevo León, Tamaulipas (US border) -MX +2838-10605 America/Chihuahua Chihuahua (most areas) -MX +3144-10629 America/Ciudad_Juarez Chihuahua (US border - west) -MX +2934-10425 America/Ojinaga Chihuahua (US border - east) -MX +2313-10625 America/Mazatlan Baja California Sur, Nayarit (most areas), Sinaloa -MX +2048-10515 America/Bahia_Banderas Bahía de Banderas -MX +2904-11058 America/Hermosillo Sonora -MX +3232-11701 America/Tijuana Baja California -MY,BN +0133+11020 Asia/Kuching Sabah, Sarawak -MZ,BI,BW,CD,MW,RW,ZM,ZW -2558+03235 Africa/Maputo Central Africa Time -NA -2234+01706 Africa/Windhoek -NC -2216+16627 Pacific/Noumea -NF -2903+16758 Pacific/Norfolk -NG,AO,BJ,CD,CF,CG,CM,GA,GQ,NE +0627+00324 Africa/Lagos West Africa Time -NI +1209-08617 America/Managua -NP +2743+08519 Asia/Kathmandu -NR -0031+16655 Pacific/Nauru -NU -1901-16955 Pacific/Niue -NZ,AQ -3652+17446 Pacific/Auckland New Zealand time -NZ -4357-17633 Pacific/Chatham Chatham Islands -PA,CA,KY +0858-07932 America/Panama EST - ON (Atikokan), NU (Coral H) -PE -1203-07703 America/Lima -PF -1732-14934 Pacific/Tahiti Society Islands -PF -0900-13930 Pacific/Marquesas Marquesas Islands -PF -2308-13457 Pacific/Gambier Gambier Islands -PG,AQ,FM -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas), Chuuk, Yap, Dumont d’Urville -PG -0613+15534 Pacific/Bougainville Bougainville -PH +143512+1205804 Asia/Manila -PK +2452+06703 Asia/Karachi -PL +5215+02100 Europe/Warsaw -PM +4703-05620 America/Miquelon -PN -2504-13005 Pacific/Pitcairn -PR,AG,CA,AI,AW,BL,BQ,CW,DM,GD,GP,KN,LC,MF,MS,SX,TT,VC,VG,VI +182806-0660622 America/Puerto_Rico AST - QC (Lower North Shore) -PS +3130+03428 Asia/Gaza Gaza Strip -PS +313200+0350542 Asia/Hebron West Bank -PT +3843-00908 Europe/Lisbon Portugal (mainland) -PT +3238-01654 Atlantic/Madeira Madeira Islands -PT +3744-02540 Atlantic/Azores Azores -PW +0720+13429 Pacific/Palau -PY -2516-05740 America/Asuncion -QA,BH +2517+05132 Asia/Qatar -RO +4426+02606 Europe/Bucharest -RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade -RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad -RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area -# Mention RU and UA alphabetically. See “territorial claims” above. -RU,UA +4457+03406 Europe/Simferopol Crimea -RU +5836+04939 Europe/Kirov MSK+00 - Kirov -RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd -RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan -RU +5134+04602 Europe/Saratov MSK+01 - Saratov -RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk -RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia -RU +5651+06036 Asia/Yekaterinburg MSK+02 - Urals -RU +5500+07324 Asia/Omsk MSK+03 - Omsk -RU +5502+08255 Asia/Novosibirsk MSK+04 - Novosibirsk -RU +5322+08345 Asia/Barnaul MSK+04 - Altai -RU +5630+08458 Asia/Tomsk MSK+04 - Tomsk -RU +5345+08707 Asia/Novokuznetsk MSK+04 - Kemerovo -RU +5601+09250 Asia/Krasnoyarsk MSK+04 - Krasnoyarsk area -RU +5216+10420 Asia/Irkutsk MSK+05 - Irkutsk, Buryatia -RU +5203+11328 Asia/Chita MSK+06 - Zabaykalsky -RU +6200+12940 Asia/Yakutsk MSK+06 - Lena River -RU +623923+1353314 Asia/Khandyga MSK+06 - Tomponsky, Ust-Maysky -RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River -RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky -RU +5934+15048 Asia/Magadan MSK+08 - Magadan -RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island -RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E), N Kuril Is -RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka -RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea -SA,AQ,KW,YE +2438+04643 Asia/Riyadh Syowa -SB,FM -0932+16012 Pacific/Guadalcanal Pohnpei -SD +1536+03232 Africa/Khartoum -SG,AQ,MY +0117+10351 Asia/Singapore peninsular Malaysia, Concordia -SR +0550-05510 America/Paramaribo -SS +0451+03137 Africa/Juba -ST +0020+00644 Africa/Sao_Tome -SV +1342-08912 America/El_Salvador -SY +3330+03618 Asia/Damascus -TC +2128-07108 America/Grand_Turk -TD +1207+01503 Africa/Ndjamena -TH,CX,KH,LA,VN +1345+10031 Asia/Bangkok north Vietnam -TJ +3835+06848 Asia/Dushanbe -TK -0922-17114 Pacific/Fakaofo -TL -0833+12535 Asia/Dili -TM +3757+05823 Asia/Ashgabat -TN +3648+01011 Africa/Tunis -TO -210800-1751200 Pacific/Tongatapu -TR +4101+02858 Europe/Istanbul -TW +2503+12130 Asia/Taipei -UA +5026+03031 Europe/Kyiv most of Ukraine -US +404251-0740023 America/New_York Eastern (most areas) -US +421953-0830245 America/Detroit Eastern - MI (most areas) -US +381515-0854534 America/Kentucky/Louisville Eastern - KY (Louisville area) -US +364947-0845057 America/Kentucky/Monticello Eastern - KY (Wayne) -US +394606-0860929 America/Indiana/Indianapolis Eastern - IN (most areas) -US +384038-0873143 America/Indiana/Vincennes Eastern - IN (Da, Du, K, Mn) -US +410305-0863611 America/Indiana/Winamac Eastern - IN (Pulaski) -US +382232-0862041 America/Indiana/Marengo Eastern - IN (Crawford) -US +382931-0871643 America/Indiana/Petersburg Eastern - IN (Pike) -US +384452-0850402 America/Indiana/Vevay Eastern - IN (Switzerland) -US +415100-0873900 America/Chicago Central (most areas) -US +375711-0864541 America/Indiana/Tell_City Central - IN (Perry) -US +411745-0863730 America/Indiana/Knox Central - IN (Starke) -US +450628-0873651 America/Menominee Central - MI (Wisconsin border) -US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver) -US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural) -US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer) -US +394421-1045903 America/Denver Mountain (most areas) -US +433649-1161209 America/Boise Mountain - ID (south), OR (east) -US,CA +332654-1120424 America/Phoenix MST - AZ (most areas), Creston BC -US +340308-1181434 America/Los_Angeles Pacific -US +611305-1495401 America/Anchorage Alaska (most areas) -US +581807-1342511 America/Juneau Alaska - Juneau area -US +571035-1351807 America/Sitka Alaska - Sitka area -US +550737-1313435 America/Metlakatla Alaska - Annette Island -US +593249-1394338 America/Yakutat Alaska - Yakutat -US +643004-1652423 America/Nome Alaska (west) -US +515248-1763929 America/Adak Alaska - western Aleutians -US +211825-1575130 Pacific/Honolulu Hawaii -UY -345433-0561245 America/Montevideo -UZ +3940+06648 Asia/Samarkand Uzbekistan (west) -UZ +4120+06918 Asia/Tashkent Uzbekistan (east) -VE +1030-06656 America/Caracas -VN +1045+10640 Asia/Ho_Chi_Minh south Vietnam -VU -1740+16825 Pacific/Efate -WS -1350-17144 Pacific/Apia -ZA,LS,SZ -2615+02800 Africa/Johannesburg -# -# The next section contains experimental tab-separated comments for -# use by user agents like tzselect that identify continents and oceans. -# -# For example, the comment ‘#@AQAntarctica/’ means the country code -# AQ is in the continent Antarctica regardless of the Zone name, -# so Pacific/Auckland should be listed under Antarctica as well as -# under the Pacific because its line’s country codes include AQ. -# -# If more than one country code is affected each is listed separated -# by commas, e.g., ‘#@IS,SHAtlantic/’. If a country code is in -# more than one continent or ocean, each is listed separated by -# commas, e.g., the second column of ‘#@CY,TRAsia/,Europe/’. -# -# These experimental comments are present only for country codes where -# the continent or ocean is not already obvious from the Zone name. -# For example, there is no such comment for RU since it already -# corresponds to Zone names starting with both ‘Europe/’ and ‘Asia/’. -# -#@AQ Antarctica/ -#@IS,SH Atlantic/ -#@CY,TR Asia/,Europe/ -#@SJ Arctic/ -#@CC,CX,KM,MG,YT Indian/ diff --git a/src/cctz/testdata/zoneinfo/zonenow.tab b/src/cctz/testdata/zoneinfo/zonenow.tab deleted file mode 100644 index aa3a64f3d..000000000 --- a/src/cctz/testdata/zoneinfo/zonenow.tab +++ /dev/null @@ -1,293 +0,0 @@ -# tzdb timezone descriptions, for users who do not care about old timestamps -# -# This file is in the public domain. -# -# From Paul Eggert (2023-12-18): -# This file contains a table where each row stands for a timezone -# where civil timestamps are predicted to agree from now on. -# This file is like zone1970.tab (see zone1970.tab’s comments), -# but with the following changes: -# -# 1. Each timezone corresponds to a set of clocks that are planned -# to agree from now on. This is a larger set of clocks than in -# zone1970.tab, where each timezone’s clocks must agree from 1970 on. -# 2. The first column is irrelevant and ignored. -# 3. The table is sorted in a different way: -# first by standard time UTC offset; -# then, if DST is used, by daylight saving UTC offset; -# then by time zone abbreviation. -# 4. Every timezone has a nonempty comments column, with wording -# distinguishing the timezone only from other timezones with the -# same UTC offset at some point during the year. -# -# The format of this table is experimental, and may change in future versions. -# -# This table is intended as an aid for users, to help them select timezones -# appropriate for their practical needs. It is not intended to take or -# endorse any position on legal or territorial claims. -# -#XX coordinates TZ comments -# -# -11 - SST -XX -1416-17042 Pacific/Pago_Pago Midway; Samoa (SST) -# -# -11 -XX -1901-16955 Pacific/Niue Niue -# -# -10 - HST -XX +211825-1575130 Pacific/Honolulu Hawaii (HST) -# -# -10 -XX -1732-14934 Pacific/Tahiti Tahiti; Cook Islands -# -# -10/-09 - HST / HDT (North America DST) -XX +515248-1763929 America/Adak western Aleutians in Alaska (HST/HDT) -# -# -09:30 -XX -0900-13930 Pacific/Marquesas Marquesas -# -# -09 -XX -2308-13457 Pacific/Gambier Gambier -# -# -09/-08 - AKST/AKDT (North America DST) -XX +611305-1495401 America/Anchorage most of Alaska (AKST/AKDT) -# -# -08 -XX -2504-13005 Pacific/Pitcairn Pitcairn -# -# -08/-07 - PST/PDT (North America DST) -XX +340308-1181434 America/Los_Angeles Pacific (PST/PDT) - US & Canada; Mexico near US border -# -# -07 - MST -XX +332654-1120424 America/Phoenix Mountain Standard (MST) - Arizona; western Mexico; Yukon -# -# -07/-06 - MST/MDT (North America DST) -XX +394421-1045903 America/Denver Mountain (MST/MDT) - US & Canada; Mexico near US border -# -# -06 -XX -0054-08936 Pacific/Galapagos Galápagos -# -# -06 - CST -XX +1924-09909 America/Mexico_City Central Standard (CST) - Saskatchewan; central Mexico; Central America -# -# -06/-05 (Chile DST) -XX -2709-10926 Pacific/Easter Easter Island -# -# -06/-05 - CST/CDT (North America DST) -XX +415100-0873900 America/Chicago Central (CST/CDT) - US & Canada; Mexico near US border -# -# -05 -XX -1203-07703 America/Lima eastern South America -# -# -05 - EST -XX +175805-0764736 America/Jamaica Eastern Standard (EST) - Caymans; Jamaica; eastern Mexico; Panama -# -# -05/-04 - CST/CDT (Cuba DST) -XX +2308-08222 America/Havana Cuba -# -# -05/-04 - EST/EDT (North America DST) -XX +404251-0740023 America/New_York Eastern (EST/EDT) - US & Canada -# -# -04 -XX +1030-06656 America/Caracas western South America -# -# -04 - AST -XX +1828-06954 America/Santo_Domingo Atlantic Standard (AST) - eastern Caribbean -# -# -04/-03 (Chile DST) -XX -3327-07040 America/Santiago most of Chile -# -# -04/-03 - AST/ADT (North America DST) -XX +4439-06336 America/Halifax Atlantic (AST/ADT) - Canada; Bermuda -# -# -03:30/-02:30 - NST/NDT (North America DST) -XX +4734-05243 America/St_Johns Newfoundland (NST/NDT) -# -# -03 -XX -2332-04637 America/Sao_Paulo eastern and southern South America -# -# -03/-02 (North America DST) -XX +4703-05620 America/Miquelon St Pierre & Miquelon -# -# -02 -XX -0351-03225 America/Noronha Fernando de Noronha; South Georgia -# -# -02/-01 (EU DST) -XX +6411-05144 America/Nuuk most of Greenland -# -# -01 -XX +1455-02331 Atlantic/Cape_Verde Cape Verde -# -# -01/+00 (EU DST) -XX +3744-02540 Atlantic/Azores Azores -# -# +00 - GMT -XX +0519-00402 Africa/Abidjan far western Africa; Iceland (GMT) -# -# +00/+01 - GMT/BST (EU DST) -XX +513030-0000731 Europe/London United Kingdom (GMT/BST) -# -# +00/+01 - WET/WEST (EU DST) -XX +3843-00908 Europe/Lisbon western Europe (WET/WEST) -# -# +00/+02 - Troll DST -XX -720041+0023206 Antarctica/Troll Troll Station in Antarctica -# -# +01 - CET -XX +3647+00303 Africa/Algiers Algeria, Tunisia (CET) -# -# +01 - WAT -XX +0627+00324 Africa/Lagos western Africa (WAT) -# -# +01/+00 - IST/GMT (EU DST in reverse) -XX +5320-00615 Europe/Dublin Ireland (IST/GMT) -# -# +01/+00 - (Morocco DST) -XX +3339-00735 Africa/Casablanca Morocco -# -# +01/+02 - CET/CEST (EU DST) -XX +4852+00220 Europe/Paris central Europe (CET/CEST) -# -# +02 - CAT -XX -2558+03235 Africa/Maputo central Africa (CAT) -# -# +02 - EET -XX +3254+01311 Africa/Tripoli Libya; Kaliningrad (EET) -# -# +02 - SAST -XX -2615+02800 Africa/Johannesburg southern Africa (SAST) -# -# +02/+03 - EET/EEST (EU DST) -XX +3758+02343 Europe/Athens eastern Europe (EET/EEST) -# -# +02/+03 - EET/EEST (Egypt DST) -XX +3003+03115 Africa/Cairo Egypt -# -# +02/+03 - EET/EEST (Lebanon DST) -XX +3353+03530 Asia/Beirut Lebanon -# -# +02/+03 - EET/EEST (Palestine DST) -XX +3130+03428 Asia/Gaza Palestine -# -# +02/+03 - IST/IDT (Israel DST) -XX +314650+0351326 Asia/Jerusalem Israel -# -# +03 -XX +4101+02858 Europe/Istanbul Near East; Belarus -# -# +03 - EAT -XX -0117+03649 Africa/Nairobi eastern Africa (EAT) -# -# +03 - MSK -XX +554521+0373704 Europe/Moscow Moscow (MSK) -# -# +03:30 -XX +3540+05126 Asia/Tehran Iran -# -# +04 -XX +2518+05518 Asia/Dubai Russia; Caucasus; Persian Gulf; Seychelles; Réunion -# -# +04:30 -XX +3431+06912 Asia/Kabul Afghanistan -# -# +05 -XX +4120+06918 Asia/Tashkent Russia; Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives -# -# +05 - PKT -XX +2452+06703 Asia/Karachi Pakistan (PKT) -# -# +05:30 -XX +0656+07951 Asia/Colombo Sri Lanka -# -# +05:30 - IST -XX +2232+08822 Asia/Kolkata India (IST) -# -# +05:45 -XX +2743+08519 Asia/Kathmandu Nepal -# -# +06 -XX +2343+09025 Asia/Dhaka Russia; Kyrgyzstan; Bhutan; Bangladesh; Chagos -# -# +06:30 -XX +1647+09610 Asia/Yangon Myanmar; Cocos -# -# +07 -XX +1345+10031 Asia/Bangkok Russia; Indochina; Christmas Island -# -# +07 - WIB -XX -0610+10648 Asia/Jakarta Indonesia (WIB) -# -# +08 -XX +0117+10351 Asia/Singapore Russia; Brunei; Malaysia; Singapore; Concordia -# -# +08 - AWST -XX -3157+11551 Australia/Perth Western Australia (AWST) -# -# +08 - CST -XX +3114+12128 Asia/Shanghai China (CST) -# -# +08 - HKT -XX +2217+11409 Asia/Hong_Kong Hong Kong (HKT) -# -# +08 - PHT -XX +143512+1205804 Asia/Manila Philippines (PHT) -# -# +08 - WITA -XX -0507+11924 Asia/Makassar Indonesia (WITA) -# -# +08:45 -XX -3143+12852 Australia/Eucla Eucla -# -# +09 -XX +5203+11328 Asia/Chita Russia; Palau; East Timor -# -# +09 - JST -XX +353916+1394441 Asia/Tokyo Japan (JST); Eyre Bird Observatory -# -# +09 - KST -XX +3733+12658 Asia/Seoul Korea (KST) -# -# +09 - WIT -XX -0232+14042 Asia/Jayapura Indonesia (WIT) -# -# +09:30 - ACST -XX -1228+13050 Australia/Darwin Northern Territory (ACST) -# -# +09:30/+10:30 - ACST/ACDT (Australia DST) -XX -3455+13835 Australia/Adelaide South Australia (ACST/ACDT) -# -# +10 -XX +4310+13156 Asia/Vladivostok Russia; Yap; Chuuk; Papua New Guinea; Dumont d’Urville -# -# +10 - AEST -XX -2728+15302 Australia/Brisbane Queensland (AEST) -# -# +10 - ChST -XX +1328+14445 Pacific/Guam Mariana Islands (ChST) -# -# +10/+11 - AEST/AEDT (Australia DST) -XX -3352+15113 Australia/Sydney southeast Australia (AEST/AEDT) -# -# +10:30/+11 -XX -3133+15905 Australia/Lord_Howe Lord Howe Island -# -# +11 -XX -0613+15534 Pacific/Bougainville Russia; Kosrae; Bougainville; Solomons -# -# +11/+12 (Australia DST) -XX -2903+16758 Pacific/Norfolk Norfolk Island -# -# +12 -XX +5301+15839 Asia/Kamchatka Russia; Tuvalu; Fiji; etc. -# -# +12/+13 (New Zealand DST) -XX -3652+17446 Pacific/Auckland New Zealand (NZST/NZDT) -# -# +12:45/+13:45 (Chatham DST) -XX -4357-17633 Pacific/Chatham Chatham Islands -# -# +13 -XX -210800-1751200 Pacific/Tongatapu Kanton; Tokelau; Samoa (western); Tonga -# -# +14 -XX +0152-15720 Pacific/Kiritimati Kiritimati From 3d8b82188339d34add19c296a6e55176ad8882c1 Mon Sep 17 00:00:00 2001 From: Bruno Tremblay Date: Wed, 25 Mar 2026 14:29:00 -0400 Subject: [PATCH 4/6] Update cctz vendored lib From commit : 00fc77b843504f231f89c13eff86327c444094e8 --- src/cctz/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cctz/Makefile b/src/cctz/Makefile index 650496be1..13e32f1d7 100644 --- a/src/cctz/Makefile +++ b/src/cctz/Makefile @@ -41,8 +41,8 @@ DESTDIR ?= ## TEST_LIBS = ... VPATH = $(SRC)src:$(SRC)examples -CXXFLAGS += -g -Wall -I$(SRC)include -std=$(STD) \ - $(TEST_FLAGS) -fPIC -MMD +CPPFLAGS += -I$(SRC)include +override CXXFLAGS += -g -Wall -std=$(STD) $(TEST_FLAGS) $(CXXPICFLAGS) -MMD ARFLAGS = rcs LINK.o = $(LINK.cc) LDLIBS += $(TEST_LIBS) @@ -67,6 +67,10 @@ CCTZ_OBJS = \ time_zone_posix.o \ zone_info_source.o +ifeq ($(OS),Windows_NT) +CCTZ_OBJS += time_zone_name_win.o +endif + TOOLS = time_tool EXAMPLES = classic epoch_shift hello example1 example2 example3 example4 From a9d1820331f3e7d4e994f1bf91719f3ac9db139c Mon Sep 17 00:00:00 2001 From: Bruno Tremblay Date: Wed, 25 Mar 2026 15:28:48 -0400 Subject: [PATCH 5/6] News, document vendored lib in maintenance + add clear comments in vendored cctz source for odbc specific changes. --- MAINTENANCE.md | 30 ++++++++++++++++++++++++++++++ NEWS.md | 3 +++ src/cctz/Makefile | 4 ++++ src/cctz/src/time_zone_fixed.cc | 3 ++- src/cctz/src/time_zone_format.cc | 7 +++++-- 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/MAINTENANCE.md b/MAINTENANCE.md index b83ae9278..d1d7e0461 100644 --- a/MAINTENANCE.md +++ b/MAINTENANCE.md @@ -8,6 +8,36 @@ The "Developing odbc" vignette at `vignette("develop")` contains instructions on The hardest part of maintaining odbc is often an issue only occurs with a specific database, and setting up the environment for that database usually takes a non-trivial amount of time. +## Vendored cctz + +The vendored copy in `src/cctz` was last updated against `google/cctz` +commit `00fc77b843504f231f89c13eff86327c444094e8`. + +Relative to that upstream commit, the odbc package intentionally keeps the +following deltas for R package inclusion: + +- Upstream `.github/` is omitted from the vendored copy. +- Upstream `testdata/` is omitted from the vendored copy. +- `src/cctz/Makefile` is patched so recursive builds from `src/Makevars` keep + the cctz include path and PIC flags required for R shared-library builds. +- `src/cctz/Makefile` adds `time_zone_name_win.o` on Windows because upstream + now ships `src/time_zone_name_win.cc`, and omitting it breaks Windows + linking. +- `src/cctz/src/time_zone_fixed.cc` keeps odbc-specific fixed-offset zone names + based on `Etc/GMT` rather than upstream `Fixed/UTC`, matching odbc timestamp + offset behavior. +- `src/cctz/src/time_zone_fixed.cc` also retains local formatting behavior for + fixed offsets, including compact hour formatting, omission of zero + minute/second components, and a runtime error in place of the upstream + assert. +- `src/cctz/src/time_zone_format.cc` keeps historical odbc compatibility + patches for Windows/MinGW-era behavior: forcing `HAS_STRPTIME`, disabling the + `tm_year` saturation branch for large positive values, and bypassing the + `strptime()` call in `ParseTM()`. + +When updating cctz again, compare the vendored tree against upstream and carry +these deltas forward only if they are still required by odbc. + ## Future directions - Convert from using Rcpp to using cpp11. diff --git a/NEWS.md b/NEWS.md index 095e9462b..88e51a9e9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # odbc (development version) +* Update vendored cctz to current upstream, including local build compatibility + fixes retained for R package and Windows builds. + * SQL Server: Make it possible to write `POSIXct` data to `DATETIMEOFFSET` targets (#985). diff --git a/src/cctz/Makefile b/src/cctz/Makefile index 13e32f1d7..832380146 100644 --- a/src/cctz/Makefile +++ b/src/cctz/Makefile @@ -41,6 +41,9 @@ DESTDIR ?= ## TEST_LIBS = ... VPATH = $(SRC)src:$(SRC)examples +# package::odbc +# Preserve include flags and PIC flags when src/Makevars invokes +# this Makefile with command-line CXXFLAGS during R package builds. CPPFLAGS += -I$(SRC)include override CXXFLAGS += -g -Wall -std=$(STD) $(TEST_FLAGS) $(CXXPICFLAGS) -MMD ARFLAGS = rcs @@ -68,6 +71,7 @@ CCTZ_OBJS = \ zone_info_source.o ifeq ($(OS),Windows_NT) +# package:odbc Include the upstream Windows source added after prior vendoring. CCTZ_OBJS += time_zone_name_win.o endif diff --git a/src/cctz/src/time_zone_fixed.cc b/src/cctz/src/time_zone_fixed.cc index c6cd6154e..970bd61a9 100644 --- a/src/cctz/src/time_zone_fixed.cc +++ b/src/cctz/src/time_zone_fixed.cc @@ -25,7 +25,8 @@ namespace cctz { namespace { // The prefix used for the internal names of fixed-offset zones. -// package:odbc changed from "Fixed/UTC" +// package::odbc +// changed from "Fixed/UTC" const char kFixedZonePrefix[] = "Etc/GMT"; const char kDigits[] = "0123456789"; diff --git a/src/cctz/src/time_zone_format.cc b/src/cctz/src/time_zone_format.cc index eb618d4a7..e08244a33 100644 --- a/src/cctz/src/time_zone_format.cc +++ b/src/cctz/src/time_zone_format.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -# define HAS_STRPTIME 1 // assume everyone has strptime() +# define HAS_STRPTIME 1 // package::odbc assume everyone has strptime() #if !defined(HAS_STRPTIME) # if defined(_MSC_VER) || defined(__MINGW32__) || defined(__VXWORKS__) # define HAS_STRPTIME 0 @@ -119,6 +119,8 @@ std::tm ToTM(const time_zone::absolute_lookup& al) { if (al.cs.year() < std::numeric_limits::min() + 1900) { tm.tm_year = std::numeric_limits::min(); //} else if (al.cs.year() - 1900 > std::numeric_limits::max()) { + // package::odbc + // preserve historical behavior and avoid saturating here. //tm.tm_year = std::numeric_limits::max(); } else { tm.tm_year = static_cast(al.cs.year() - 1900); @@ -649,7 +651,8 @@ const char* ParseSubSeconds(const char* dp, detail::femtoseconds* subseconds) { // Parses a string into a std::tm using strptime(3). const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) { if (dp != nullptr) { - // We are not parsing from strings, so don't need this + // package::odbc + // We are not parsing from strings, so don't need this. //dp = strptime(dp, fmt, tm); } return dp; From 34aa3a06bb2f55c125c8cf17722942878bc15538 Mon Sep 17 00:00:00 2001 From: Bruno Tremblay Date: Wed, 25 Mar 2026 15:49:05 -0400 Subject: [PATCH 6/6] Address CRAN checks complaining --- MAINTENANCE.md | 1 + src/cctz/Makefile | 5 ++++- src/odbc_result.cpp | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MAINTENANCE.md b/MAINTENANCE.md index d1d7e0461..e1a79d5b1 100644 --- a/MAINTENANCE.md +++ b/MAINTENANCE.md @@ -23,6 +23,7 @@ following deltas for R package inclusion: - `src/cctz/Makefile` adds `time_zone_name_win.o` on Windows because upstream now ships `src/time_zone_name_win.cc`, and omitting it breaks Windows linking. +- `src/cctz/Makefile` add `-DNDEBUG` to `CPPFLAGS`. - `src/cctz/src/time_zone_fixed.cc` keeps odbc-specific fixed-offset zone names based on `Etc/GMT` rather than upstream `Fixed/UTC`, matching odbc timestamp offset behavior. diff --git a/src/cctz/Makefile b/src/cctz/Makefile index 832380146..e638118af 100644 --- a/src/cctz/Makefile +++ b/src/cctz/Makefile @@ -44,7 +44,10 @@ VPATH = $(SRC)src:$(SRC)examples # package::odbc # Preserve include flags and PIC flags when src/Makevars invokes # this Makefile with command-line CXXFLAGS during R package builds. -CPPFLAGS += -I$(SRC)include +# package:odbc +# Build vendored cctz in release mode so assert() does not surface in +# CRAN's compiled-code checks for termination-prone entry points. +CPPFLAGS += -DNDEBUG -I$(SRC)include override CXXFLAGS += -g -Wall -std=$(STD) $(TEST_FLAGS) $(CXXPICFLAGS) -MMD ARFLAGS = rcs LINK.o = $(LINK.cc) diff --git a/src/odbc_result.cpp b/src/odbc_result.cpp index 2b1fecfcc..dc8b36a74 100644 --- a/src/odbc_result.cpp +++ b/src/odbc_result.cpp @@ -1161,7 +1161,7 @@ std::pair odbc_result::get_tz_bind_info( std::string tzonestr = Rcpp::as(tzone); cctz::time_zone tz; if (!cctz::load_time_zone(tzonestr.data(), &tz)) { - std::cerr << "Failed to load time zone" << std::endl; + raise_warning("Failed to load time zone"); return {false, c_->timezone()}; } return {true, tz};