闰秒和 std::chrono

Leap seconds and std::chrono

我看了一下cppreference.org(强调我的):

The clock std::chrono::utc_clock is a Clock that represents Coordinated Universal Time (UTC). It measures time since 00:00:00 UTC, Thursday, 1 January 1970, including leap seconds.

将其与 system_clock 的定义进行比较:

system_clock measures Unix Time (i.e., time since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970, not counting leap seconds).

是否真的可以在同一个系统中同时使用两者?例如,如果系统时钟是通过 NTP 同步的,那么服务器会决定现在几点,可以使用闰秒或不使用闰秒,但 C++ 库实现对此一无所知。或者,该标准是否需要有关何时引入闰秒的数据库?

NTP 服务器为您提供 UTC(seconds-since-1900 格式)。当前时间,就是当前时间。为了到达那里有多少闰秒并不重要。

事情变得复杂的地方是添加闰秒。 NTP 将在此刻宣布这一点,并且各种操作系统会在内部做各种事情来记录这一点,因为它们倾向于将时间存储为 "number of seconds since an epoch" — Linux 和 Windows 不包括 leap秒,因为这会使他们的时间戳渲染更加复杂(有多少闰秒?)并且他们无法处理。相反,他们只是在宣布的闰秒前后将时钟放慢或加快了一小会儿,所以他们并没有实际记录它,而是调整了自己的seconds-count,因此将计数作为时间戳渲染后会显得准确。

(我不知道 OS 如何在不知道要扣除多少闰秒的情况下从 NTP 事务中重新确定其 not-really-but-sort-of-seconds 计数;欢迎编辑。 )

system_clock 为您提供秒数,(在主流平台上)直接来自 OS(例如 time())。

utc_clock 给你一个类似的秒数,但是是 "real"。在这样的主流平台上,这必然是 system_clock 添加了闰秒 after-the-fact。此历史数据也来自系统,确实 some kind of database(尽管确切来源取决于实现)。

总之,两个时钟的数据源(略)不同,所以不存在是否可以在同一个系统上co-exist的问题。但是,system_clock 可能 直接来自您的操作系统,utc_clock 可能 不会.

进一步阅读

我发现 this working draft about time for C++ 20, which seems to be due out in AD 2020. It has a subpage about utc_clock 其中包括这个例子:

clock_­cast<utc_­clock>(sys_­seconds{sys_­days{1970y/January/1}}).time_­since_­epoch() is 0s.
clock_­cast<utc_­clock>(sys_­seconds{sys_­days{2000y/January/1}}).time_­since_­epoch()

并说明最后一个值 "is 946'684'822s, which is 10'957 * 86'400s + 22s." 请注意,10,957 天大约是 30 年,因此 utc_clock 的值显然表示自 1970 年 1 月 1 日 UTC 以来的秒数,其中每个闰秒都会增加utc_clock.

由于这是表示为转换,因此推断转换会调用 table 闰秒似乎是合理的,并且即使操作系统不知道 UTC 之间的区别也可以执行和TAI,并没有包含61秒的一分钟的概念。

我必须承认我对时间比 C++ 更感兴趣,近 20 年来没有写过正经的 C++ 代码。