Updated Examples and Recipes (markdown)

Howard Hinnant
2017-04-20 16:38:53 -04:00
parent 988ec745b2
commit 7dd89c5173

@@ -302,6 +302,7 @@ This library can query the installed IANA timezone database for its version numb
Here is how you get the version of the installed IANA timezone database:
```c++
#include "tz.h"
#include <iostream>
@@ -310,6 +311,7 @@ Here is how you get the version of the installed IANA timezone database:
{
std::cout << date::get_tzdb().version << '\n';
}
```
As I write this, the output is:
@@ -317,7 +319,9 @@ As I write this, the output is:
If the remote API is enabled ([`HAS_REMOTE_API == 1`](https://howardhinnant.github.io/date/tz.html#Installation)) then you can also query the latest version number at the IANA website with:
```c++
std::cout << date::remote_version() << '\n';
```
which currently outputs `2016f`.
@@ -423,6 +427,7 @@ std::cout << t.tm_year << "-" << t.tm_mon << "-" << t.tm_day << " ";
The following function will "normalize" a `year_month_day`, much like `mktime` normalizes a `tm`. This function is not part of the library, but is offered as an example if you find yourself needing things like this:
```c++
date::year_month_day
normalize(date::year_month_day ymd)
{
@@ -431,6 +436,7 @@ The following function will "normalize" a `year_month_day`, much like `mktime` n
ymd = sys_days{ymd};
return ymd;
}
```
The first line simply adds 0 months to the `ymd`. If `ymd.month()` is 0, this will subtract one from the `year` and set the month to `Dec`. If `ymd.month()` is greater than 12, the year will be incremented as many times as appropriate, and the month will be brought within the proper range. This operation will do nothing if `ymd.month().ok()` is already true.
@@ -446,6 +452,7 @@ http://howardhinnant.github.io/date_algorithms.html#civil_from_days
Example:
```c++
int
main()
{
@@ -457,6 +464,7 @@ Example:
ymd = sys_days{ymd};
std::cout << ymd << (ymd.ok() ? "\n" : " invalid date\n");
}
```
Outputs:
@@ -476,6 +484,7 @@ 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:
```c++
std::pair<std::array<date::year_month_day, 5>, unsigned>
fifth_friday(date::year y)
{
@@ -496,6 +505,7 @@ I want to find all dates for some year `y` which are the 5th Friday of the month
}
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.
@@ -503,12 +513,15 @@ The first job is just to initialize the `array` with a bunch of `year_month_day`
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:
```c++
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:
```c++
int
main()
{
@@ -520,6 +533,7 @@ This function can be exercised like this:
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:
@@ -548,6 +562,7 @@ Given a `year_month_day`, and a day of the week, how to I efficiently increment
This is very easy. But first you have to decide: If the `year_month_day` is already the desired `weekday`, do you want to return the original `year_month_day` or add a week? There is no one right answer. We'll do it both ways here. First I'll show how to keep the original. It is then an easy modification to show how to jump to the next week.
```c++
date::year_month_day
next_weekday(date::year_month_day ymd, date::weekday target)
{
@@ -555,6 +570,7 @@ This is very easy. But first you have to decide: If the `year_month_day` is al
sys_days sd = ymd;
return sd + (target - weekday{sd});
}
```
The first thing to do is to convert the `year_month_day` to a `sys_days`. This is done because it is very efficient to find the day of the week of a `sys_days` (count of days), and to do day-oriented arithmetic on that data structure.
@@ -564,6 +580,7 @@ Above if `target == weekday{sd}`, then we don't add any days at all because `ymd
If we want to add a week when the input is already at the target weekday, then you just add a day to `sd` prior to the algorithm:
```c++
date::year_month_day
next_weekday(date::year_month_day ymd, date::weekday target)
{
@@ -572,9 +589,11 @@ If we want to add a week when the input is already at the target weekday, then y
sd += days{1};
return sd + (target - weekday{sd});
}
```
The reverse is similar:
```c++
date::year_month_day
prev_weekday(date::year_month_day ymd, date::weekday target)
{
@@ -583,6 +602,7 @@ The reverse is similar:
sd -= days{1};
return sd - (weekday{sd} - target);
}
```
Except now we're subtracting weekdays to find out how many days to subtract from `sd`. Remove the pre-decrement by a day if you want this function to return the input when the input is already at the target weekday.
@@ -592,12 +612,14 @@ Except now we're subtracting weekdays to find out how many days to subtract from
CCSDS (http://public.ccsds.org/default.aspx) has a data structure that looks like this:
```c++
struct CCSDS
{
std::uint16_t days;
std::uint32_t ms;
std::uint16_t us;
};
```
where `days` is the number of days since Jan 1, 1958, `ms` is the count of milliseconds of the current day, and `us` is the count of microseconds of the current millisecond.
@@ -605,6 +627,7 @@ A need arose to convert a {year, microsecond} data structure to the above CCSDS
Here is a function to perform that conversion:
```c++
CCSDS
to_CCSDS(date::year y, std::chrono::microseconds us)
{
@@ -621,6 +644,7 @@ Here is a function to perform that conversion:
static_cast<std::uint32_t>(ms.count()),
static_cast<std::uint16_t>(us.count())};
}
```
The variable `utc` holds the “year + us” as a time point with microseconds precision. This time point counts microseconds, including leap seconds, since 1970-01-01 00:00:00 UTC.
@@ -638,8 +662,10 @@ http://stackoverflow.com/q/19290421/576911
And I decided to see if I could answer it (here) using this library. The question asks: How can I get the number of months between two dates? And it gives two example dates:
```c++
auto d1 = 1_d/oct/2013;
auto d2 = 30_d/oct/2016;
```
(I've converted the syntax to that of this library).