Improve "Obtaining a time_point from y/m/d hⓂ️s components"

ajneu
2017-12-06 23:40:23 +01:00
parent 85dc536b7f
commit 50be3e67b4

@@ -526,23 +526,105 @@ which currently outputs `2016f`.
<a name="time_point_to_components"></a>
### Obtaining a `time_point` from `y/m/d h:m:s` components
(by [ecorm](https://github.com/ecorm))
See http://stackoverflow.com/questions/31711782.
#### Date/time, interpreted as UTC
Converting a date/time, interpreted as UTC
```cpp
struct DateTime { // hold date/time (interpreted as UTC), to be converted to time_point
int year;
int month;
int day;
int hour = 0;
int min = 0;
int sec = 0;
};
```c++
using namespace std::chrono;
using namespace date;
// Component values (as obtained from an UI form, for example)
int y=2015, m=7, d=30, h=12, min=34, s=56;
auto ymd = year(y)/m/d; // Yields a year_month_day type
if (!ymd.ok())
throw std::runtime_error("Invalid date");
system_clock::time_point tp = sys_days(ymd) +
hours(h) + minutes(min) + seconds(s);
DateTime datetime{2016 /*year*/, 12 /*month*/, 24 /*day*/, 23 /* hour */, 0 /* min */, 0 /*sec*/}; // variable definition
```
Alternatively, using `struct tm` to hold the components:
to a `std::chrono::system_clock::time_point`, can be done with the following function:
```cpp
// convert date/time from UTC, to time_point
std::chrono::system_clock::time_point datetime_utc_to_timepoint(const DateTime &dt) // note: this function does NOT need the tz library and header
{
using namespace std::chrono;
using namespace date;
auto ymd = year(dt.year)/dt.month/dt.day; // year_month_day type
if (!ymd.ok()) { throw std::runtime_error("Invalid date"); }
return sys_days(ymd) + hours(dt.hour) + minutes(dt.min) + seconds(dt.sec);
}
```
To print a `std::chrono::system_clock::time_point`, getting back a UTC date/time, the following can be used:
```cpp
std::cout << "Date/Time is ";
date::operator<<(std::cout, tp) << std::endl;
// or
using date::operator<<;
std::cout << "Date/Time is " << tp << std::endl;
// It will print the following
// Date/Time is 2016-12-24 23:00:00.000000000
```
The above needs only the `"date/date.h"` header. (`"date/tz.h"` header and tz library are not needed).
#### Date/time, interpreted as coming from a specific time-zone
If the date/time is taken as being from a specific time-zone, then "date/tz.h" header and tz library are needed:
```cpp
//// convert date/time from tzone, to time_point
std::chrono::system_clock::time_point datetime_to_timepoint(const DateTime &dt, const date::time_zone* tzone)
{
using namespace std::chrono;
using namespace date;
auto ymd = year(dt.year)/dt.month/dt.day; // year_month_day type
if (!ymd.ok()) { throw std::runtime_error("Invalid date"); }
return make_zoned(tzone, local_days{ymd} + hours(dt.hour) + minutes(dt.min) + seconds(dt.sec)).get_sys_time();
}
```
The above function can be called as follows
```cpp
DateTime datetime{2016 /*year*/, 12 /*month*/, 24 /*day*/, 23 /* hour */, 0 /* min */, 0 /*sec*/}; // variable definition
using date::operator<<;
auto tp = datetime_to_timepoint(datetime, date::current_zone()); // datetime from local timezone
std::cout << tp << std::endl;
std::cout << date::make_zoned("UTC", tp) << std::endl;
std::cout << date::make_zoned(date::current_zone(), tp) << std::endl;
std::cout << date::make_zoned(date::locate_zone("Europe/Moscow"), tp) << std::endl;
// Will print e.g. (if you're in CET timezone...)
// 2016-12-24 22:00:00.000000000
// 2016-12-24 22:00:00.000000000 UTC
// 2016-12-24 23:00:00.000000000 CET
// 2016-12-25 01:00:00.000000000 MSK
auto tp2 = datetime_to_timepoint(datetime, date::locate_zone("America/New_York")); // datetime from New York
std::cout << tp2 << std::endl;
std::cout << date::make_zoned("UTC", tp2) << std::endl;
std::cout << date::make_zoned(date::current_zone(), tp2) << std::endl;
std::cout << date::make_zoned(date::locate_zone("Europe/Moscow"), tp2) << std::endl;
// Will print
// 2016-12-25 04:00:00.000000000
// 2016-12-25 04:00:00.000000000 UTC
// 2016-12-25 05:00:00.000000000 CET // e.g. (if you're in CET timezone...)
// 2016-12-25 07:00:00.000000000 MSK
```
#### `struct tm` holding the components
If you have a `struct tm` holding the components (as UTC), the following function sets a `time_point`:
```c++
// Ignores tm_isdst!