mirror of
https://github.com/HowardHinnant/date.git
synced 2025-08-05 13:44:26 +02:00
Updated Examples and Recipes (markdown)
@@ -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))
|
||||||
|
Reference in New Issue
Block a user