#include "date/tz.h" #include void test_info(const date::time_zone* zone, const date::sys_info& info) { using namespace date; using namespace std::chrono; auto begin = info.begin; auto end = info.end - microseconds{1}; auto mid = begin + (end - begin) /2; using sys_microseconds = date::sys_time; using zoned_microseconds = zoned_time; zoned_microseconds local{zone}; if (begin > sys_days{jan/1/1700}) { auto prev_local = local; local = begin; prev_local = begin - seconds{1}; auto slocal = local.get_local_time(); auto plocal = prev_local.get_local_time(); if (plocal < slocal - seconds{1}) { assert(sys_microseconds{local} == begin); try { local = plocal + (slocal - seconds{1} - plocal) / 2; assert(false); } catch (const nonexistent_local_time&) { } } else if (plocal > slocal - seconds{1}) { try { local = slocal - seconds{1} + (plocal - (slocal - seconds{1})) / 2; assert(false); } catch (const ambiguous_local_time&) { } } } local = mid; assert(sys_microseconds{local} == mid); if (end < sys_days{jan/1/3000}) { local = end; auto next_local = local; next_local = info.end; auto slocal = local.get_local_time(); auto nlocal = next_local.get_local_time(); if (nlocal < slocal + microseconds{1}) { try { local = nlocal + (slocal + microseconds{1} - nlocal) / 2; assert(false); } catch (const ambiguous_local_time&) { } } else if (nlocal > slocal + microseconds{1}) { assert(sys_microseconds{local} == end); try { local = slocal + microseconds{1} + (nlocal - (slocal + microseconds{1})) / 2; assert(false); } catch (const nonexistent_local_time&) { } } } } void tzmain() { using namespace date; using namespace std::chrono; auto& db = get_tzdb(); std::vector names; #if USE_OS_TZDB names.reserve(db.zones.size()); for (auto& zone : db.zones) names.push_back(zone.name()); #else // !USE_OS_TZDB names.reserve(db.zones.size() + db.links.size()); for (auto& zone : db.zones) names.push_back(zone.name()); for (auto& link : db.links) names.push_back(link.name()); std::sort(names.begin(), names.end()); #endif // !USE_OS_TZDB std::cout << db.version << "\n\n"; for (auto const& name : names) { std::cout << name << '\n'; auto z = locate_zone(name); auto begin = sys_days(jan/1/date::year::min()) + seconds{0}; auto end = sys_days(jan/1/2035) + seconds{0}; auto info = z->get_info(begin); std::cout << "Initially: "; if (info.offset >= seconds{0}) std::cout << '+'; std::cout << make_time(info.offset); if (info.save == minutes{0}) std::cout << " standard "; else std::cout << " daylight "; std::cout << info.abbrev << '\n'; test_info(z, info); auto prev_offset = info.offset; auto prev_abbrev = info.abbrev; auto prev_save = info.save; for (begin = info.end; begin < end; begin = info.end) { info = z->get_info(begin); test_info(z, info); if (info.offset == prev_offset && info.abbrev == prev_abbrev && info.save == prev_save) continue; auto dp = floor(begin); auto ymd = date::year_month_day(dp); auto time = make_time(begin - dp); std::cout << ymd << ' ' << time << "Z "; if (info.offset >= seconds{0}) std::cout << '+'; std::cout << make_time(info.offset); if (info.save == minutes{0}) std::cout << " standard "; else std::cout << " daylight "; std::cout << info.abbrev << '\n'; prev_offset = info.offset; prev_abbrev = info.abbrev; prev_save = info.save; } std::cout << '\n'; } } int main() { try { tzmain(); } catch(const std::exception& ex) { std::cout << "An exception occured: " << ex.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }