diff --git a/Examples-and-Recipes.md b/Examples-and-Recipes.md index 7874512..bc19f30 100644 --- a/Examples-and-Recipes.md +++ b/Examples-and-Recipes.md @@ -526,23 +526,105 @@ which currently outputs `2016f`. ### 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!