Reputation: 2137
I fast read the C++ reference about new chrono classes but I found them a little bit complicated.
So, the question is, how to re-write this code in C++20, to get year, month, day, hour, minute, second?
Are there any changes? I ask because of this minor problem with std::localtime
: It is thread-unsafe. tm
will be destroyed after next call to std::localtime
.
std::time_t t = std::time(nullptr);
std::tm *tm = std::localtime(&t);
int year = tm->tm_year + 1900;
int month = tm->tm_mon + 1;
int day = tm->tm_mday;
int hour = tm->tm_hour;
int minute = tm->tm_min;
int second = tm->tm_sec;
Upvotes: 5
Views: 2733
Reputation: 218750
#include <chrono>
int
main()
{
using namespace std::chrono;
// Get a local time_point with system_clock::duration precision
auto now = zoned_time{current_zone(), system_clock::now()}.get_local_time();
// Get a local time_point with days precision
auto ld = floor<days>(now);
// Convert local days-precision time_point to a local {y, m, d} calendar
year_month_day ymd{ld};
// Split time since local midnight into {h, m, s, subseconds}
hh_mm_ss hms{now - ld};
// This part not recommended. Stay within the chrono type system.
int year{ymd.year()};
int month = unsigned{ymd.month()};
int day = unsigned{ymd.day()};
int hour = hms.hours().count();
int minute = hms.minutes().count();
int second = hms.seconds().count();
}
I've tried to explain what each line of code does with a comment. I'm happy to elaborate further if anything is not clear.
This is all threadsafe.
More information:
Another and perhaps even more concise way to compute now
is:
auto now = current_zone()->to_local(system_clock::now());
This results in the exact same type and value for now
.
I used zoned_time
above because it is (in general) a higher-level abstraction than calling member functions of a time_zone
directly. In both examples the type of now
is a simple std::chrono::time_point
that is offset from system_clock::time_point
by the UTC offset associated with the time_zone
at this point in time.
In contrast zoned_time
carries much more information. For example it knows about:
time_zone
.time_zone
at this point in time.time_zone
at this point in time, and subsequently can produce both the local time and the UTC equivalent time.Therefore a zoned_time
is much more flexible for jobs like formatting as it can display the abbreviation and/or the UTC offset. And a zoned_time
can also be more easily used to find out the equivalent time in other time zones.
Nevertheless, all of that extra information isn't actually used in this simple example, and is thus why I'm exposing the alternative of calling the to_local()
member function of time_zone
directly.
For the simple case of finding the local time, both techniques have identical behavior and performance, so it comes down to a matter of readability for choosing the preferred approach.
Upvotes: 8