闰秒和std::chrono

3
我查看了cppreference.org (重点标注如下):
`std::chrono::utc_clock` 是表示协调世界时(UTC)的时钟。它测量自 1970 年 1 月 1 日,周四,00:00:00 UTC 后经过的时间, 包括闰秒。
与 `system_clock` 的定义进行比较:
`system_clock` 测量Unix时间(即自 1970 年 1 月 1 日,星期四,00:00:00 协调世界时(UTC)起, 不包括闰秒)。
在同一个系统中同时使用它们实际上是否可能?例如,如果通过 NTP 同步系统时钟,则服务器决定时间,该时间可以使用闰秒或不使用闰秒,但 C++ 库实现可能无法知道任何有关此问题的信息。或者,标准是否要求有一个数据库来记录何时引入闰秒?

2
在同一系统中同时拥有两者是否真的可能?等等,不在同一系统中没有两者是可能的吗?那么tai_clockgps_clockfile_clock呢?为什么utc_clock如此特殊?标准是否要求数据库记录闰秒的引入时间?嗯,它有点这样要求 - KamilCuk
1
简而言之,是的,除非平台有其他跳秒信息来源。IANA时区数据库包括跳秒插入列表。而标准是否要求使用数据库来确定跳秒引入时间呢? - Howard Hinnant
@KamilCuk 那个文件只包括到2008年的闰秒,但是自那以后已经有一些了。那是文件的当前版本吗? - Jerry Jeremiah
这是文件的当前版本吗?是和不是。不,这不是最新版本的文件,那个仓库是某个人使用的旧版本。Glibc源代码可从https://www.gnu.org/software/libc/sources.html获取。然而,glibc源代码中的秒数只有到2008年。IANA https://www.iana.org/time-zones具有最新的数据,在tar.gz中有最新的闰秒,应该分发到Linux上的`/usr/share/zoneinfo/leapseconds`。 - KamilCuk
2个回答

3
NTP服务器提供以秒为单位的协调世界时(自1900年以来的秒数格式)。当前时间就是当前时间。无论有多少闰秒,都不会影响到它。当添加一个闰秒时,事情就变得复杂了。NTP会在那一刻宣布这个闰秒,各种操作系统会在内部做出各种记录,因为它们倾向于将时间存储为“自纪元以来的秒数” - Linux和Windows不包括闰秒,因为这会使它们的时间戳呈现更加复杂(有多少闰秒?),而它们不能处理。相反,它们只是在宣布的闰秒周围短暂地减慢或加快时钟,因此它们只是调整自己的秒数计数,以便稍后呈现该计数作为时间戳时看起来准确。system_clock给你这个秒数计数,这个计数(在主流平台上)直接来自操作系统(例如time())。

utc_clock提供类似的秒数计数,但是这个计数是“真实的”。在这样的主流平台上,必须使用system_clock,然后在事后添加闰秒。这些历史数据也来自于系统,确切的来源取决于实现方式some kind of database

总之,两个时钟的数据源略有不同,因此它们可以在同一系统上共存的问题并不成立。但是,system_clock很可能直接来自您的操作系统,而utc_clock则很可能不是。

进一步阅读


1
示例实现从IANA时区数据库获取其闰秒插入列表,并在转换utc_timesys_time之间使用该列表。 utc_time最有用的是在跨越闰秒插入的time_point差异计算中包含闰秒。 - Howard Hinnant
据我理解,这就是链接的glibc存储库获取它们的地方。 - Lightness Races in Orbit
就此而言,那个代码库已经过时了。这里有一个方便的列表,会被及时更新:https://en.wikipedia.org/wiki/Leap_second - Howard Hinnant
NTP的当前版本由RFC 5905定义。计算机专家撰写的有关闰秒的散文是不可信的;我更喜欢看数字。在第14页,RFC给出了1972年1月1日(2,272,060,800)和1999年12月31日(3,155,587,200)的时间戳。如果NTP时间戳包括闰秒,则后一个数字将为3,155,587,222。 - Gerard Ashton

2
我找到了有关C++20时间方面的工作草案,预计于公元2020年发布。其中包括一个有关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()

而最终值为"946'684'822s,即10'957 * 86'400s + 22s"。注意,10,957天约为30年,因此utc_clock的值显然表示自1970年1月1日UTC以来的秒数,每个闰秒增加了utc_clock的值。
既然这是一种转换,那么推断该转换将调用闰秒表,并且即使操作系统没有区分UTC和TAI的概念,也没有包含61秒的概念,也可以执行该转换。
我必须承认,我对时间比对C++更感兴趣,近20年来几乎没有写过严肃的C++代码。

你推断得很正确。请注意还有一个 tai_clock,甚至还有一个 gps_clock,并且可以在它们之间进行 clock_cast 的能力。 - Howard Hinnant
你可以在这里找到所有这些的一个示例实现:https://github.com/HowardHinnant/date - Howard Hinnant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接