diff --git a/Examples-and-Recipes.md b/Examples-and-Recipes.md index f952c2b..52d6086 100644 --- a/Examples-and-Recipes.md +++ b/Examples-and-Recipes.md @@ -1614,31 +1614,33 @@ and then the solution is simple. To convert PST to -08:00 is in general non-triv Once we have a string of form 2), give this sample code a try (thank you [Aaron](https://github.com/ahn6) who provided the draft): - #include - #include - #include - #include "tz.h" +```c++ +#include +#include +#include +#include "tz.h" - int main() - { - using namespace std; - using namespace date; +int main() +{ + using namespace std; + using namespace date; - istringstream inputStream{ "1999-10-31 01:30:00 -08:00 US/Pacific" }; - - // Using local_seconds would resolve in ambiguous date exception - sys_seconds tp; - string tz_name; - inputStream >> parse("%F %T %Ez %Z", tp, tz_name); + istringstream inputStream{ "1999-10-31 01:30:00 -08:00 US/Pacific" }; - // bool operator tells us whether stream was successfully parsed - assert(bool(inputStream)); + // Using local_seconds would resolve in ambiguous date exception + sys_seconds tp; + string tz_name; + inputStream >> parse("%F %T %Ez %Z", tp, tz_name); - auto zt = make_zoned(tz_name, tp); + // bool operator tells us whether stream was successfully parsed + assert(bool(inputStream)); - // 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'; - } + auto zt = make_zoned(tz_name, tp); + + // 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'; +} +``` *** @@ -1650,60 +1652,62 @@ There is now functionality to parse the original format: 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" +```c++ +#include +#include +#include +#include "tz.h" - int main() +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) { - 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'; + 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.