Updated Examples and Recipes (markdown)

Howard Hinnant
2016-07-14 17:52:14 -04:00
parent 14ba7c738c
commit 844b20e436

@@ -5,6 +5,7 @@ This page contains examples and recipes contributed by community members. Feel f
- [The current time somewhere else](#elsetime) - [The current time somewhere else](#elsetime)
- [Get the current difference between any two arbitrary time zones](#deltatz) - [Get the current difference between any two arbitrary time zones](#deltatz)
- [Set simultaneous meeting in two different time zones](#meeting) - [Set simultaneous meeting in two different time zones](#meeting)
- [Get milliseconds since the local midnight](#since_midnight)
- [Obtaining a `time_point` from `y/m/d h:m:s` components](#time_point_to_components) - [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) - [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) - [Normalizing `y/m/d` when it is `!ok()`](#normalize)
@@ -157,6 +158,101 @@ In any event, the output is still:
2016-07-08 09:00:00 EDT 2016-07-08 09:00:00 EDT
2016-07-08 16:00:00 MSK 2016-07-08 16:00:00 MSK
<a name="since_midnight"></a>
### Get milliseconds since the local midnight
(by [Howard Hinnant](https://github.com/HowardHinnant))
After reading this [stack Overflow question/answers](http://stackoverflow.com/q/11128629/576911) I decided it would be good to show how to solve this problem using this library. As the question is not crystal clear what it is asking, I will attempt to create an unambiguous problem statement here:
> Find the time duration in milliseconds since the last midnight in the local time zone.
So that I can more easily test the code to do this, I'm going to write this more generally as:
std::chrono::milliseconds
since_local_midnight(std::chrono::system_clock::time_point t, const date::time_zone* zone);
And then create an overload to pass in the current time and current time zone:
inline
std::chrono::milliseconds
since_local_midnight()
{
return since_local_midnight(std::chrono::system_clock::now(), date::current_zone());
}
That way I can test things like times just after known daylight saving time transitions to make sure that my code is doing what I want it to.
This only takes a few lines of code:
std::chrono::milliseconds
since_local_midnight(std::chrono::system_clock::time_point t, const date::time_zone* zone)
{
using namespace date;
using namespace std::chrono;
auto zt = make_zoned(zone, t);
zt = floor<days>(zt.get_local_time());
return floor<milliseconds>(t - zt.get_sys_time());
}
The first thing to do is create a `zoned_time` which really does nothing at all but pair `zone` and `t`. This pairing is mainly just to make the syntax nicer.
The next step is to get the local time associated with `t`. That is what `zt.get_local_time()` does. This will have whatever precision `t` has, unless `t` is coarser than seconds, in which case the local time will have a precision of seconds.
The call to `floor<days>` _truncates_ the local time to a precision of `days`. This effectively creates a `local_time` equal to the local midnight. By assigning this `local_time` back to `zt`, we don't change the time zone of `zt` at all, but we change the `local_time` of `zt` to midnight (and thus change its `sys_time` as well).
We can get the corresponding `sys_time` out of `zt` with `zt.get_sys_time()`. This is the UTC time which corresponds to the local midnight. It is then an easy process to subtract this from the input `t` and truncate the results to the desired precision.
As a further testing aid, it is convenient to write a `since_local_midnight` that takes a `zoned_seconds` (which is a `zoned_time` with the precision of seconds) that calls into the main overload:
inline
std::chrono::milliseconds
since_local_midnight(const date::zoned_seconds& zt)
{
return since_local_midnight(zt.get_sys_time(), zt.get_time_zone());
}
So to output the current time in milliseconds since the local midnight, you would just:
std::cout << since_local_midnight().count() << "ms\n";
To ensure that our function is working, it is worthwhile to output a few example dates. This is most easily done by specifying a time zone (I'll use "America/New_York"), and some local date/times where I know the right answer:
auto zt = make_zoned(locate_zone("America/New_York"), local_days{jan/15/2016} + 3h);
std::cout << zt << " is " << since_local_midnight(zt).count() << "ms after midnight\n";
This 3am in the middle of the Winter. This outputs:
2016-01-15 03:00:00 EST is 10800000ms after midnight
which is correct (10800000ms == 3h).
I can run the test again just by assigning a new local time to `zt`. The following is 3am just after the "spring forward" daylight saving transition (2nd Sunday in March):
zt = local_days{sun[2]/mar/2016} + 3h;
std::cout << zt << " is " << since_local_midnight(zt).count() << "ms after midnight\n";
This outputs:
2016-03-13 03:00:00 EDT is 7200000ms after midnight
Because the local time from 2am to 3am was skipped, this correctly outputs 2 hours since midnight.
An example from the middle of Summer gets us back to 3 hours after midnight:
zt = local_days{jul/15/2016} + 3h;
std::cout << zt << " is " << since_local_midnight(zt).count() << "ms after midnight\n";
2016-07-15 03:00:00 EDT is 10800000ms after midnight
And finally an example just after the Fall transition from daylight saving back to standard gives us 4 hours:
zt = local_days{sun[1]/nov/2016} + 3h;
std::cout << zt << " is " << since_local_midnight(zt).count() << "ms after midnight\n";
2016-11-06 03:00:00 EST is 14400000ms after midnight
Not only does this library make it easy to write the code to do the desired computation, it also makes it easy to write the test code.
<a name="time_point_to_components"></a> <a name="time_point_to_components"></a>
### Obtaining a `time_point` from `y/m/d h:m:s` components ### Obtaining a `time_point` from `y/m/d h:m:s` components
(by [ecorm](https://github.com/ecorm)) (by [ecorm](https://github.com/ecorm))