This works:
year_month_day day() {
return year_month_day(floor<days>(
zoned_time{
zone,
system_clock::now()
}.get_local_time()));
}
But I need to floor()
the zoned_time
, as above - since that's templated on the duration, I'd expect to be able to floor either that, or the result of now()
, i.e. do this:
year_month_day day2() {
return year_month_day(
zoned_time{
zone,
floor<days>(system_clock::now())
}.get_local_time());
}
So I'm puzzled as to why I get the following error when I try that - should the zoned_time
above not be in units of days, and so fine to convert to a year_month_day
?
error: no matching function for call to ‘std::chrono::year_month_day::year_month_day(std::chrono::local_time<std::chrono::duration<long int> >)’
48 | }.get_local_time());
I'm using g++ (GCC) 14.2.1 20240912 (Red Hat 14.2.1-3)
(called as c++
) with -std=gnu++20
.
year_month_day
can convert from a time point with a precision of days. That time point can be based on system_clock
or local_t
. But in either case, it must have a precision of days
.
The reverse conversion can also be made, and when done, results in exactly the same time point as the original. This is known as a lossless conversion. Information is conserved.
If conversions were allowed from a time point with precision finer than days
, say seconds
, then this would be a lossy conversion and break one of the fundamental design principles of chrono: You can't loose information implicitly. You must explicitly request a lossy conversion with expressions such as floor
.
This sub-expression:
floor<days>(system_clock::now())
creates a days
-precision time_point
based on system_clock
. So far so good.
This sub-expression:
zoned_time{
zone,
floor<days>(system_clock::now())
}.get_local_time()
takes that days
-precision time_point
and adds the associated time_zone
's UTC offset to it to compute the local time. The UTC offset from the IANA time zone database has units of seconds
. And if you add seconds
to a days
-precision time_point
the result is a seconds
-precision time_point
. And this seconds
-precision time_point
can not be directly converted to a year_month_day
.
All of the above is the type system turning a potential run-time error into a compile-time error. If the lossy conversion were allowed, it would sometimes give the wrong answer.
For example, let's say the UTC offset is 5h, and the current system_clock
time of day (UTC) is 20h. The correct local time (before the floor) is 01:00 the next day: floor<days>(20h + 5h)
gives the next day.
But if one instead computed floor<days>(20h) + 5h
you would get 05:00 of the same day (one-off error).