mirror of
https://github.com/HowardHinnant/date.git
synced 2025-08-03 20:54:27 +02:00
Improve "Obtaining a time_point
from y/m/d hⓂ️s
components"
@@ -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!
|
||||
|
Reference in New Issue
Block a user