Date: Fri, 31 Jan 2025 21:52:33 +0800
It seems to me that you misunderstood the purpose of `utc_clock`,
which is the true UTC clock that is capable of expressing a time point
like 23:59:60 (before 00:00:00). With `utc_clock`, a day can have
86401 seconds (and 86399 seconds, theoretically).
For all practical purposes of interacting with the system clock API
(including `gmtime`), you just need `std::chrono::system_clock`.
Quoting the C++23 standard:
Objects of type system_clock represent wall clock time from the
system-wide realtime clock. Objects of type sys_time<Duration> measure
time since 1970-01-01 00:00:00 UTC excluding leap seconds. This
measure is commonly referred to as Unix time.
In contrast to sys_time, which does not take leap seconds into
account, utc_clock and its associated time_point, utc_time, count
time, including leap seconds, since 1970-01-01 00:00:00 UTC.
The following program shows their difference:
#include <iostream>
#include <chrono>
using namespace std::chrono;
int main()
{
auto stp = sys_seconds{sys_days{2017y / January / 1}};
auto utp = clock_cast<utc_clock>(stp);
std::cout << stp << '\n';
std::cout << stp.time_since_epoch() << '\n';
std::cout << utp << '\n';
std::cout << utp.time_since_epoch() << '\n';
--stp;
--utp;
std::cout << stp << '\n';
std::cout << stp.time_since_epoch() << '\n';
std::cout << utp << '\n';
std::cout << utp.time_since_epoch() << '\n';
}
Result:
2017-01-01 00:00:00
1483228800s
2017-01-01 00:00:00
1483228827s
2016-12-31 23:59:59
1483228799s
2016-12-31 23:59:60
1483228826s
https://godbolt.org/z/dEfo19joT
On Thu, 30 Jan 2025 at 23:14, Enji Cooper (yaneurabeya) via
Std-Discussion <std-discussion_at_[hidden]> wrote:
>
> Hi Jens!
>
> > On Jan 30, 2025, at 2:24 AM, Jens Maurer <jens.maurer_at_[hidden]> wrote:
>
> …
>
> > I'm not finding a mention of "unix_clock" in the standard. What are you talking about?
>
> Good catch — I meant `utc_clock` here (typo).
>
> …
>
> > So, if you want a time_t value for a utc_clock time_point, you need to first
> > convert that time_point to system_clock and then call to_time_t on the latter.
> > There's clock_cast in [time.clock.cast.fn] to do that. Note: This is non-trivial,
> > because the number of UTC leap seconds that have elapsed at the
> > indicated time point need to be queried from some sort of database.
>
> Got it. This part was honestly difficult to figure out given the sparse documentation on the subject. I’ll update my demo program based on the insight you provided in your reply.
>
> At the end of the day what I was trying to figure out was how to use the chrono portion of C++11 (and newer) in place of the C/POSIX libcall, `std::gmtime(..)`.
which is the true UTC clock that is capable of expressing a time point
like 23:59:60 (before 00:00:00). With `utc_clock`, a day can have
86401 seconds (and 86399 seconds, theoretically).
For all practical purposes of interacting with the system clock API
(including `gmtime`), you just need `std::chrono::system_clock`.
Quoting the C++23 standard:
Objects of type system_clock represent wall clock time from the
system-wide realtime clock. Objects of type sys_time<Duration> measure
time since 1970-01-01 00:00:00 UTC excluding leap seconds. This
measure is commonly referred to as Unix time.
In contrast to sys_time, which does not take leap seconds into
account, utc_clock and its associated time_point, utc_time, count
time, including leap seconds, since 1970-01-01 00:00:00 UTC.
The following program shows their difference:
#include <iostream>
#include <chrono>
using namespace std::chrono;
int main()
{
auto stp = sys_seconds{sys_days{2017y / January / 1}};
auto utp = clock_cast<utc_clock>(stp);
std::cout << stp << '\n';
std::cout << stp.time_since_epoch() << '\n';
std::cout << utp << '\n';
std::cout << utp.time_since_epoch() << '\n';
--stp;
--utp;
std::cout << stp << '\n';
std::cout << stp.time_since_epoch() << '\n';
std::cout << utp << '\n';
std::cout << utp.time_since_epoch() << '\n';
}
Result:
2017-01-01 00:00:00
1483228800s
2017-01-01 00:00:00
1483228827s
2016-12-31 23:59:59
1483228799s
2016-12-31 23:59:60
1483228826s
https://godbolt.org/z/dEfo19joT
On Thu, 30 Jan 2025 at 23:14, Enji Cooper (yaneurabeya) via
Std-Discussion <std-discussion_at_[hidden]> wrote:
>
> Hi Jens!
>
> > On Jan 30, 2025, at 2:24 AM, Jens Maurer <jens.maurer_at_[hidden]> wrote:
>
> …
>
> > I'm not finding a mention of "unix_clock" in the standard. What are you talking about?
>
> Good catch — I meant `utc_clock` here (typo).
>
> …
>
> > So, if you want a time_t value for a utc_clock time_point, you need to first
> > convert that time_point to system_clock and then call to_time_t on the latter.
> > There's clock_cast in [time.clock.cast.fn] to do that. Note: This is non-trivial,
> > because the number of UTC leap seconds that have elapsed at the
> > indicated time point need to be queried from some sort of database.
>
> Got it. This part was honestly difficult to figure out given the sparse documentation on the subject. I’ll update my demo program based on the insight you provided in your reply.
>
> At the end of the day what I was trying to figure out was how to use the chrono portion of C++11 (and newer) in place of the C/POSIX libcall, `std::gmtime(..)`.
-- Yongwei Wu URL: http://wyw.dcweb.cn/
Received on 2025-01-31 13:52:47