std::chrono不处理闰秒,所有标准时钟均忽略闰秒,依赖外部库(如date)或手动查表实现UTC/TAI转换。
std::chrono 不处理闰秒,它基于系统时钟(通常是 UTC),但完全不感知闰秒存在。
所有标准时钟 —— std::chrono::system_clock、std::chrono::steady_clock、std::chrono::high_resolution_clock —— 都是单调或近似 UTC 的实现,但 C++ 标准明确回避了闰秒语义:
system_clock 通常映射到 POSIX clock_gettime(CLOCK_REALTIME, ...) 或 Windows GetSystemTimeAsFileTime(),二者都跳过闰秒(即“smear”或直接忽略)std::chrono::tai_clock 或 std::chrono::utc_clock(C++20 及之前标准)system_clock::time_point 仍按“Unix 时间戳”解释
以 2016 年末的闰秒(UTC 23:59:60)为例:
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 不保证传入合法值)标准库无解,必须依赖外部数据和手动校正:
leap-seconds.list)date 库(Howard Hinnant)提供 date 和 utc_clock,并内置截至编译时的闰秒表
– 示例:将 TAI 时间转为带闰秒的 UTC 字符串需显式调用 tai_clock(内部查表)#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()。