std::chrono不处理闰秒,所有标准时钟均忽略闰秒,依赖外部库(如date)或手动查表实现UTC/TAI转换。

std::chrono 不处理闰秒,它基于系统时钟(通常是 UTC),但完全不感知闰秒存在。
std::chrono 的时钟类型都不支持闰秒
所有标准时钟 —— std::chrono::system_clock、std::chrono::steady_clock、std::chrono::high_resolution_clock —— 都是单调或近似 UTC 的实现,但 C++ 标准明确回避了闰秒语义:
-
system_clock通常映射到 POSIXclock_gettime(CLOCK_REALTIME, ...)或 WindowsGetSystemTimeAsFileTime(),二者都跳过闰秒(即“smear”或直接忽略) - 没有
std::chrono::tai_clock或std::chrono::utc_clock(C++20 及之前标准) - 即使系统底层使用 TAI(如某些 NTP 服务器),
system_clock::time_point仍按“Unix 时间戳”解释:自 1970-01-01T00:00:00 UTC 起的秒数(不含闰秒)
闰秒发生时 std::chrono 的实际行为
以 2016 年末的闰秒(UTC 23:59:60)为例:
- Linux 系统通常采用“重复秒”策略:
23:59:60→23:59:60→00:00:00,但clock_gettime(CLOCK_REALTIME)多数发行版会“抹平”(smear),让这一秒被拉长或跳过 -
system_clock::to_time_t()和system_clock::from_time_t()无法表示23:59:60—— 它们只接受struct tm中tm_sec ∈ [0, 60),而60是 POSIX 允许的闰秒值,但std::chrono的转换函数不校验或处理该值 - 若你用
std::put_time格式化一个恰好落在闰秒窗口内的time_t,结果取决于 libc 实现(glibc 支持tm_sec == 60,但std::chrono不保证传入合法值)
需要 TAI/UTC 对齐时怎么办?
标准库无解,必须依赖外部数据和手动校正:
立即学习“C++免费学习笔记(深入)”;
- 闰秒表是离散、人工发布的(如 IERS Bulletin C),需定期更新本地数据库(如
leap-seconds.list) - 可用第三方库辅助:
–
date库(Howard Hinnant)提供date和utc_clock,并内置截至编译时的闰秒表 – 示例:将 TAI 时间转为带闰秒的 UTC 字符串需显式调用tai_clock(内部查表) - 自行实现需注意:TAI = UTC + 总闰秒数;而总闰秒数随时间分段变化(不是固定偏移),必须做时间点查表而非简单加减
#include "date/tz.h" using namespace date; auto tai_tp = tai_clock::now(); auto utc_tp = utc_clock::from_tai(tai_tp); // 查表计算 UTC 偏移 std::cout << utc_tp << '\n'; // 输出含闰秒语义的 UTC 时间
真正棘手的不是“怎么转”,而是“谁负责更新闰秒表”和“系统时钟是否已 smear”。生产环境若需亚秒级 UTC 对齐(如天文、金融时间戳),不能只靠 date::utc_clock::to_sys()。











