diff --git a/Examples-and-Recipes.md b/Examples-and-Recipes.md
index e64b20b..89fc731 100644
--- a/Examples-and-Recipes.md
+++ b/Examples-and-Recipes.md
@@ -10,6 +10,7 @@ This page contains examples and recipes contributed by community members. Feel f
- [Working with the ISO week-based year](#iso_week)
- [2Gs Birthday](#birthday2gs)
- [Calculating Ordinal Dates](#year_day)
+- [Convert a time zone abbreviation into a time zone](#convert_by_timezone_abbreviation)
- [Find all instances when a daylight savings shift is not 1 hour](#tz_search)
- [How many timezones are using daylight saving?](#tz_daylight)
@@ -360,6 +361,142 @@ An [ordinal date](https://en.wikipedia.org/wiki/Ordinal_date) consists of a year
assert(ymd == year_month_day{sys_days{year/jan/0} + year_day});
}
+
+### Convert a time zone abbreviation into a time zone
+(by [Howard Hinnant](https://github.com/HowardHinnant))
+
+It is well known that converting a time zone abbreviation into a time zone is in general a difficult task. Not only do time zones keep changing what abbreviation they are using, but the abbreviations in use are not unique. At any given time multiple time zones could be using the exact same abbreviation. And not all of these time zones will always have the same UTC offset.
+
+If nothing else, this operation can be extremely confusing and error prone. You should strive to not find yourself in the situation of needing to perform this operation. However, if you are forced into it, this library provides solutions that you can program yourself, which are superior to all other solutions.
+
+To illustrate, this example develops `find_by_abbrev` functions which return a `std::vector>`. The client can then iterate over this list and inspect each `zoned_time` and output all information of interest to the client. Presumably some of this information can be used to choose a unique time zone.
+
+To begin, let's say we have a date/time: `2016-04-03 03:15`, and an abbreviation "CST". We want to find all possible time zones which might be using "CST" at `2016-04-03 03:15`.
+
+First problem: Is `2016-04-03 03:15` a time local to the time zone, or is it UTC? The answer to this question can make a difference in the results, so we need to be clear about what we're asking for. Both questions are valid: What time zones are using "CST" at this instant? What time zones have a local `time_point` `t` which uses "CST"?
+
+So we need two `find_by_abbrev`: One which takes a `sys_time`, and one which takes a `local_time`. Let's do `sys_time` first:
+
+ #include "tz.h"
+ #include
+ #include
+ #include
+
+ template
+ std::vector>>
+ find_by_abbrev(date::sys_time tp, const std::string& abbrev)
+ {
+ using namespace std::chrono;
+ using namespace date;
+ std::vector>> results;
+ auto& db = get_tzdb();
+ for (auto& z : db.zones)
+ {
+ if (z.get_info(tp).abbrev == abbrev)
+ results.push_back(make_zoned(&z, tp));
+ }
+ return results;
+ }
+
+ int
+ main()
+ {
+ using namespace std::chrono;
+ using namespace date;
+ auto now = sys_days{2016_y/4/3} + 3h + 15min;
+ auto v = find_by_abbrev(now, "CST");
+ for (auto const& zt : v)
+ std::cout << zt << " " << zt.get_time_zone()->name() << '\n';
+ }
+
+The `find_by_abbrev` function is surprisingly simple: Loop over all `time_zone`s in the database, get the `sys_info` for each one at time `tp`, and if that `sys_info` has an abbreviation equal to `abbrev`, create a `zoned_time` for this `time_zone` and `tp` and append it to the `vector`. The most complicated part is figuring out the precision of the duration of the `zoned_time` which is going be the finer of `seconds` and `Duration`. The facility `std::common_type` figures that out for us.
+
+This program outputs:
+
+ 2016-04-02 21:15:00 CST America/Bahia_Banderas
+ 2016-04-02 21:15:00 CST America/Belize
+ 2016-04-02 21:15:00 CST America/Costa_Rica
+ 2016-04-02 21:15:00 CST America/El_Salvador
+ 2016-04-02 21:15:00 CST America/Guatemala
+ 2016-04-02 21:15:00 CST America/Managua
+ 2016-04-02 21:15:00 CST America/Merida
+ 2016-04-02 21:15:00 CST America/Mexico_City
+ 2016-04-02 21:15:00 CST America/Monterrey
+ 2016-04-02 21:15:00 CST America/Regina
+ 2016-04-02 21:15:00 CST America/Swift_Current
+ 2016-04-02 21:15:00 CST America/Tegucigalpa
+ 2016-04-03 11:15:00 CST Asia/Macau
+ 2016-04-03 11:15:00 CST Asia/Shanghai
+ 2016-04-03 11:15:00 CST Asia/Taipei
+
+These are all the times and locations using "CST" at `2016-04-03 03:15 UTC`. Note that some of the places are on opposite sides of the planet.
+
+Now the really interesting part of this problem is what happens if we are talking about `2016-04-03 03:15` local time? Around this time of year many regions are switching in/out of daylight saving time. And how do we compute that?
+
+The driver program is identical to that shown above except that instead of:
+
+ auto now = sys_days{2016_y/4/3} + 3h + 15min;
+
+we have:
+
+ auto now = local_days{2016_y/4/3} + 3h + 15min;
+
+The `find_by_abbrev` takes a `local_time` instead of a `sys_time`, and the logic is slightly more complicated:
+
+ template
+ std::vector>>
+ find_by_abbrev(date::local_time tp, const std::string& abbrev)
+ {
+ using namespace std::chrono;
+ using namespace date;
+ std::vector>> results;
+ auto& db = get_tzdb();
+ for (auto& z : db.zones)
+ {
+ auto i = z.get_info(tp);
+ switch (i.result)
+ {
+ case local_info::unique:
+ if (i.first.abbrev == abbrev)
+ results.push_back(make_zoned(&z, tp));
+ break;
+ case local_info::ambiguous:
+ if (i.first.abbrev == abbrev)
+ results.push_back(make_zoned(&z, tp, choose::earliest));
+ else if (i.second.abbrev == abbrev)
+ results.push_back(make_zoned(&z, tp, choose::latest));
+ break;
+ default:
+ break;
+ }
+ }
+ return results;
+ }
+
+A `local_time` may or may not have a unique mapping to UTC. It might be unique, it might be ambiguous, or it might not exist at all. This function discovers if the mapping is unique, ambiguous or non-existent with `i.result`. If it is unique, the logic is exactly as with the `find_by_abbrev` for `sys_time` search. Note that `make_zoned` knows the difference between a `sys_time` and a `local_time`, and always does the right thing.
+
+If the mapping is ambiguous, then there are two potential mappings from `{local time, time zone abbrev}` to UTC. If the first matches up with the abbreviation then the first is selected, else if the second matches up with the abbreviation then the second is selected. Else neither is selected.
+
+If the mapping is non-existent, then it is ignored.
+
+This program outputs:
+
+ 2016-04-03 03:15:00 CST America/Belize
+ 2016-04-03 03:15:00 CST America/Costa_Rica
+ 2016-04-03 03:15:00 CST America/El_Salvador
+ 2016-04-03 03:15:00 CST America/Guatemala
+ 2016-04-03 03:15:00 CST America/Managua
+ 2016-04-03 03:15:00 CST America/Regina
+ 2016-04-03 03:15:00 CST America/Swift_Current
+ 2016-04-03 03:15:00 CST America/Tegucigalpa
+ 2016-04-03 03:15:00 CST Asia/Macau
+ 2016-04-03 03:15:00 CST Asia/Shanghai
+ 2016-04-03 03:15:00 CST Asia/Taipei
+
+Note that *all* local times are now 03:15:00. Also note that this list is a subset of the previous list as by this time, some of the previous time zones have already switched to *another* abbreviation.
+
+How you choose between these time zones is beyond the scope of this library. Perhaps you know a priori that you are dealing with time zones in Asia. Perhaps you know a priori that you are dealing with a time zone in the US. By whatever application-specific logic you have, these functions give you the tools to narrow your search to the *possible* time zones.
+
### Find all instances when a daylight savings shift is not 1 hour
(by [Howard Hinnant](https://github.com/HowardHinnant))