std::chrono::leap_second 是 C++20 中仅作模板参数占位符的空标记类型,无构造函数、数据成员或闰秒信息;查询历史闰秒需依赖 tzdb 或 Howard Hinnant's date 库等外部数据源。

std::chrono::leap_second 不能用于查询历史闰秒 —— 它在 C++20 中仅是一个空的、不可实例化的标记类型,不携带任何时间点或闰秒数据。
为什么 std::chrono::leap_second 没有闰秒信息
C++20 标准引入 std::chrono::leap_second 的唯一目的是作为模板参数的占位符(例如用于区分 utc_clock 和 system_clock),它本身不含构造函数、静态成员或数据。标准未要求其实现存储闰秒表,也没有提供访问 IERS 公布的闰秒列表的接口。
- 它不是闰秒事件的表示,也不是时间点类型
- 所有主流实现(libstdc++、libc++、MSVC STL)都将其定义为
struct leap_second {}; - 试图取地址、构造或序列化它都会编译失败
真正能查历史闰秒的替代方案
要获取 IERS 发布的历次闰秒(如 1972–2025 年共 27 次),必须依赖外部数据源或专用库:
-
tzdb(C++20<chrono>中的时区数据库)包含闰秒表,但仅用于utc_clock::to_sys_time()等内部转换,不提供公开 API 查询指定日期是否为闰秒时刻 -
Howard Hinnant's date library(事实上的 C++ 时区/历法扩展)通过date::get_tzdb().leap_seconds暴露只读的std::vector<date::leap_second>,其中每个元素含date::sys_seconds和修正值 - 手动加载 IERS 官方
leap-seconds.list(文本格式,需解析):路径通常为/usr/share/zoneinfo/leap-seconds.list或从 ietf.org 下载
用 date 库安全读取闰秒列表(推荐实操)
假设已通过 vcpkg/conan 引入 date(>=3.0.1),以下代码可列出全部已知闰秒生效时间点:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
#include <date/date.h>
#include <iostream>
#include <vector>
int main() {
const auto& ls = date::get_tzdb().leap_seconds;
for (const auto& l : ls) {
std::cout << date::format("%F %T", l.date) << " (+" << l.total << ")\n";
}
}
注意:l.date 是 UTC 时间点(sys_seconds),对应闰秒插入前的最后一秒;l.total 是到该点为止累计的正闰秒总数(IERS 不使用负闰秒)。
- 首次调用
get_tzdb()会自动解析系统时区数据库,若无leap-seconds.list则leap_seconds为空 - 该列表只反映编译/运行时 tzdb 版本所含的闰秒,不会自动更新 —— 需定期更新
zoneinfo包 - 不要尝试用
leap_second类型自己构造时间点:它和std::chrono::leap_second同名但属于不同命名空间,且 date 库的leap_second是具体结构体
闰秒处理的关键不在类型名,而在时区数据库的完整性和时效性;别被 std::chrono::leap_second 的名字误导,它只是个类型标签,不是数据容器。

















