std::chrono::leap_second 在 c++20 中不可用,标准未定义该类型,所有主流编译器均不支持;闰秒支持需依赖 howard hinnant 的 date 库,如 date::utc_clock。

std::chrono::leap_second 在 C++20 中根本不可用
直接说结论:std::chrono::leap_second 不是标准 C++ 库的一部分,C++20 标准中 **没有定义这个类型**,任何编译器(包括 GCC 13、Clang 16、MSVC 19.38)都未实现它。你如果在代码里写 std::chrono::leap_second,一定会遇到编译错误,例如:
error: 'leap_second' is not a member of 'std::chrono'
这是个常见误解——有人把提案(P0355R7 等 chrono 扩展草案)当成了已落地特性,或混淆了第三方库(如 Howard Hinnant 的 date 库)的接口。
真正可用的闰秒支持只来自 Howard Hinnant date 库
C++ 标准库至今不提供闰秒感知的时钟或日历计算。唯一成熟、被广泛采用的方案是基于 date::utc_clock 的 date 库(现为 C++20 <chrono></chrono> 的事实参考实现,但需额外链接)。
它通过内置的 IERS 闰秒表(硬编码在 src/leapsecond.cpp 中)提供闰秒支持。关键点:
-
date::utc_clock是闰秒感知的时钟,其time_point表示 UTC 时间(含历史闰秒) -
date::tai_clock表示国际原子时(TAI),与 UTC 有固定偏移(当前为 +37 秒) -
date::sys_clock(即std::chrono::system_clock)仍是 Unix 时间,**不包含闰秒**
示例:获取 2016-12-31 23:59:60(最后一个已知闰秒时刻)的 UTC 时间点:
auto ls = date::sys_days{date::December/31/2016} + 23h + 59min + 60s;<br>// ❌ 错误:sys_clock 不支持 60 秒<br><br>auto ls_utc = date::utc_clock::time_point{<br> date::sys_days{date::December/31/2016} + 23h + 59min + 59s<br>} + 1s; // ✅ 正确:UTC 时间点可跨过闰秒
为什么标准库不加 leap_second?
这不是技术做不到,而是设计取舍:
- 闰秒由 IERS 临时宣布(通常提前 6 个月),标准库无法保证运行时数据更新
- 绝大多数系统(Linux、Windows)内核和 libc 实际以“ smear ”(闰秒抹平)或“跳变”方式处理,不暴露闰秒细节
-
std::chrono定位是“精确时间间隔计算”,而非“高保真 UTC 日历”;引入闰秒会破坏duration的单调性和可预测性 - POSIX 和大多数 API(如
clock_gettime(CLOCK_REALTIME))返回的是 TAI 或抹平后的秒数,非原始 UTC
实际项目中该怎么选?
除非你在开发天文台、卫星测控或金融高频时间戳系统,否则不要尝试手动处理闰秒。绝大多数场景应:
- 用
std::chrono::system_clock做计时、超时、性能测量(它稳定、快、无歧义) - 用
date::utc_clock仅当明确需要与 UTC 日历对齐(如日志时间戳、合规审计) - 避免跨 UTC/TAI/system_clock 混用
time_point,转换必须显式调用date::clock_cast - 注意:date 库的闰秒表截止到 2025 年底,之后需手动更新或切换到在线 IERS 查询(date 库本身不自动联网)
闰秒不是“多一秒那么简单”,它是整个时间栈的契约断裂点。标准库选择沉默,是最务实的答案。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











