From b2b63744ca5484d8a0220ba41aa4689cdaca1a74 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Mon, 17 Apr 2017 13:16:09 -0400 Subject: [PATCH] Updated Examples and Recipes (markdown) --- Examples-and-Recipes.md | 68 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/Examples-and-Recipes.md b/Examples-and-Recipes.md index f1af552..c6e27a5 100644 --- a/Examples-and-Recipes.md +++ b/Examples-and-Recipes.md @@ -1612,6 +1612,74 @@ Once we have a string of form 2), give this sample code a try (thank you [Aaron] cout << format("%F %T %Ez", zt) << ' ' << zt.get_time_zone()->name() << '\n'; } +*** + +Update from [Howard](https://github.com/HowardHinnant): + +There is now functionality to parse the original format: + + 1) 1999-10-31 01:30:00 US/Pacific PST + +And check if the time zone abbreviation is consistent, and in the ambiguous case, use the time zone abbreviation to disambiguate the time stamp: + + #include + #include + #include + #include "tz.h" + + int main() + { + using namespace std; + using namespace date; + + istringstream inputStream{ "1999-10-31 00:30:00 US/Pacific PST" }; + + // Using local_seconds would resolve in ambiguous date exception + local_seconds tp; + string tz_name; + string tz_abbrev; + inputStream >> parse("%F %T", tp) >> tz_name >> tz_abbrev; + + // bool operator tells us whether stream was successfully parsed + assert(bool(inputStream)); + + // Check for ambiguous and nonexistent timestamps + auto zone = locate_zone(tz_name); + auto info = zone->get_info(tp); + zoned_seconds zt{zone}; + switch (info.result) + { + case local_info::unique: + zt = tp; // easy case + // One can check that the tz_abbrev is consistent with + // info.first.abbrev if desired. + break; + case local_info::nonexistent: + // time stamp never existed. Throw an error? + // Or here is how map to a unique UTC equivalent: + zt = make_zoned(zone, tp, choose::earliest); // choose::latest also + // gives same answer. + break; + case local_info::ambiguous: + // Use tz_abbrev to break the ambiguity + if (info.first.abbrev == tz_abbrev) + zt = make_zoned(zone, tp, choose::earliest); + else if (info.second.abbrev == tz_abbrev) + zt = make_zoned(zone, tp, choose::latest); + else + throw std::runtime_error(tz_abbrev + + " is not a valid abbreviation for " + tz_name); + break; + } + + // This will output America/Los_Angeles, because US/Pacific is an alias of it. + cout << format("%F %T %Ez", zt) << ' ' << zt.get_time_zone()->name() << '\n'; + } + +This involves getting the `local_info` structure from the `time_zone` for that `local_time`. The `local_info` will have all of the information about that `time_zone/local_time` combination, including whether there is a unique mapping to UTC, a non-existing mapping (as in the gap created by "spring forward"), or an ambiguous mapping (created by a local time occurring twice during a "fall back"). + +In the ambiguous case you can view both mappings, including their abbreviations, and compare that to the abbreviation you parsed, and then choose either the earlier mapping, or the later mapping. + ### `microfortnights`?! Are you serious? (by [Howard Hinnant](https://github.com/HowardHinnant))