diff --git a/Examples-and-Recipes.md b/Examples-and-Recipes.md
index 8aab121..7d47019 100644
--- a/Examples-and-Recipes.md
+++ b/Examples-and-Recipes.md
@@ -5,6 +5,7 @@ This page contains examples and recipes contributed by community members. Feel f
- [The current time somewhere else](#elsetime)
- [Get the current difference between any two arbitrary time zones](#deltatz)
- [Set simultaneous meeting in two different time zones](#meeting)
+- [Interfacing with the C API](#Ccompatiblity)
- [Get milliseconds since the local midnight](#since_midnight)
- [What is my timezone database version?](#version)
- [Obtaining a `time_point` from `y/m/d h:m:s` components](#time_point_to_components)
@@ -179,6 +180,202 @@ In any event, the output is still:
2016-07-08 09:00:00 EDT
2016-07-08 16:00:00 MSK
+
+### Interfacing with the C API
+(by [Howard Hinnant](https://github.com/HowardHinnant))
+
+The goal of this library is to ensure that you never have to bother with the C timing API again. That being said, the real world interrupts my goals sometimes, and one just has to convert to/from a `tm`, or `timespec` now and then for interfacing with somebody else's code that still uses the C timing API. So this note is about how to write those conversion functions:
+
+#### Converting from a `tm`
+
+C allows a `tm` to contain more members than are documented by the C specification. This example assumes only the portable members of `tm`. Hopefully once you understand how to work with the portable members, you will be able to extend your knowledge to the non-portable members for your platform if necessary. The portable `tm` is:
+
+```c++
+struct tm
+{
+ int tm_sec; // seconds after the minute — [0, 60]
+ int tm_min; // minutes after the hour — [0, 59]
+ int tm_hour; // hours since midnight — [0, 23]
+ int tm_mday; // day of the month — [1, 31]
+ int tm_mon; // months since January — [0, 11]
+ int tm_year; // years since 1900
+ int tm_wday; // days since Sunday — [0, 6]
+ int tm_yday; // days since January 1 — [0, 365]
+ int tm_isdst; // Daylight Saving Time flag
+};
+```
+The `tm` struct can be used to hold a UTC time (`sys_time` or `utc_time`), or a local time (`local_time`). However the `tm` does not contain enough information to identify the time zone of a local time, or even the UTC offset (some platforms include a utc offset member as a conforming extension). Additionally the `tm` is limited to seconds precision. This limits what we can convert to. For example it is not possible to convert to a `zoned_time` because there is not enough information to do so. And it only makes sense to convert to a destination with seconds precision. If you want to convert to something with higher precision than that, it is an implicit conversion from the seconds-precision result of these functions.
+
+So we can convert from a `tm` to either a `sys_seconds`, or a `local_seconds`. Here is the first:
+
+```c++
+date::sys_seconds
+to_sys_time(std::tm const& t)
+{
+ using namespace date;
+ using namespace std::chrono;
+ return sys_days{year{t.tm_year + 1900}/(t.tm_mon+1)/t.tm_mday} +
+ hours{t.tm_hour} + minutes{t.tm_min} + seconds{t.tm_sec};
+}
+```
+
+As can be seen, not all of the fields of the `tm` are needed for this conversion. And this conversion assumes that the `tm` represents a UTC time point. The conversion itself is quite straightforward: Convert the year/month/day information into a `sys_days`, and then add the H:M:S information, converting into chrono durations along the way. One has to be careful with the year and month data from `tm` to bias it correctly.
+
+Converting to a `local_seconds` is identical except for the use of `local_days` in place of `sys_days`:
+
+```c++
+date::local_seconds
+to_local_time(std::tm const& t)
+{
+ using namespace date;
+ using namespace std::chrono;
+ return local_days{year{t.tm_year + 1900}/(t.tm_mon+1)/t.tm_mday} +
+ hours{t.tm_hour} + minutes{t.tm_min} + seconds{t.tm_sec};
+}
+```
+
+This can give you a local time in an _as-yet-unspecified_ time zone. One can subsequently pair that `local_time` with a time zone such as `current_zone()` to complete the conversion (assuming `current_zone()` is the correct time zone).
+
+#### Converting to a `tm`
+
+Conversion _to_ a `tm` is a bit more flexible since we generally have more than enough information to fill out the `tm`. Let's start with converting from `zoned_seconds` to a `tm`:
+
+```c++
+std::tm
+to_tm(date::zoned_seconds tp)
+{
+ using namespace date;
+ using namespace std;
+ using namespace std::chrono;
+ auto lt = tp.get_local_time();
+ auto ld = floor(lt);
+ time_of_day tod{lt - ld}; // can be omitted in C++17
+ year_month_day ymd{ld};
+ tm t{};
+ t.tm_sec = tod.seconds().count();
+ t.tm_min = tod.minutes().count();
+ t.tm_hour = tod.hours().count();
+ t.tm_mday = unsigned{ymd.day()};
+ t.tm_mon = unsigned{ymd.month()} - 1;
+ t.tm_year = int{ymd.year()} - 1900;
+ t.tm_wday = unsigned{weekday{ld}};
+ t.tm_yday = (ld - local_days{ymd.year()/jan/1}).count();
+ t.tm_isdst = tp.get_info().save != minutes{0};
+ return t;
+}
+```
+
+A presumption here is that one desires to convert the _local time_ in the `zoned_time` to the `tm`. If that assumption is not the case, we cover putting a UTC time into a `tm` below. So the first thing to do is to get the local time out of the `zoned_seconds` with `tp.get_local_time()`.
+
+Next we truncate the `local_seconds` into `local_days` using the `floor(lt)` function. Now we have two `local_time` `time_point`s, one with a precision of seconds, and the other with a precision of days. The days-precision `time_point` can be explicitly converted to a `year_month_day` object so that we can retrieve the year, month and day fields.
+
+The time of day is just the difference between the seconds-precision `time_point` and the days-precision `time_point`, which gives us the seconds since midnight. This duration can be broken down into a `{hours, minutes, seconds}` struct by converting it to a `time_of_day`. In C++17 the `` template parameter will be deduced by the seconds-presion duration used in the constructor.
+
+Now we just start filling out the `tm`, being careful to bias the month and year correctly. It is also good practice to first zero the entire `tm` so as to zero-out any platform-specific fields of the `tm`.
+
+The `weekday` encoding of this library is the same encoding used in C, and so that conversion is straight forward, going from `local_days`, to `weekday`, to `unsigned`, and finally to `int`.
+
+The computation for days-since-Jan 1 is found by simply subtracting the expression for New Years day for the current year from the already stored `local_days` value.
+
+Finally we can set `tm_isdst` to 1 if the `save` member of `sys_info` is not `0min`, and to 0 otherwise. The `sys_info` can be obtained from the `zoned_seconds`, and contains all kinds of useful information (including the UTC offset should you want to install that into your platform-specific `tm`).
+
+If we want to convert from a `sys_seconds` to a `tm`, that is quite easy to do using the conversion function above:
+
+```c++
+std::tm
+to_tm(date::sys_seconds tp)
+{
+ return to_tm(date::zoned_seconds{tp});
+}
+```
+
+This creates a `zoned_time`, and defaults the `time_zone` to "UTC", then passes that `zoned_time` to `to_tm`. If desired, one could repeat the code from `zoned_seconds` instead of reuse it. This would save a small amount of processing time involved in looking up "UTC" in the database. And in this event you would always set `t.tm_isdst` to 0. One would also use `sys_days` in place of `local_days` in this alternative.
+
+One can also create a `tm` from `local_seconds`:
+
+```c++
+std::tm
+to_tm(date::local_seconds tp)
+{
+ auto tm = to_tm(date::sys_seconds{tp.time_since_epoch()});
+ tm.tm_isdst = -1;
+ return tm;
+}
+```
+
+In this variant, the `time_zone` is unknown, and thus `-1` is the proper value for `tm.tm_isdst`.
+
+#### Converting from a `timespec`
+
+`timespec` is new in the latest C specification. It contains at least the following members in any order:
+
+```c++
+struct timespec
+{
+ time_t tv_sec; // whole seconds -- >= 0
+ long tv_nsec; // nanoseconds -- [0, 999999999]
+};
+```
+
+C uses `timespec` as both a time point, and as a time duration. So we should be able to convert to both `nanoseconds` (a `duration`), and `sys_time` (a `time_point`). Both are easy. First to convert to a duration:
+
+```c++
+std::chrono::nanoseconds
+to_nanoseconds(timespec const& ts)
+{
+ using namespace std::chrono;
+ return seconds{ts.tv_sec} + nanoseconds{ts.tv_nsec};
+}
+```
+
+One just converts the integrals to their proper `duration` types and adds them. The result has type `nanoseconds`.
+
+We can resume the above the above function to convert to a `time_point`:
+
+```c++
+date::sys_time
+to_time_point(timespec const& ts)
+{
+ return date::sys_time{to_nanoseconds(ts)};
+}
+```
+
+Just get the duration and explicitly convert it to the proper `time_point`.
+
+#### Converting to a `timespec`
+
+The reverse conversions are only slightly more complex:
+
+```c++
+timespec
+to_timespec(std::chrono::nanoseconds const& d)
+{
+ using namespace std::chrono;
+ timespec ts;
+ seconds s = duration_cast(d);
+ ts.tv_sec = s.count();
+ ts.tv_nsec = (d - s).count();
+ return ts;
+}
+```
+
+First truncate the nanoseconds-precision duration to seconds-precision. That truncated value can be placed into `ts.tv_sec`. Now the difference between the original nanoseconds-precision duration and the seconds-precsion duration is the amount of a nanoseconds left over, and is assigned to `ts.tv_nsec`.
+
+The conversion to a `time_point` follow exactly the same logic, with the syntax being slightly modified to account for the fact that we're working with `time_point`s instead of `duration`s:
+
+```c++
+timespec
+to_timespec(date::sys_time const& tp)
+{
+ using namespace std::chrono;
+ timespec ts;
+ auto tps = time_point_cast(tp);
+ ts.tv_sec = tps.time_since_epoch().count();
+ ts.tv_nsec = (tp - tps).count();
+ return ts;
+}
+```
+
### Get milliseconds since the local midnight
(by [Howard Hinnant](https://github.com/HowardHinnant))
@@ -1955,4 +2152,4 @@ Where some_local_time and some_sys_time are template instantiations of local_tim
***
- _This work is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/)._
+ _This work is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/)._
\ No newline at end of file