time_zone_lookup_test.cc
Go to the documentation of this file.
00001 // Copyright 2016 Google Inc. All Rights Reserved.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //   https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 //   Unless required by applicable law or agreed to in writing, software
00010 //   distributed under the License is distributed on an "AS IS" BASIS,
00011 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 //   See the License for the specific language governing permissions and
00013 //   limitations under the License.
00014 
00015 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
00016 
00017 #include <chrono>
00018 #include <cstddef>
00019 #include <cstdlib>
00020 #include <future>
00021 #include <limits>
00022 #include <string>
00023 #include <thread>
00024 #include <vector>
00025 
00026 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
00027 #include "gtest/gtest.h"
00028 
00029 namespace chrono = std::chrono;
00030 
00031 namespace absl {
00032 namespace time_internal {
00033 namespace cctz {
00034 
00035 namespace {
00036 
00037 // A list of known time-zone names.
00038 const char* const kTimeZoneNames[] = {
00039   "Africa/Abidjan",
00040   "Africa/Accra",
00041   "Africa/Addis_Ababa",
00042   "Africa/Algiers",
00043   "Africa/Asmara",
00044   "Africa/Asmera",
00045   "Africa/Bamako",
00046   "Africa/Bangui",
00047   "Africa/Banjul",
00048   "Africa/Bissau",
00049   "Africa/Blantyre",
00050   "Africa/Brazzaville",
00051   "Africa/Bujumbura",
00052   "Africa/Cairo",
00053   "Africa/Casablanca",
00054   "Africa/Ceuta",
00055   "Africa/Conakry",
00056   "Africa/Dakar",
00057   "Africa/Dar_es_Salaam",
00058   "Africa/Djibouti",
00059   "Africa/Douala",
00060   "Africa/El_Aaiun",
00061   "Africa/Freetown",
00062   "Africa/Gaborone",
00063   "Africa/Harare",
00064   "Africa/Johannesburg",
00065   "Africa/Juba",
00066   "Africa/Kampala",
00067   "Africa/Khartoum",
00068   "Africa/Kigali",
00069   "Africa/Kinshasa",
00070   "Africa/Lagos",
00071   "Africa/Libreville",
00072   "Africa/Lome",
00073   "Africa/Luanda",
00074   "Africa/Lubumbashi",
00075   "Africa/Lusaka",
00076   "Africa/Malabo",
00077   "Africa/Maputo",
00078   "Africa/Maseru",
00079   "Africa/Mbabane",
00080   "Africa/Mogadishu",
00081   "Africa/Monrovia",
00082   "Africa/Nairobi",
00083   "Africa/Ndjamena",
00084   "Africa/Niamey",
00085   "Africa/Nouakchott",
00086   "Africa/Ouagadougou",
00087   "Africa/Porto-Novo",
00088   "Africa/Sao_Tome",
00089   "Africa/Timbuktu",
00090   "Africa/Tripoli",
00091   "Africa/Tunis",
00092   "Africa/Windhoek",
00093   "America/Adak",
00094   "America/Anchorage",
00095   "America/Anguilla",
00096   "America/Antigua",
00097   "America/Araguaina",
00098   "America/Argentina/Buenos_Aires",
00099   "America/Argentina/Catamarca",
00100   "America/Argentina/ComodRivadavia",
00101   "America/Argentina/Cordoba",
00102   "America/Argentina/Jujuy",
00103   "America/Argentina/La_Rioja",
00104   "America/Argentina/Mendoza",
00105   "America/Argentina/Rio_Gallegos",
00106   "America/Argentina/Salta",
00107   "America/Argentina/San_Juan",
00108   "America/Argentina/San_Luis",
00109   "America/Argentina/Tucuman",
00110   "America/Argentina/Ushuaia",
00111   "America/Aruba",
00112   "America/Asuncion",
00113   "America/Atikokan",
00114   "America/Atka",
00115   "America/Bahia",
00116   "America/Bahia_Banderas",
00117   "America/Barbados",
00118   "America/Belem",
00119   "America/Belize",
00120   "America/Blanc-Sablon",
00121   "America/Boa_Vista",
00122   "America/Bogota",
00123   "America/Boise",
00124   "America/Buenos_Aires",
00125   "America/Cambridge_Bay",
00126   "America/Campo_Grande",
00127   "America/Cancun",
00128   "America/Caracas",
00129   "America/Catamarca",
00130   "America/Cayenne",
00131   "America/Cayman",
00132   "America/Chicago",
00133   "America/Chihuahua",
00134   "America/Coral_Harbour",
00135   "America/Cordoba",
00136   "America/Costa_Rica",
00137   "America/Creston",
00138   "America/Cuiaba",
00139   "America/Curacao",
00140   "America/Danmarkshavn",
00141   "America/Dawson",
00142   "America/Dawson_Creek",
00143   "America/Denver",
00144   "America/Detroit",
00145   "America/Dominica",
00146   "America/Edmonton",
00147   "America/Eirunepe",
00148   "America/El_Salvador",
00149   "America/Ensenada",
00150   "America/Fort_Nelson",
00151   "America/Fort_Wayne",
00152   "America/Fortaleza",
00153   "America/Glace_Bay",
00154   "America/Godthab",
00155   "America/Goose_Bay",
00156   "America/Grand_Turk",
00157   "America/Grenada",
00158   "America/Guadeloupe",
00159   "America/Guatemala",
00160   "America/Guayaquil",
00161   "America/Guyana",
00162   "America/Halifax",
00163   "America/Havana",
00164   "America/Hermosillo",
00165   "America/Indiana/Indianapolis",
00166   "America/Indiana/Knox",
00167   "America/Indiana/Marengo",
00168   "America/Indiana/Petersburg",
00169   "America/Indiana/Tell_City",
00170   "America/Indiana/Vevay",
00171   "America/Indiana/Vincennes",
00172   "America/Indiana/Winamac",
00173   "America/Indianapolis",
00174   "America/Inuvik",
00175   "America/Iqaluit",
00176   "America/Jamaica",
00177   "America/Jujuy",
00178   "America/Juneau",
00179   "America/Kentucky/Louisville",
00180   "America/Kentucky/Monticello",
00181   "America/Knox_IN",
00182   "America/Kralendijk",
00183   "America/La_Paz",
00184   "America/Lima",
00185   "America/Los_Angeles",
00186   "America/Louisville",
00187   "America/Lower_Princes",
00188   "America/Maceio",
00189   "America/Managua",
00190   "America/Manaus",
00191   "America/Marigot",
00192   "America/Martinique",
00193   "America/Matamoros",
00194   "America/Mazatlan",
00195   "America/Mendoza",
00196   "America/Menominee",
00197   "America/Merida",
00198   "America/Metlakatla",
00199   "America/Mexico_City",
00200   "America/Miquelon",
00201   "America/Moncton",
00202   "America/Monterrey",
00203   "America/Montevideo",
00204   "America/Montreal",
00205   "America/Montserrat",
00206   "America/Nassau",
00207   "America/New_York",
00208   "America/Nipigon",
00209   "America/Nome",
00210   "America/Noronha",
00211   "America/North_Dakota/Beulah",
00212   "America/North_Dakota/Center",
00213   "America/North_Dakota/New_Salem",
00214   "America/Ojinaga",
00215   "America/Panama",
00216   "America/Pangnirtung",
00217   "America/Paramaribo",
00218   "America/Phoenix",
00219   "America/Port-au-Prince",
00220   "America/Port_of_Spain",
00221   "America/Porto_Acre",
00222   "America/Porto_Velho",
00223   "America/Puerto_Rico",
00224   "America/Punta_Arenas",
00225   "America/Rainy_River",
00226   "America/Rankin_Inlet",
00227   "America/Recife",
00228   "America/Regina",
00229   "America/Resolute",
00230   "America/Rio_Branco",
00231   "America/Rosario",
00232   "America/Santa_Isabel",
00233   "America/Santarem",
00234   "America/Santiago",
00235   "America/Santo_Domingo",
00236   "America/Sao_Paulo",
00237   "America/Scoresbysund",
00238   "America/Shiprock",
00239   "America/Sitka",
00240   "America/St_Barthelemy",
00241   "America/St_Johns",
00242   "America/St_Kitts",
00243   "America/St_Lucia",
00244   "America/St_Thomas",
00245   "America/St_Vincent",
00246   "America/Swift_Current",
00247   "America/Tegucigalpa",
00248   "America/Thule",
00249   "America/Thunder_Bay",
00250   "America/Tijuana",
00251   "America/Toronto",
00252   "America/Tortola",
00253   "America/Vancouver",
00254   "America/Virgin",
00255   "America/Whitehorse",
00256   "America/Winnipeg",
00257   "America/Yakutat",
00258   "America/Yellowknife",
00259   "Antarctica/Casey",
00260   "Antarctica/Davis",
00261   "Antarctica/DumontDUrville",
00262   "Antarctica/Macquarie",
00263   "Antarctica/Mawson",
00264   "Antarctica/McMurdo",
00265   "Antarctica/Palmer",
00266   "Antarctica/Rothera",
00267   "Antarctica/South_Pole",
00268   "Antarctica/Syowa",
00269   "Antarctica/Troll",
00270   "Antarctica/Vostok",
00271   "Arctic/Longyearbyen",
00272   "Asia/Aden",
00273   "Asia/Almaty",
00274   "Asia/Amman",
00275   "Asia/Anadyr",
00276   "Asia/Aqtau",
00277   "Asia/Aqtobe",
00278   "Asia/Ashgabat",
00279   "Asia/Ashkhabad",
00280   "Asia/Atyrau",
00281   "Asia/Baghdad",
00282   "Asia/Bahrain",
00283   "Asia/Baku",
00284   "Asia/Bangkok",
00285   "Asia/Barnaul",
00286   "Asia/Beirut",
00287   "Asia/Bishkek",
00288   "Asia/Brunei",
00289   "Asia/Calcutta",
00290   "Asia/Chita",
00291   "Asia/Choibalsan",
00292   "Asia/Chongqing",
00293   "Asia/Chungking",
00294   "Asia/Colombo",
00295   "Asia/Dacca",
00296   "Asia/Damascus",
00297   "Asia/Dhaka",
00298   "Asia/Dili",
00299   "Asia/Dubai",
00300   "Asia/Dushanbe",
00301   "Asia/Famagusta",
00302   "Asia/Gaza",
00303   "Asia/Harbin",
00304   "Asia/Hebron",
00305   "Asia/Ho_Chi_Minh",
00306   "Asia/Hong_Kong",
00307   "Asia/Hovd",
00308   "Asia/Irkutsk",
00309   "Asia/Istanbul",
00310   "Asia/Jakarta",
00311   "Asia/Jayapura",
00312   "Asia/Jerusalem",
00313   "Asia/Kabul",
00314   "Asia/Kamchatka",
00315   "Asia/Karachi",
00316   "Asia/Kashgar",
00317   "Asia/Kathmandu",
00318   "Asia/Katmandu",
00319   "Asia/Khandyga",
00320   "Asia/Kolkata",
00321   "Asia/Krasnoyarsk",
00322   "Asia/Kuala_Lumpur",
00323   "Asia/Kuching",
00324   "Asia/Kuwait",
00325   "Asia/Macao",
00326   "Asia/Macau",
00327   "Asia/Magadan",
00328   "Asia/Makassar",
00329   "Asia/Manila",
00330   "Asia/Muscat",
00331   "Asia/Nicosia",
00332   "Asia/Novokuznetsk",
00333   "Asia/Novosibirsk",
00334   "Asia/Omsk",
00335   "Asia/Oral",
00336   "Asia/Phnom_Penh",
00337   "Asia/Pontianak",
00338   "Asia/Pyongyang",
00339   "Asia/Qatar",
00340   "Asia/Qostanay",
00341   "Asia/Qyzylorda",
00342   "Asia/Rangoon",
00343   "Asia/Riyadh",
00344   "Asia/Saigon",
00345   "Asia/Sakhalin",
00346   "Asia/Samarkand",
00347   "Asia/Seoul",
00348   "Asia/Shanghai",
00349   "Asia/Singapore",
00350   "Asia/Srednekolymsk",
00351   "Asia/Taipei",
00352   "Asia/Tashkent",
00353   "Asia/Tbilisi",
00354   "Asia/Tehran",
00355   "Asia/Tel_Aviv",
00356   "Asia/Thimbu",
00357   "Asia/Thimphu",
00358   "Asia/Tokyo",
00359   "Asia/Tomsk",
00360   "Asia/Ujung_Pandang",
00361   "Asia/Ulaanbaatar",
00362   "Asia/Ulan_Bator",
00363   "Asia/Urumqi",
00364   "Asia/Ust-Nera",
00365   "Asia/Vientiane",
00366   "Asia/Vladivostok",
00367   "Asia/Yakutsk",
00368   "Asia/Yangon",
00369   "Asia/Yekaterinburg",
00370   "Asia/Yerevan",
00371   "Atlantic/Azores",
00372   "Atlantic/Bermuda",
00373   "Atlantic/Canary",
00374   "Atlantic/Cape_Verde",
00375   "Atlantic/Faeroe",
00376   "Atlantic/Faroe",
00377   "Atlantic/Jan_Mayen",
00378   "Atlantic/Madeira",
00379   "Atlantic/Reykjavik",
00380   "Atlantic/South_Georgia",
00381   "Atlantic/St_Helena",
00382   "Atlantic/Stanley",
00383   "Australia/ACT",
00384   "Australia/Adelaide",
00385   "Australia/Brisbane",
00386   "Australia/Broken_Hill",
00387   "Australia/Canberra",
00388   "Australia/Currie",
00389   "Australia/Darwin",
00390   "Australia/Eucla",
00391   "Australia/Hobart",
00392   "Australia/LHI",
00393   "Australia/Lindeman",
00394   "Australia/Lord_Howe",
00395   "Australia/Melbourne",
00396   "Australia/NSW",
00397   "Australia/North",
00398   "Australia/Perth",
00399   "Australia/Queensland",
00400   "Australia/South",
00401   "Australia/Sydney",
00402   "Australia/Tasmania",
00403   "Australia/Victoria",
00404   "Australia/West",
00405   "Australia/Yancowinna",
00406   "Brazil/Acre",
00407   "Brazil/DeNoronha",
00408   "Brazil/East",
00409   "Brazil/West",
00410   "CET",
00411   "CST6CDT",
00412   "Canada/Atlantic",
00413   "Canada/Central",
00414   "Canada/Eastern",
00415   "Canada/Mountain",
00416   "Canada/Newfoundland",
00417   "Canada/Pacific",
00418   "Canada/Saskatchewan",
00419   "Canada/Yukon",
00420   "Chile/Continental",
00421   "Chile/EasterIsland",
00422   "Cuba",
00423   "EET",
00424   "EST",
00425   "EST5EDT",
00426   "Egypt",
00427   "Eire",
00428   "Etc/GMT",
00429   "Etc/GMT+0",
00430   "Etc/GMT+1",
00431   "Etc/GMT+10",
00432   "Etc/GMT+11",
00433   "Etc/GMT+12",
00434   "Etc/GMT+2",
00435   "Etc/GMT+3",
00436   "Etc/GMT+4",
00437   "Etc/GMT+5",
00438   "Etc/GMT+6",
00439   "Etc/GMT+7",
00440   "Etc/GMT+8",
00441   "Etc/GMT+9",
00442   "Etc/GMT-0",
00443   "Etc/GMT-1",
00444   "Etc/GMT-10",
00445   "Etc/GMT-11",
00446   "Etc/GMT-12",
00447   "Etc/GMT-13",
00448   "Etc/GMT-14",
00449   "Etc/GMT-2",
00450   "Etc/GMT-3",
00451   "Etc/GMT-4",
00452   "Etc/GMT-5",
00453   "Etc/GMT-6",
00454   "Etc/GMT-7",
00455   "Etc/GMT-8",
00456   "Etc/GMT-9",
00457   "Etc/GMT0",
00458   "Etc/Greenwich",
00459   "Etc/UCT",
00460   "Etc/UTC",
00461   "Etc/Universal",
00462   "Etc/Zulu",
00463   "Europe/Amsterdam",
00464   "Europe/Andorra",
00465   "Europe/Astrakhan",
00466   "Europe/Athens",
00467   "Europe/Belfast",
00468   "Europe/Belgrade",
00469   "Europe/Berlin",
00470   "Europe/Bratislava",
00471   "Europe/Brussels",
00472   "Europe/Bucharest",
00473   "Europe/Budapest",
00474   "Europe/Busingen",
00475   "Europe/Chisinau",
00476   "Europe/Copenhagen",
00477   "Europe/Dublin",
00478   "Europe/Gibraltar",
00479   "Europe/Guernsey",
00480   "Europe/Helsinki",
00481   "Europe/Isle_of_Man",
00482   "Europe/Istanbul",
00483   "Europe/Jersey",
00484   "Europe/Kaliningrad",
00485   "Europe/Kiev",
00486   "Europe/Kirov",
00487   "Europe/Lisbon",
00488   "Europe/Ljubljana",
00489   "Europe/London",
00490   "Europe/Luxembourg",
00491   "Europe/Madrid",
00492   "Europe/Malta",
00493   "Europe/Mariehamn",
00494   "Europe/Minsk",
00495   "Europe/Monaco",
00496   "Europe/Moscow",
00497   "Europe/Nicosia",
00498   "Europe/Oslo",
00499   "Europe/Paris",
00500   "Europe/Podgorica",
00501   "Europe/Prague",
00502   "Europe/Riga",
00503   "Europe/Rome",
00504   "Europe/Samara",
00505   "Europe/San_Marino",
00506   "Europe/Sarajevo",
00507   "Europe/Saratov",
00508   "Europe/Simferopol",
00509   "Europe/Skopje",
00510   "Europe/Sofia",
00511   "Europe/Stockholm",
00512   "Europe/Tallinn",
00513   "Europe/Tirane",
00514   "Europe/Tiraspol",
00515   "Europe/Ulyanovsk",
00516   "Europe/Uzhgorod",
00517   "Europe/Vaduz",
00518   "Europe/Vatican",
00519   "Europe/Vienna",
00520   "Europe/Vilnius",
00521   "Europe/Volgograd",
00522   "Europe/Warsaw",
00523   "Europe/Zagreb",
00524   "Europe/Zaporozhye",
00525   "Europe/Zurich",
00526   "GB",
00527   "GB-Eire",
00528   "GMT",
00529   "GMT+0",
00530   "GMT-0",
00531   "GMT0",
00532   "Greenwich",
00533   "HST",
00534   "Hongkong",
00535   "Iceland",
00536   "Indian/Antananarivo",
00537   "Indian/Chagos",
00538   "Indian/Christmas",
00539   "Indian/Cocos",
00540   "Indian/Comoro",
00541   "Indian/Kerguelen",
00542   "Indian/Mahe",
00543   "Indian/Maldives",
00544   "Indian/Mauritius",
00545   "Indian/Mayotte",
00546   "Indian/Reunion",
00547   "Iran",
00548   "Israel",
00549   "Jamaica",
00550   "Japan",
00551   "Kwajalein",
00552   "Libya",
00553   "MET",
00554   "MST",
00555   "MST7MDT",
00556   "Mexico/BajaNorte",
00557   "Mexico/BajaSur",
00558   "Mexico/General",
00559   "NZ",
00560   "NZ-CHAT",
00561   "Navajo",
00562   "PRC",
00563   "PST8PDT",
00564   "Pacific/Apia",
00565   "Pacific/Auckland",
00566   "Pacific/Bougainville",
00567   "Pacific/Chatham",
00568   "Pacific/Chuuk",
00569   "Pacific/Easter",
00570   "Pacific/Efate",
00571   "Pacific/Enderbury",
00572   "Pacific/Fakaofo",
00573   "Pacific/Fiji",
00574   "Pacific/Funafuti",
00575   "Pacific/Galapagos",
00576   "Pacific/Gambier",
00577   "Pacific/Guadalcanal",
00578   "Pacific/Guam",
00579   "Pacific/Honolulu",
00580   "Pacific/Johnston",
00581   "Pacific/Kiritimati",
00582   "Pacific/Kosrae",
00583   "Pacific/Kwajalein",
00584   "Pacific/Majuro",
00585   "Pacific/Marquesas",
00586   "Pacific/Midway",
00587   "Pacific/Nauru",
00588   "Pacific/Niue",
00589   "Pacific/Norfolk",
00590   "Pacific/Noumea",
00591   "Pacific/Pago_Pago",
00592   "Pacific/Palau",
00593   "Pacific/Pitcairn",
00594   "Pacific/Pohnpei",
00595   "Pacific/Ponape",
00596   "Pacific/Port_Moresby",
00597   "Pacific/Rarotonga",
00598   "Pacific/Saipan",
00599   "Pacific/Samoa",
00600   "Pacific/Tahiti",
00601   "Pacific/Tarawa",
00602   "Pacific/Tongatapu",
00603   "Pacific/Truk",
00604   "Pacific/Wake",
00605   "Pacific/Wallis",
00606   "Pacific/Yap",
00607   "Poland",
00608   "Portugal",
00609   "ROC",
00610   "ROK",
00611   "Singapore",
00612   "Turkey",
00613   "UCT",
00614   "US/Alaska",
00615   "US/Aleutian",
00616   "US/Arizona",
00617   "US/Central",
00618   "US/East-Indiana",
00619   "US/Eastern",
00620   "US/Hawaii",
00621   "US/Indiana-Starke",
00622   "US/Michigan",
00623   "US/Mountain",
00624   "US/Pacific",
00625   "US/Samoa",
00626   "UTC",
00627   "Universal",
00628   "W-SU",
00629   "WET",
00630   "Zulu",
00631   nullptr
00632 };
00633 
00634 // Helper to return a loaded time zone by value (UTC on error).
00635 time_zone LoadZone(const std::string& name) {
00636   time_zone tz;
00637   load_time_zone(name, &tz);
00638   return tz;
00639 }
00640 
00641 // This helper is a macro so that failed expectations show up with the
00642 // correct line numbers.
00643 #define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \
00644   do {                                                            \
00645     time_zone::absolute_lookup al = tz.lookup(tp);                \
00646     EXPECT_EQ(y, al.cs.year());                                   \
00647     EXPECT_EQ(m, al.cs.month());                                  \
00648     EXPECT_EQ(d, al.cs.day());                                    \
00649     EXPECT_EQ(hh, al.cs.hour());                                  \
00650     EXPECT_EQ(mm, al.cs.minute());                                \
00651     EXPECT_EQ(ss, al.cs.second());                                \
00652     EXPECT_EQ(off, al.offset);                                    \
00653     EXPECT_TRUE(isdst == al.is_dst);                              \
00654     /* EXPECT_STREQ(zone, al.abbr); */                            \
00655   } while (0)
00656 
00657 // These tests sometimes run on platforms that have zoneinfo data so old
00658 // that the transition we are attempting to check does not exist, most
00659 // notably Android emulators.  Fortunately, AndroidZoneInfoSource supports
00660 // time_zone::version() so, in cases where we've learned that it matters,
00661 // we can make the check conditionally.
00662 int VersionCmp(time_zone tz, const std::string& target) {
00663   std::string version = tz.version();
00664   if (version.empty() && !target.empty()) return 1;  // unknown > known
00665   return version.compare(target);
00666 }
00667 
00668 }  // namespace
00669 
00670 #if !defined(__EMSCRIPTEN__)
00671 TEST(TimeZones, LoadZonesConcurrently) {
00672   std::promise<void> ready_promise;
00673   std::shared_future<void> ready_future(ready_promise.get_future());
00674   auto load_zones = [ready_future](std::promise<void>* started,
00675                                    std::set<std::string>* failures) {
00676     started->set_value();
00677     ready_future.wait();
00678     for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) {
00679       std::string zone = *np;
00680       time_zone tz;
00681       if (load_time_zone(zone, &tz)) {
00682         EXPECT_EQ(zone, tz.name());
00683       } else {
00684         failures->insert(zone);
00685       }
00686     }
00687   };
00688 
00689   const std::size_t n_threads = 128;
00690   std::vector<std::thread> threads;
00691   std::vector<std::set<std::string>> thread_failures(n_threads);
00692   for (std::size_t i = 0; i != n_threads; ++i) {
00693     std::promise<void> started;
00694     threads.emplace_back(load_zones, &started, &thread_failures[i]);
00695     started.get_future().wait();
00696   }
00697   ready_promise.set_value();
00698   for (auto& thread : threads) {
00699     thread.join();
00700   }
00701 
00702   // Allow a small number of failures to account for skew between
00703   // the contents of kTimeZoneNames and the zoneinfo data source.
00704 #if defined(__ANDROID__)
00705   // Cater to the possibility of using an even older zoneinfo data
00706   // source when running on Android, where it is difficult to override
00707   // the bionic tzdata provided by the test environment.
00708   const std::size_t max_failures = 20;
00709 #else
00710   const std::size_t max_failures = 3;
00711 #endif
00712   std::set<std::string> failures;
00713   for (const auto& thread_failure : thread_failures) {
00714     failures.insert(thread_failure.begin(), thread_failure.end());
00715   }
00716   EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures);
00717 }
00718 #endif
00719 
00720 TEST(TimeZone, NamedTimeZones) {
00721   const time_zone utc = utc_time_zone();
00722   EXPECT_EQ("UTC", utc.name());
00723   const time_zone nyc = LoadZone("America/New_York");
00724   EXPECT_EQ("America/New_York", nyc.name());
00725   const time_zone syd = LoadZone("Australia/Sydney");
00726   EXPECT_EQ("Australia/Sydney", syd.name());
00727   const time_zone fixed0 = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
00728   EXPECT_EQ("UTC", fixed0.name());
00729   const time_zone fixed_pos = fixed_time_zone(
00730       chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45));
00731   EXPECT_EQ("Fixed/UTC+03:25:45", fixed_pos.name());
00732   const time_zone fixed_neg = fixed_time_zone(
00733       -(chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56)));
00734   EXPECT_EQ("Fixed/UTC-12:34:56", fixed_neg.name());
00735 }
00736 
00737 TEST(TimeZone, Failures) {
00738   time_zone tz;
00739   EXPECT_FALSE(load_time_zone(":America/Los_Angeles", &tz));
00740 
00741   tz = LoadZone("America/Los_Angeles");
00742   EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &tz));
00743   EXPECT_EQ(chrono::system_clock::from_time_t(0),
00744             convert(civil_second(1970, 1, 1, 0, 0, 0), tz));  // UTC
00745 
00746   // Ensures that the load still fails on a subsequent attempt.
00747   tz = LoadZone("America/Los_Angeles");
00748   EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &tz));
00749   EXPECT_EQ(chrono::system_clock::from_time_t(0),
00750             convert(civil_second(1970, 1, 1, 0, 0, 0), tz));  // UTC
00751 
00752   // Loading an empty std::string timezone should fail.
00753   tz = LoadZone("America/Los_Angeles");
00754   EXPECT_FALSE(load_time_zone("", &tz));
00755   EXPECT_EQ(chrono::system_clock::from_time_t(0),
00756             convert(civil_second(1970, 1, 1, 0, 0, 0), tz));  // UTC
00757 }
00758 
00759 TEST(TimeZone, Equality) {
00760   const time_zone a;
00761   const time_zone b;
00762   EXPECT_EQ(a, b);
00763   EXPECT_EQ(a.name(), b.name());
00764 
00765   const time_zone implicit_utc;
00766   const time_zone explicit_utc = utc_time_zone();
00767   EXPECT_EQ(implicit_utc, explicit_utc);
00768   EXPECT_EQ(implicit_utc.name(), explicit_utc.name());
00769 
00770   const time_zone fixed_zero = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
00771   EXPECT_EQ(fixed_zero, LoadZone(fixed_zero.name()));
00772   EXPECT_EQ(fixed_zero, explicit_utc);
00773 
00774   const time_zone fixed_utc = LoadZone("Fixed/UTC+00:00:00");
00775   EXPECT_EQ(fixed_utc, LoadZone(fixed_utc.name()));
00776   EXPECT_EQ(fixed_utc, explicit_utc);
00777 
00778   const time_zone fixed_pos = fixed_time_zone(
00779       chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45));
00780   EXPECT_EQ(fixed_pos, LoadZone(fixed_pos.name()));
00781   EXPECT_NE(fixed_pos, explicit_utc);
00782   const time_zone fixed_neg = fixed_time_zone(
00783       -(chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56)));
00784   EXPECT_EQ(fixed_neg, LoadZone(fixed_neg.name()));
00785   EXPECT_NE(fixed_neg, explicit_utc);
00786 
00787   const time_zone fixed_lim = fixed_time_zone(chrono::hours(24));
00788   EXPECT_EQ(fixed_lim, LoadZone(fixed_lim.name()));
00789   EXPECT_NE(fixed_lim, explicit_utc);
00790   const time_zone fixed_ovfl =
00791       fixed_time_zone(chrono::hours(24) + chrono::seconds(1));
00792   EXPECT_EQ(fixed_ovfl, LoadZone(fixed_ovfl.name()));
00793   EXPECT_EQ(fixed_ovfl, explicit_utc);
00794 
00795   EXPECT_EQ(fixed_time_zone(chrono::seconds(1)),
00796             fixed_time_zone(chrono::seconds(1)));
00797 
00798   const time_zone local = local_time_zone();
00799   EXPECT_EQ(local, LoadZone(local.name()));
00800 
00801   time_zone la = LoadZone("America/Los_Angeles");
00802   time_zone nyc = LoadZone("America/New_York");
00803   EXPECT_NE(la, nyc);
00804 }
00805 
00806 TEST(StdChronoTimePoint, TimeTAlignment) {
00807   // Ensures that the Unix epoch and the system clock epoch are an integral
00808   // number of seconds apart. This simplifies conversions to/from time_t.
00809   auto diff = chrono::system_clock::time_point() -
00810               chrono::system_clock::from_time_t(0);
00811   EXPECT_EQ(chrono::system_clock::time_point::duration::zero(),
00812             diff % chrono::seconds(1));
00813 }
00814 
00815 TEST(BreakTime, TimePointResolution) {
00816   const time_zone utc = utc_time_zone();
00817   const auto t0 = chrono::system_clock::from_time_t(0);
00818 
00819   ExpectTime(chrono::time_point_cast<chrono::nanoseconds>(t0), utc,
00820              1970, 1, 1, 0, 0, 0, 0, false, "UTC");
00821   ExpectTime(chrono::time_point_cast<chrono::microseconds>(t0), utc,
00822              1970, 1, 1, 0, 0, 0, 0, false, "UTC");
00823   ExpectTime(chrono::time_point_cast<chrono::milliseconds>(t0), utc,
00824              1970, 1, 1, 0, 0, 0, 0, false, "UTC");
00825   ExpectTime(chrono::time_point_cast<chrono::seconds>(t0), utc,
00826              1970, 1, 1, 0, 0, 0, 0, false, "UTC");
00827   ExpectTime(chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0), utc,
00828              1970, 1, 1, 0, 0, 0, 0, false, "UTC");
00829   ExpectTime(chrono::time_point_cast<chrono::minutes>(t0), utc,
00830              1970, 1, 1, 0, 0, 0, 0, false, "UTC");
00831   ExpectTime(chrono::time_point_cast<chrono::hours>(t0), utc,
00832              1970, 1, 1, 0, 0, 0, 0, false, "UTC");
00833 }
00834 
00835 TEST(BreakTime, LocalTimeInUTC) {
00836   const time_zone tz = utc_time_zone();
00837   const auto tp = chrono::system_clock::from_time_t(0);
00838   ExpectTime(tp, tz, 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
00839   EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz))));
00840 }
00841 
00842 TEST(BreakTime, LocalTimeInUTCUnaligned) {
00843   const time_zone tz = utc_time_zone();
00844   const auto tp =
00845       chrono::system_clock::from_time_t(0) - chrono::milliseconds(500);
00846   ExpectTime(tp, tz, 1969, 12, 31, 23, 59, 59, 0, false, "UTC");
00847   EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
00848 }
00849 
00850 TEST(BreakTime, LocalTimePosix) {
00851   // See IEEE Std 1003.1-1988 B.2.3 General Terms, Epoch.
00852   const time_zone tz = utc_time_zone();
00853   const auto tp = chrono::system_clock::from_time_t(536457599);
00854   ExpectTime(tp, tz, 1986, 12, 31, 23, 59, 59, 0, false, "UTC");
00855   EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
00856 }
00857 
00858 TEST(TimeZoneImpl, LocalTimeInFixed) {
00859   const absl::time_internal::cctz::seconds offset =
00860       -(chrono::hours(8) + chrono::minutes(33) + chrono::seconds(47));
00861   const time_zone tz = fixed_time_zone(offset);
00862   const auto tp = chrono::system_clock::from_time_t(0);
00863   ExpectTime(tp, tz, 1969, 12, 31, 15, 26, 13, offset.count(), false,
00864              "-083347");
00865   EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
00866 }
00867 
00868 TEST(BreakTime, LocalTimeInNewYork) {
00869   const time_zone tz = LoadZone("America/New_York");
00870   const auto tp = chrono::system_clock::from_time_t(45);
00871   ExpectTime(tp, tz, 1969, 12, 31, 19, 0, 45, -5 * 60 * 60, false, "EST");
00872   EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
00873 }
00874 
00875 TEST(BreakTime, LocalTimeInMTV) {
00876   const time_zone tz = LoadZone("America/Los_Angeles");
00877   const auto tp = chrono::system_clock::from_time_t(1380855729);
00878   ExpectTime(tp, tz, 2013, 10, 3, 20, 2, 9, -7 * 60 * 60, true, "PDT");
00879   EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz))));
00880 }
00881 
00882 TEST(BreakTime, LocalTimeInSydney) {
00883   const time_zone tz = LoadZone("Australia/Sydney");
00884   const auto tp = chrono::system_clock::from_time_t(90);
00885   ExpectTime(tp, tz, 1970, 1, 1, 10, 1, 30, 10 * 60 * 60, false, "AEST");
00886   EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz))));
00887 }
00888 
00889 TEST(MakeTime, TimePointResolution) {
00890   const time_zone utc = utc_time_zone();
00891   const time_point<chrono::nanoseconds> tp_ns =
00892       convert(civil_second(2015, 1, 2, 3, 4, 5), utc);
00893   EXPECT_EQ("04:05", format("%M:%E*S", tp_ns, utc));
00894   const time_point<chrono::microseconds> tp_us =
00895       convert(civil_second(2015, 1, 2, 3, 4, 5), utc);
00896   EXPECT_EQ("04:05", format("%M:%E*S", tp_us, utc));
00897   const time_point<chrono::milliseconds> tp_ms =
00898       convert(civil_second(2015, 1, 2, 3, 4, 5), utc);
00899   EXPECT_EQ("04:05", format("%M:%E*S", tp_ms, utc));
00900   const time_point<chrono::seconds> tp_s =
00901       convert(civil_second(2015, 1, 2, 3, 4, 5), utc);
00902   EXPECT_EQ("04:05", format("%M:%E*S", tp_s, utc));
00903   const time_point<absl::time_internal::cctz::seconds> tp_s64 =
00904       convert(civil_second(2015, 1, 2, 3, 4, 5), utc);
00905   EXPECT_EQ("04:05", format("%M:%E*S", tp_s64, utc));
00906 
00907   // These next two require chrono::time_point_cast because the conversion
00908   // from a resolution of seconds (the return value of convert()) to a
00909   // coarser resolution requires an explicit cast.
00910   const time_point<chrono::minutes> tp_m =
00911       chrono::time_point_cast<chrono::minutes>(
00912           convert(civil_second(2015, 1, 2, 3, 4, 5), utc));
00913   EXPECT_EQ("04:00", format("%M:%E*S", tp_m, utc));
00914   const time_point<chrono::hours> tp_h =
00915       chrono::time_point_cast<chrono::hours>(
00916           convert(civil_second(2015, 1, 2, 3, 4, 5), utc));
00917   EXPECT_EQ("00:00", format("%M:%E*S", tp_h, utc));
00918 }
00919 
00920 TEST(MakeTime, Normalization) {
00921   const time_zone tz = LoadZone("America/New_York");
00922   const auto tp = convert(civil_second(2009, 2, 13, 18, 31, 30), tz);
00923   EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp);
00924 
00925   // Now requests for the same time_point but with out-of-range fields.
00926   EXPECT_EQ(tp, convert(civil_second(2008, 14, 13, 18, 31, 30), tz));  // month
00927   EXPECT_EQ(tp, convert(civil_second(2009, 1, 44, 18, 31, 30), tz));   // day
00928   EXPECT_EQ(tp, convert(civil_second(2009, 2, 12, 42, 31, 30), tz));   // hour
00929   EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 17, 91, 30), tz));   // minute
00930   EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 18, 30, 90), tz));   // second
00931 }
00932 
00933 // NOTE: Run this with -ftrapv to detect overflow problems.
00934 TEST(MakeTime, SysSecondsLimits) {
00935   const char RFC3339[] =  "%Y-%m-%dT%H:%M:%S%Ez";
00936   const time_zone utc = utc_time_zone();
00937   const time_zone east = fixed_time_zone(chrono::hours(14));
00938   const time_zone west = fixed_time_zone(-chrono::hours(14));
00939   time_point<absl::time_internal::cctz::seconds> tp;
00940 
00941   // Approach the maximal time_point<cctz::seconds> value from below.
00942   tp = convert(civil_second(292277026596, 12, 4, 15, 30, 6), utc);
00943   EXPECT_EQ("292277026596-12-04T15:30:06+00:00", format(RFC3339, tp, utc));
00944   tp = convert(civil_second(292277026596, 12, 4, 15, 30, 7), utc);
00945   EXPECT_EQ("292277026596-12-04T15:30:07+00:00", format(RFC3339, tp, utc));
00946   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);
00947   tp = convert(civil_second(292277026596, 12, 4, 15, 30, 8), utc);
00948   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);
00949   tp = convert(civil_second::max(), utc);
00950   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);
00951 
00952   // Checks that we can also get the maximal value for a far-east zone.
00953   tp = convert(civil_second(292277026596, 12, 5, 5, 30, 7), east);
00954   EXPECT_EQ("292277026596-12-05T05:30:07+14:00", format(RFC3339, tp, east));
00955   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);
00956   tp = convert(civil_second(292277026596, 12, 5, 5, 30, 8), east);
00957   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);
00958   tp = convert(civil_second::max(), east);
00959   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);
00960 
00961   // Checks that we can also get the maximal value for a far-west zone.
00962   tp = convert(civil_second(292277026596, 12, 4, 1, 30, 7), west);
00963   EXPECT_EQ("292277026596-12-04T01:30:07-14:00", format(RFC3339, tp, west));
00964   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);
00965   tp = convert(civil_second(292277026596, 12, 4, 7, 30, 8), west);
00966   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);
00967   tp = convert(civil_second::max(), west);
00968   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::max(), tp);
00969 
00970   // Approach the minimal time_point<cctz::seconds> value from above.
00971   tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 53), utc);
00972   EXPECT_EQ("-292277022657-01-27T08:29:53+00:00", format(RFC3339, tp, utc));
00973   tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 52), utc);
00974   EXPECT_EQ("-292277022657-01-27T08:29:52+00:00", format(RFC3339, tp, utc));
00975   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
00976   tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 51), utc);
00977   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
00978   tp = convert(civil_second::min(), utc);
00979   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
00980 
00981   // Checks that we can also get the minimal value for a far-east zone.
00982   tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 52), east);
00983   EXPECT_EQ("-292277022657-01-27T22:29:52+14:00", format(RFC3339, tp, east));
00984   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
00985   tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 51), east);
00986   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
00987   tp = convert(civil_second::min(), east);
00988   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
00989 
00990   // Checks that we can also get the minimal value for a far-west zone.
00991   tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 52), west);
00992   EXPECT_EQ("-292277022657-01-26T18:29:52-14:00", format(RFC3339, tp, west));
00993   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
00994   tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 51), west);
00995   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
00996   tp = convert(civil_second::min(), west);
00997   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
00998 
00999   // Some similar checks for the "libc" time-zone implementation.
01000   if (sizeof(std::time_t) >= 8) {
01001     // Checks that "tm_year + 1900", as used by the "libc" implementation,
01002     // can produce year values beyond the range on an int without overflow.
01003 #if defined(_WIN32) || defined(_WIN64)
01004     // localtime_s() and gmtime_s() don't believe in years outside [1970:3000].
01005 #else
01006     const time_zone utc = LoadZone("libc:UTC");
01007     const year_t max_tm_year = year_t{std::numeric_limits<int>::max()} + 1900;
01008     tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), utc);
01009     EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, utc));
01010     const year_t min_tm_year = year_t{std::numeric_limits<int>::min()} + 1900;
01011     tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), utc);
01012     EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, utc));
01013 #endif
01014   }
01015 }
01016 
01017 TEST(MakeTime, LocalTimeLibC) {
01018   // Checks that cctz and libc agree on transition points in [1970:2037].
01019   //
01020   // We limit this test case to environments where:
01021   //  1) we know how to change the time zone used by localtime()/mktime(),
01022   //  2) cctz and localtime()/mktime() will use similar-enough tzdata, and
01023   //  3) we have some idea about how mktime() behaves during transitions.
01024 #if defined(__linux__) && !defined(__ANDROID__)
01025   const char* const ep = getenv("TZ");
01026   std::string tz_name = (ep != nullptr) ? ep : "";
01027   for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) {
01028     ASSERT_EQ(0, setenv("TZ", *np, 1));  // change what "localtime" means
01029     const auto zi = local_time_zone();
01030     const auto lc = LoadZone("libc:localtime");
01031     time_zone::civil_transition trans;
01032     for (auto tp = zi.lookup(civil_second()).trans;
01033          zi.next_transition(tp, &trans);
01034          tp = zi.lookup(trans.to).trans) {
01035       const auto fcl = zi.lookup(trans.from);
01036       const auto tcl = zi.lookup(trans.to);
01037       civil_second cs;  // compare cs in zi and lc
01038       if (fcl.kind == time_zone::civil_lookup::UNIQUE) {
01039         if (tcl.kind == time_zone::civil_lookup::UNIQUE) {
01040           // Both unique; must be an is_dst or abbr change.
01041           ASSERT_EQ(trans.from, trans.to);
01042           const auto trans = fcl.trans;
01043           const auto tal = zi.lookup(trans);
01044           const auto tprev = trans - absl::time_internal::cctz::seconds(1);
01045           const auto pal = zi.lookup(tprev);
01046           if (pal.is_dst == tal.is_dst) {
01047             ASSERT_STRNE(pal.abbr, tal.abbr);
01048           }
01049           continue;
01050         }
01051         ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind);
01052         cs = trans.to;
01053       } else {
01054         ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind);
01055         ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind);
01056         cs = trans.from;
01057       }
01058       if (cs.year() > 2037) break;  // limit test time (and to 32-bit time_t)
01059       const auto cl_zi = zi.lookup(cs);
01060       if (zi.lookup(cl_zi.pre).is_dst == zi.lookup(cl_zi.post).is_dst) {
01061         // The "libc" implementation cannot correctly classify transitions
01062         // that don't change the "tm_isdst" flag.  In Europe/Volgograd, for
01063         // example, there is a SKIPPED transition from +03 to +04 with dst=F
01064         // on both sides ...
01065         //   1540681199 = 2018-10-28 01:59:59 +03:00:00 [dst=F off=10800]
01066         //   1540681200 = 2018-10-28 03:00:00 +04:00:00 [dst=F off=14400]
01067         // but std::mktime(2018-10-28 02:00:00, tm_isdst=0) fails, unlike,
01068         // say, the similar Europe/Chisinau transition from +02 to +03 ...
01069         //   1521935999 = 2018-03-25 01:59:59 +02:00:00 [dst=F off=7200]
01070         //   1521936000 = 2018-03-25 03:00:00 +03:00:00 [dst=T off=10800]
01071         // where std::mktime(2018-03-25 02:00:00, tm_isdst=0) succeeds and
01072         // returns 1521936000.
01073         continue;
01074       }
01075       if (cs == civil_second(2037, 10, 4, 2, 0, 0)) {
01076         const std::string tzname = *np;
01077         if (tzname == "Africa/Casablanca" || tzname == "Africa/El_Aaiun") {
01078           // The "libc" implementation gets this transition wrong (at least
01079           // until 2018g when it was removed), returning an offset of 3600
01080           // instead of 0.  TODO: Revert this when 2018g is ubiquitous.
01081           continue;
01082         }
01083       }
01084       const auto cl_lc = lc.lookup(cs);
01085       SCOPED_TRACE(testing::Message() << "For " << cs << " in " << *np);
01086       EXPECT_EQ(cl_zi.kind, cl_lc.kind);
01087       EXPECT_EQ(cl_zi.pre, cl_lc.pre);
01088       EXPECT_EQ(cl_zi.trans, cl_lc.trans);
01089       EXPECT_EQ(cl_zi.post, cl_lc.post);
01090     }
01091   }
01092   if (ep == nullptr) {
01093     ASSERT_EQ(0, unsetenv("TZ"));
01094   } else {
01095     ASSERT_EQ(0, setenv("TZ", tz_name.c_str(), 1));
01096   }
01097 #endif
01098 }
01099 
01100 TEST(NextTransition, UTC) {
01101   const auto tz = utc_time_zone();
01102   time_zone::civil_transition trans;
01103 
01104   auto tp = time_point<absl::time_internal::cctz::seconds>::min();
01105   EXPECT_FALSE(tz.next_transition(tp, &trans));
01106 
01107   tp = time_point<absl::time_internal::cctz::seconds>::max();
01108   EXPECT_FALSE(tz.next_transition(tp, &trans));
01109 }
01110 
01111 TEST(PrevTransition, UTC) {
01112   const auto tz = utc_time_zone();
01113   time_zone::civil_transition trans;
01114 
01115   auto tp = time_point<absl::time_internal::cctz::seconds>::max();
01116   EXPECT_FALSE(tz.prev_transition(tp, &trans));
01117 
01118   tp = time_point<absl::time_internal::cctz::seconds>::min();
01119   EXPECT_FALSE(tz.prev_transition(tp, &trans));
01120 }
01121 
01122 TEST(NextTransition, AmericaNewYork) {
01123   const auto tz = LoadZone("America/New_York");
01124   time_zone::civil_transition trans;
01125 
01126   auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz);
01127   EXPECT_TRUE(tz.next_transition(tp, &trans));
01128   EXPECT_EQ(civil_second(2018, 11, 4, 2, 0, 0), trans.from);
01129   EXPECT_EQ(civil_second(2018, 11, 4, 1, 0, 0), trans.to);
01130 
01131   tp = time_point<absl::time_internal::cctz::seconds>::max();
01132   EXPECT_FALSE(tz.next_transition(tp, &trans));
01133 
01134   tp = time_point<absl::time_internal::cctz::seconds>::min();
01135   EXPECT_TRUE(tz.next_transition(tp, &trans));
01136   if (trans.from == civil_second(1918, 3, 31, 2, 0, 0)) {
01137     // It looks like the tzdata is only 32 bit (probably macOS),
01138     // which bottoms out at 1901-12-13T20:45:52+00:00.
01139     EXPECT_EQ(civil_second(1918, 3, 31, 3, 0, 0), trans.to);
01140   } else {
01141     EXPECT_EQ(civil_second(1883, 11, 18, 12, 3, 58), trans.from);
01142     EXPECT_EQ(civil_second(1883, 11, 18, 12, 0, 0), trans.to);
01143   }
01144 }
01145 
01146 TEST(PrevTransition, AmericaNewYork) {
01147   const auto tz = LoadZone("America/New_York");
01148   time_zone::civil_transition trans;
01149 
01150   auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz);
01151   EXPECT_TRUE(tz.prev_transition(tp, &trans));
01152   EXPECT_EQ(civil_second(2018, 3, 11, 2, 0, 0), trans.from);
01153   EXPECT_EQ(civil_second(2018, 3, 11, 3, 0, 0), trans.to);
01154 
01155   tp = time_point<absl::time_internal::cctz::seconds>::min();
01156   EXPECT_FALSE(tz.prev_transition(tp, &trans));
01157 
01158   tp = time_point<absl::time_internal::cctz::seconds>::max();
01159   EXPECT_TRUE(tz.prev_transition(tp, &trans));
01160   // We have a transition but we don't know which one.
01161 }
01162 
01163 TEST(TimeZoneEdgeCase, AmericaNewYork) {
01164   const time_zone tz = LoadZone("America/New_York");
01165 
01166   // Spring 1:59:59 -> 3:00:00
01167   auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz);
01168   ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -5 * 3600, false, "EST");
01169   tp += absl::time_internal::cctz::seconds(1);
01170   ExpectTime(tp, tz, 2013, 3, 10, 3, 0, 0, -4 * 3600, true, "EDT");
01171 
01172   // Fall 1:59:59 -> 1:00:00
01173   tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz);
01174   ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -4 * 3600, true, "EDT");
01175   tp += absl::time_internal::cctz::seconds(1);
01176   ExpectTime(tp, tz, 2013, 11, 3, 1, 0, 0, -5 * 3600, false, "EST");
01177 }
01178 
01179 TEST(TimeZoneEdgeCase, AmericaLosAngeles) {
01180   const time_zone tz = LoadZone("America/Los_Angeles");
01181 
01182   // Spring 1:59:59 -> 3:00:00
01183   auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz);
01184   ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -8 * 3600, false, "PST");
01185   tp += absl::time_internal::cctz::seconds(1);
01186   ExpectTime(tp, tz, 2013, 3, 10, 3, 0, 0, -7 * 3600, true, "PDT");
01187 
01188   // Fall 1:59:59 -> 1:00:00
01189   tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz);
01190   ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -7 * 3600, true, "PDT");
01191   tp += absl::time_internal::cctz::seconds(1);
01192   ExpectTime(tp, tz, 2013, 11, 3, 1, 0, 0, -8 * 3600, false, "PST");
01193 }
01194 
01195 TEST(TimeZoneEdgeCase, ArizonaNoTransition) {
01196   const time_zone tz = LoadZone("America/Phoenix");
01197 
01198   // No transition in Spring.
01199   auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz);
01200   ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -7 * 3600, false, "MST");
01201   tp += absl::time_internal::cctz::seconds(1);
01202   ExpectTime(tp, tz, 2013, 3, 10, 2, 0, 0, -7 * 3600, false, "MST");
01203 
01204   // No transition in Fall.
01205   tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz);
01206   ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -7 * 3600, false, "MST");
01207   tp += absl::time_internal::cctz::seconds(1);
01208   ExpectTime(tp, tz, 2013, 11, 3, 2, 0, 0, -7 * 3600, false, "MST");
01209 }
01210 
01211 TEST(TimeZoneEdgeCase, AsiaKathmandu) {
01212   const time_zone tz = LoadZone("Asia/Kathmandu");
01213 
01214   // A non-DST offset change from +0530 to +0545
01215   //
01216   //   504901799 == Tue, 31 Dec 1985 23:59:59 +0530 (+0530)
01217   //   504901800 == Wed,  1 Jan 1986 00:15:00 +0545 (+0545)
01218   auto tp = convert(civil_second(1985, 12, 31, 23, 59, 59), tz);
01219   ExpectTime(tp, tz, 1985, 12, 31, 23, 59, 59, 5.5 * 3600, false, "+0530");
01220   tp += absl::time_internal::cctz::seconds(1);
01221   ExpectTime(tp, tz, 1986, 1, 1, 0, 15, 0, 5.75 * 3600, false, "+0545");
01222 }
01223 
01224 TEST(TimeZoneEdgeCase, PacificChatham) {
01225   const time_zone tz = LoadZone("Pacific/Chatham");
01226 
01227   // One-hour DST offset changes, but at atypical values
01228   //
01229   //   1365256799 == Sun,  7 Apr 2013 03:44:59 +1345 (+1345)
01230   //   1365256800 == Sun,  7 Apr 2013 02:45:00 +1245 (+1245)
01231   auto tp = convert(civil_second(2013, 4, 7, 3, 44, 59), tz);
01232   ExpectTime(tp, tz, 2013, 4, 7, 3, 44, 59, 13.75 * 3600, true, "+1345");
01233   tp += absl::time_internal::cctz::seconds(1);
01234   ExpectTime(tp, tz, 2013, 4, 7, 2, 45, 0, 12.75 * 3600, false, "+1245");
01235 
01236   //   1380376799 == Sun, 29 Sep 2013 02:44:59 +1245 (+1245)
01237   //   1380376800 == Sun, 29 Sep 2013 03:45:00 +1345 (+1345)
01238   tp = convert(civil_second(2013, 9, 29, 2, 44, 59), tz);
01239   ExpectTime(tp, tz, 2013, 9, 29, 2, 44, 59, 12.75 * 3600, false, "+1245");
01240   tp += absl::time_internal::cctz::seconds(1);
01241   ExpectTime(tp, tz, 2013, 9, 29, 3, 45, 0, 13.75 * 3600, true, "+1345");
01242 }
01243 
01244 TEST(TimeZoneEdgeCase, AustraliaLordHowe) {
01245   const time_zone tz = LoadZone("Australia/Lord_Howe");
01246 
01247   // Half-hour DST offset changes
01248   //
01249   //   1365260399 == Sun,  7 Apr 2013 01:59:59 +1100 (+11)
01250   //   1365260400 == Sun,  7 Apr 2013 01:30:00 +1030 (+1030)
01251   auto tp = convert(civil_second(2013, 4, 7, 1, 59, 59), tz);
01252   ExpectTime(tp, tz, 2013, 4, 7, 1, 59, 59, 11 * 3600, true, "+11");
01253   tp += absl::time_internal::cctz::seconds(1);
01254   ExpectTime(tp, tz, 2013, 4, 7, 1, 30, 0, 10.5 * 3600, false, "+1030");
01255 
01256   //   1380986999 == Sun,  6 Oct 2013 01:59:59 +1030 (+1030)
01257   //   1380987000 == Sun,  6 Oct 2013 02:30:00 +1100 (+11)
01258   tp = convert(civil_second(2013, 10, 6, 1, 59, 59), tz);
01259   ExpectTime(tp, tz, 2013, 10, 6, 1, 59, 59, 10.5 * 3600, false, "+1030");
01260   tp += absl::time_internal::cctz::seconds(1);
01261   ExpectTime(tp, tz, 2013, 10, 6, 2, 30, 0, 11 * 3600, true, "+11");
01262 }
01263 
01264 TEST(TimeZoneEdgeCase, PacificApia) {
01265   const time_zone tz = LoadZone("Pacific/Apia");
01266 
01267   // At the end of December 2011, Samoa jumped forward by one day,
01268   // skipping 30 December from the local calendar, when the nation
01269   // moved to the west of the International Date Line.
01270   //
01271   // A one-day, non-DST offset change
01272   //
01273   //   1325239199 == Thu, 29 Dec 2011 23:59:59 -1000 (-10)
01274   //   1325239200 == Sat, 31 Dec 2011 00:00:00 +1400 (+14)
01275   auto tp = convert(civil_second(2011, 12, 29, 23, 59, 59), tz);
01276   ExpectTime(tp, tz, 2011, 12, 29, 23, 59, 59, -10 * 3600, true, "-10");
01277   EXPECT_EQ(363, get_yearday(civil_day(convert(tp, tz))));
01278   tp += absl::time_internal::cctz::seconds(1);
01279   ExpectTime(tp, tz, 2011, 12, 31, 0, 0, 0, 14 * 3600, true, "+14");
01280   EXPECT_EQ(365, get_yearday(civil_day(convert(tp, tz))));
01281 }
01282 
01283 TEST(TimeZoneEdgeCase, AfricaCairo) {
01284   const time_zone tz = LoadZone("Africa/Cairo");
01285 
01286   if (VersionCmp(tz, "2014c") >= 0) {
01287     // An interesting case of midnight not existing.
01288     //
01289     //   1400191199 == Thu, 15 May 2014 23:59:59 +0200 (EET)
01290     //   1400191200 == Fri, 16 May 2014 01:00:00 +0300 (EEST)
01291     auto tp = convert(civil_second(2014, 5, 15, 23, 59, 59), tz);
01292     ExpectTime(tp, tz, 2014, 5, 15, 23, 59, 59, 2 * 3600, false, "EET");
01293     tp += absl::time_internal::cctz::seconds(1);
01294     ExpectTime(tp, tz, 2014, 5, 16, 1, 0, 0, 3 * 3600, true, "EEST");
01295   }
01296 }
01297 
01298 TEST(TimeZoneEdgeCase, AfricaMonrovia) {
01299   const time_zone tz = LoadZone("Africa/Monrovia");
01300 
01301   if (VersionCmp(tz, "2017b") >= 0) {
01302     // Strange offset change -00:44:30 -> +00:00:00 (non-DST)
01303     //
01304     //   63593069 == Thu,  6 Jan 1972 23:59:59 -0044 (MMT)
01305     //   63593070 == Fri,  7 Jan 1972 00:44:30 +0000 (GMT)
01306     auto tp = convert(civil_second(1972, 1, 6, 23, 59, 59), tz);
01307     ExpectTime(tp, tz, 1972, 1, 6, 23, 59, 59, -44.5 * 60, false, "MMT");
01308     tp += absl::time_internal::cctz::seconds(1);
01309     ExpectTime(tp, tz, 1972, 1, 7, 0, 44, 30, 0 * 60, false, "GMT");
01310   }
01311 }
01312 
01313 TEST(TimeZoneEdgeCase, AmericaJamaica) {
01314   // Jamaica discontinued DST transitions in 1983, and is now at a
01315   // constant -0500.  This makes it an interesting edge-case target.
01316   // Note that the 32-bit times used in a (tzh_version == 0) zoneinfo
01317   // file cannot represent the abbreviation-only transition of 1890,
01318   // so we ignore the abbreviation by expecting what we received.
01319   const time_zone tz = LoadZone("America/Jamaica");
01320 
01321   // Before the first transition.
01322   if (!tz.version().empty() && VersionCmp(tz, "2018d") >= 0) {
01323     // We avoid the expectations on the -18430 offset below unless we are
01324     // certain we have commit 907241e (Fix off-by-1 error for Jamaica and
01325     // T&C before 1913) from 2018d.  TODO: Remove the "version() not empty"
01326     // part when 2018d is generally available from /usr/share/zoneinfo.
01327     auto tp = convert(civil_second(1889, 12, 31, 0, 0, 0), tz);
01328     ExpectTime(tp, tz, 1889, 12, 31, 0, 0, 0, -18430, false,
01329                tz.lookup(tp).abbr);
01330 
01331     // Over the first (abbreviation-change only) transition.
01332     //   -2524503170 == Tue, 31 Dec 1889 23:59:59 -0507 (LMT)
01333     //   -2524503169 == Wed,  1 Jan 1890 00:00:00 -0507 (KMT)
01334     tp = convert(civil_second(1889, 12, 31, 23, 59, 59), tz);
01335     ExpectTime(tp, tz, 1889, 12, 31, 23, 59, 59, -18430, false,
01336                tz.lookup(tp).abbr);
01337     tp += absl::time_internal::cctz::seconds(1);
01338     ExpectTime(tp, tz, 1890, 1, 1, 0, 0, 0, -18430, false, "KMT");
01339   }
01340 
01341   // Over the last (DST) transition.
01342   //     436341599 == Sun, 30 Oct 1983 01:59:59 -0400 (EDT)
01343   //     436341600 == Sun, 30 Oct 1983 01:00:00 -0500 (EST)
01344   auto tp = convert(civil_second(1983, 10, 30, 1, 59, 59), tz);
01345   ExpectTime(tp, tz, 1983, 10, 30, 1, 59, 59, -4 * 3600, true, "EDT");
01346   tp += absl::time_internal::cctz::seconds(1);
01347   ExpectTime(tp, tz, 1983, 10, 30, 1, 0, 0, -5 * 3600, false, "EST");
01348 
01349   // After the last transition.
01350   tp = convert(civil_second(1983, 12, 31, 23, 59, 59), tz);
01351   ExpectTime(tp, tz, 1983, 12, 31, 23, 59, 59, -5 * 3600, false, "EST");
01352 }
01353 
01354 TEST(TimeZoneEdgeCase, WET) {
01355   // Cover some non-existent times within forward transitions.
01356   const time_zone tz = LoadZone("WET");
01357 
01358   // Before the first transition.
01359   auto tp = convert(civil_second(1977, 1, 1, 0, 0, 0), tz);
01360   ExpectTime(tp, tz, 1977, 1, 1, 0, 0, 0, 0, false, "WET");
01361 
01362   // Over the first transition.
01363   //     228877199 == Sun,  3 Apr 1977 00:59:59 +0000 (WET)
01364   //     228877200 == Sun,  3 Apr 1977 02:00:00 +0100 (WEST)
01365   tp = convert(civil_second(1977, 4, 3, 0, 59, 59), tz);
01366   ExpectTime(tp, tz, 1977, 4, 3, 0, 59, 59, 0, false, "WET");
01367   tp += absl::time_internal::cctz::seconds(1);
01368   ExpectTime(tp, tz, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST");
01369 
01370   // A non-existent time within the first transition.
01371   time_zone::civil_lookup cl1 = tz.lookup(civil_second(1977, 4, 3, 1, 15, 0));
01372   EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl1.kind);
01373   ExpectTime(cl1.pre, tz, 1977, 4, 3, 2, 15, 0, 1 * 3600, true, "WEST");
01374   ExpectTime(cl1.trans, tz, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST");
01375   ExpectTime(cl1.post, tz, 1977, 4, 3, 0, 15, 0, 0 * 3600, false, "WET");
01376 
01377   // A non-existent time within the second forward transition.
01378   time_zone::civil_lookup cl2 = tz.lookup(civil_second(1978, 4, 2, 1, 15, 0));
01379   EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl2.kind);
01380   ExpectTime(cl2.pre, tz, 1978, 4, 2, 2, 15, 0, 1 * 3600, true, "WEST");
01381   ExpectTime(cl2.trans, tz, 1978, 4, 2, 2, 0, 0, 1 * 3600, true, "WEST");
01382   ExpectTime(cl2.post, tz, 1978, 4, 2, 0, 15, 0, 0 * 3600, false, "WET");
01383 }
01384 
01385 TEST(TimeZoneEdgeCase, FixedOffsets) {
01386   const time_zone gmtm5 = LoadZone("Etc/GMT+5");  // -0500
01387   auto tp = convert(civil_second(1970, 1, 1, 0, 0, 0), gmtm5);
01388   ExpectTime(tp, gmtm5, 1970, 1, 1, 0, 0, 0, -5 * 3600, false, "-05");
01389   EXPECT_EQ(chrono::system_clock::from_time_t(5 * 3600), tp);
01390 
01391   const time_zone gmtp5 = LoadZone("Etc/GMT-5");  // +0500
01392   tp = convert(civil_second(1970, 1, 1, 0, 0, 0), gmtp5);
01393   ExpectTime(tp, gmtp5, 1970, 1, 1, 0, 0, 0, 5 * 3600, false, "+05");
01394   EXPECT_EQ(chrono::system_clock::from_time_t(-5 * 3600), tp);
01395 }
01396 
01397 TEST(TimeZoneEdgeCase, NegativeYear) {
01398   // Tests transition from year 0 (aka 1BCE) to year -1.
01399   const time_zone tz = utc_time_zone();
01400   auto tp = convert(civil_second(0, 1, 1, 0, 0, 0), tz);
01401   ExpectTime(tp, tz, 0, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC");
01402   EXPECT_EQ(weekday::saturday, get_weekday(civil_day(convert(tp, tz))));
01403   tp -= absl::time_internal::cctz::seconds(1);
01404   ExpectTime(tp, tz, -1, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC");
01405   EXPECT_EQ(weekday::friday, get_weekday(civil_day(convert(tp, tz))));
01406 }
01407 
01408 TEST(TimeZoneEdgeCase, UTC32bitLimit) {
01409   const time_zone tz = utc_time_zone();
01410 
01411   // Limits of signed 32-bit time_t
01412   //
01413   //   2147483647 == Tue, 19 Jan 2038 03:14:07 +0000 (UTC)
01414   //   2147483648 == Tue, 19 Jan 2038 03:14:08 +0000 (UTC)
01415   auto tp = convert(civil_second(2038, 1, 19, 3, 14, 7), tz);
01416   ExpectTime(tp, tz, 2038, 1, 19, 3, 14, 7, 0 * 3600, false, "UTC");
01417   tp += absl::time_internal::cctz::seconds(1);
01418   ExpectTime(tp, tz, 2038, 1, 19, 3, 14, 8, 0 * 3600, false, "UTC");
01419 }
01420 
01421 TEST(TimeZoneEdgeCase, UTC5DigitYear) {
01422   const time_zone tz = utc_time_zone();
01423 
01424   // Rollover to 5-digit year
01425   //
01426   //   253402300799 == Fri, 31 Dec 9999 23:59:59 +0000 (UTC)
01427   //   253402300800 == Sat,  1 Jan 1000 00:00:00 +0000 (UTC)
01428   auto tp = convert(civil_second(9999, 12, 31, 23, 59, 59), tz);
01429   ExpectTime(tp, tz, 9999, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC");
01430   tp += absl::time_internal::cctz::seconds(1);
01431   ExpectTime(tp, tz, 10000, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC");
01432 }
01433 
01434 }  // namespace cctz
01435 }  // namespace time_internal
01436 }  // namespace absl


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15