Updated Examples and Recipes (markdown)

Howard Hinnant
2016-05-29 22:34:04 -04:00
parent f580e3e093
commit 4318716ed2

@@ -4,6 +4,7 @@ This page contains examples and recipes contributed by community members. Feel f
- [Obtaining a `time_point` from `y/m/d h:m:s` components](#time_point_to_components)
- [Obtaining `y/m/d h:m:s` components from a `time_point`](#components_to_time_point)
- [Normalizing `y/m/d` when it is `!ok()`](#normalize)
- [When is it ok to be `!ok()`?](#not_ok_is_ok)
- [Converting from {year, microseconds} to CCSDS](#ccsds)
- [Difference in months between two dates](#deltamonths)
- [Parsing ISO strings](http://stackoverflow.com/a/33438989/576911)
@@ -157,6 +158,79 @@ Outputs:
The specifications for these functions do not yet guarantee this "normalization behavior." But the implementation has been thoroughly tested for this behavior and the specification will be updated soon.
<a name="not_ok_is_ok"></a>
### When is it ok to be `!ok()`?
(by [Howard Hinnant](https://github.com/HowardHinnant))
This library allows dates to silently fall into a state of `!ok()`. Why does not `!ok()` assert or throw? When is it *ever* ok to be `!ok()`?
Consider this problem:
I want to find all dates for some year `y` which are the 5th Friday of the month (because that is party day or whatever). Here is a **very** efficient function which collects all of the 5th Fridays of a year:
std::pair<std::array<date::year_month_day, 5>, unsigned>
fifth_friday(date::year y)
{
using namespace date;
std::array<year_month_day, 5> dates{0_y/0/0, 0_y/0/0, 0_y/0/0, 0_y/0/0, 0_y/0/0};
unsigned n = 0;
for (auto m = jan; true; ++m)
{
auto d = fri[5]/m/y;
if (d.ok())
{
dates[n] = year_month_day{d};
++n;
}
if (m == dec)
break;
}
return {dates, n};
}
It turns out that it is an invariant that *every* year will have either 4 or 5 months which will have 5 Fridays. So we can efficiently return the results as a `pair<array<year_month_day, 5>, unsigned>`, where the second member of the `pair` will always be either 4 or 5.
The first job is just to initialize the `array` with a bunch of `year_month_day`s. I've arbitrarily chosen `0_y/0/0` as a good initialization value. What do I like about this value? One of the things I like is that it is `!ok()`!. If I accidentally access `.first[4]` when `.second == 4`, an extra bit of safety is that the resultant `year_month_day` is `!ok()`. So being able to construct these `!ok()` values without an assert or exception is important just for that reason (like a `nan`). The cost? Nothing. These are compile-time constants.
Next I iterate over each month for the year `y`. The first thing to do is construct the 5th Friday for this month/year pair:
auto d = fri[5]/m/y;
Now since not every month has a 5th Friday, this may not result in a valid date. But in this function the proper response to constructing an invalid date _is not_ an assert nor an exception. The _proper_ response is to _ignore_ the date and iterate on to the next month. If it is a valid date, then it pushed on to the result.
This function can be exercised like this:
int
main()
{
using namespace std::chrono;
using namespace date;
auto current_year = year_month_day{floor<days>(system_clock::now())}.year();
auto dates = fifth_friday(current_year);
std::cout << "Fifth Friday dates for " << current_year << " are:\n";
for (auto i = 0u; i < dates.second; ++i)
std::cout << dates.first[i] << '\n';
}
The variable `current_year` is initialized with the current year in the UTC time zone (close enough for government work -- use "tz.h" if you need to make it more exact to your locale). Then it is a simple matter to feed `current_year` into `fifth_friday` and iterate over the results. This just output for me:
Fifth Friday dates for 2016 are:
2016-01-29
2016-04-29
2016-07-29
2016-09-30
2016-12-30
Next year it will output:
Fifth Friday dates for 2017 are:
2017-03-31
2017-06-30
2017-09-29
2017-12-29
_Many_ invalid dates were computed during the execution of this program. And _none_ of them represented errors.
<a name="ccsds"></a>
### Converting from {year, microseconds} to CCSDS
(by [Howard Hinnant](https://github.com/HowardHinnant))