c++oding="utf-8" ?>
std::chrono::leap_second 在 c++20 中仅为满足时钟概念的占位类型,不提供闰秒查询功能;真正闰秒数据需从 iers 官方文件解析获取。

std::chrono::leap_second 不能查询历史上所有闰秒 —— 它在 C++20 中仅作为占位类型存在,不提供任何获取闰秒列表的接口,也不包含闰秒数据。
为什么 std::chrono::leap_second 看起来像能查闰秒,实际却不能?
C++20 引入 std::chrono::leap_second 主要是为了支持日历类型(如 sys_days)与 UTC 时间的对齐语义,但它本身不是“闰秒数据库”。标准只要求它满足时钟类型的部分概念(如可被 time_point 使用),并未规定其必须携带或暴露闰秒事件信息。
常见误解来源:
- 看到名字里有 “leap_second”,误以为是闰秒查询工具
- 查文档发现它有
operator+和operator-,以为能“跳到下一个闰秒” - 某些编译器(如 libc++)内部用闰秒表实现
utc_clock转换,但该表不对外暴露
真正可用的闰秒数据来源只有 IERS 文件
国际地球自转服务(IERS)以文本文件形式发布权威闰秒记录,最新版本始终在:https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list
这个文件是纯文本,每行格式为:
2272060800 # 1972-01-01 00:00:00 TAI = 1971-12-31 23:59:42 UTC 2287785600 # 1972-07-01 00:00:00 TAI = 1972-06-30 23:59:42 UTC
其中第一列是 TAI 时间戳(单位:秒,起始为 1900-01-01 00:00:00),对应每次闰秒插入时刻(UTC 时间比 TAI 少该值减去固定偏移)。
实操建议:
- 运行时下载并解析该文件(注意 HTTPS 和缓存策略)
- 静态编译进程序:用脚本预处理成 C++ 数组(例如
constexpr std::array<:int64_t n></:int64_t>) - 别尝试用
std::chrono::leap_second构造或比较 —— 它没有time_since_epoch()成员,也不能隐式转为时间点
用 C++ 解析闰秒文件的最小可行代码
以下片段只依赖标准库(C++17 起),读取本地 leap-seconds.list 并提取所有 TAI 时间戳:
#include <fstream>
#include <vector>
#include <string>
#include <sstream><p>std::vector<:int64_t> load_leap_seconds(const char* path) {
std::vector<:int64_t> result;
std::ifstream f(path);
std::string line;
while (std::getline(f, line)) {
if (line.empty() || line[0] == '#') continue;
std::istringstream iss(line);
std::int64_t tai_sec;
if (iss >> tai_sec) result.push_back(tai_sec);
}
return result;
}</:int64_t></:int64_t></p></sstream></string></vector></fstream>
注意:
- 该文件末尾通常含校验行(如
@ # …),需跳过非数字开头的行 - IERS 每 6 个月更新一次,生产环境应定期检查更新(文件头部有版本号和到期时间)
- 若需将 TAI 秒转换为 UTC 日期,必须结合闰秒总数做偏移计算 ——
std::chrono的utc_clock在 C++20 中已支持此转换,但前提是系统时区数据库(tzdb)已加载闰秒表(glibc / musl 默认不启用)
真正棘手的地方不在解析,而在于:闰秒发生时刻的 UTC 时间无法仅靠 std::chrono 推导出来;你得自己维护 TAI ↔ UTC 偏移量随时间变化的阶梯函数。标准没帮你藏这个逻辑。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











