c++标准库无法识别闰秒日,因闰秒属iers人为调整且std::chrono和time_t采用无闰秒的posix时间;判断需查预存的闰秒日期表(如"2016-12-31"),或借助cctz解析特定时刻,但均依赖外部公告数据。

C++ 标准库中没有“闰秒日”的概念,也不存在直接判断某日是否为闰秒发生日的函数或机制。
为什么 std::chrono 和 std::time_t 无法识别闰秒
公历(格里高利历)本身不定义闰秒;闰秒是国际地球自转服务(IERS)为协调原子时(TAI)与世界时(UT1)而人为插入的调整,属于时间尺度层面的操作,和日历系统无关。C++ 的 std::chrono::system_clock 通常实现为 Unix 时间(即自 1970-01-01 00:00:00 UTC 起的秒数),它隐式采用“平滑的、无闰秒”的 UTC 变体(常称 POSIX time),即把闰秒“抹平”——例如在 2016-12-31 23:59:60 插入闰秒时,system_clock 会将该秒映射为重复的 23:59:59 或跳过 23:59:60,具体行为由底层 C 库(如 glibc)决定,且标准未作规定。
- 所有标准时间类型(
time_t、system_clock::time_point)都不携带闰秒元信息 -
std::put_time、std::get_time等格式化工具只处理日历+时分秒,不校验是否存在 60 秒 - 即使你解析出
"2016-12-31 23:59:60"这样的字符串,标准库也无法将其合法转换为time_t(多数系统返回 -1 或抛异常)
实际可行的替代方案:查表 + 字符串匹配
目前全球公认的闰秒仅发生在 6 月 30 日或 12 月 31 日的 23:59:60(UTC),且 IERS 提前至少 6 周公告。因此,“闰秒日”实质上就是这些公告中列出的特定日期(年-月-日),而非某天内所有时刻都“是闰秒”。判断只需确认该日期是否在已知闰秒生效列表中。
- 维护一个静态的
std::unordered_set<:string></:string>,存入所有已公布的闰秒日期,如"2016-12-31"、"2015-06-30"等(截至 2024 年共 27 次) - 输入日期(如
std::chrono::year_month_day)先格式化为"YYYY-MM-DD"字符串,再查表 - 注意:不要用
std::tm的tm_yday或tm_mon手动计算,易出错;优先用std::format(C++20)或std::ostringstream格式化 - 示例逻辑:
std::string date_str = std::format("{:%Y-%m-%d}", ymd); // ymd 是 year_month_day bool is_leap_second_day = leap_second_dates.count(date_str) > 0;使用第三方库(如 cctz)仍不能“自动判断”,但可辅助解析
Google 的
cctz库支持更精确的 UTC 处理,并提供cctz::utc_time_zone()和闰秒表(内置 IERS 数据),但它也不提供“is_leap_second_day()”接口。你可以用它做两件事:- 将字符串
"2016-12-31 23:59:60"解析为cctz::time_point(成功说明该时刻被其闰秒表认可) - 但注意:这只能验证“某时刻是否存在”,不是“某日是否为闰秒日”;且
cctz的闰秒表需随 IERS 更新手动升级 - 若你传入
"2016-12-31 23:59:59"和"2016-12-31 23:59:60",二者转换后可能得到相同或相邻的time_point,取决于其内部插值策略
真正可靠的判断永远依赖外部权威数据源(IERS Bulletin C),而非运行时推导。所谓“闰秒日”,本质是一个带版本的人工公告列表,不是可算法生成的数学性质。
- 将字符串
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











