c++20 推荐用 std::chrono::year::is_leap() 判断闰年,它基于格里高利历规则且类型安全;c++11/17 需手动提取 tm_year+1900 后按 (y%4==0 && y%100!=0) || y%400==0 计算。

如何用 C++ 判断当前年份是否为闰年
直接调用 std::chrono 获取系统当前年份,再按格里高利历规则判断——不是查日历表,也不是读系统 locale,而是纯逻辑计算。核心就一条:能被 4 整除但不能被 100 整除,或能被 400 整除。
std::chrono::year 是最简洁的起点(C++20 起)
C++20 引入了 std::chrono::year 和配套的时钟工具,避免手撕 time_t 和 tm。它自动处理时区无关的“日历年”概念,比 localtime 更可靠。
实操建议:
- 用
std::chrono::system_clock::now()获取当前时间点,再转换为std::chrono::year_month_day - 提取
.year()得到std::chrono::year对象,它重载了int转换,可直接参与整数运算 - 调用
y.is_leap()是最安全的方式——它内部已实现标准闰年逻辑,且处理了 year 的有效范围(-32767 到 32767)
<pre class="brush:php;toolbar:false;">#include <chrono>
#include <iostream><p>int main() {
auto ymd = std::chrono::year_month_day{
std::chrono::system_clock::now()
};
std::chrono::year y = ymd.year();
std::cout </p></iostream></chrono>兼容 C++11/14/17:手动提取年份并写判断逻辑
若无法使用 C++20,就得退回到 std::time
std::localtime。注意:tm_year 是从 1900 起算的偏移量,必须加 1900;且 localtime 返回的指针可能为 nullptr(如时区配置异常)。常见错误现象:
- 忘记加 1900,导致输出年份是
124这类值 - 未检查
localtime返回值,程序在某些嵌入式或容器环境崩溃 - 闰年判断写成
(y%4==0)单条件,把 1900、2100 等误判为闰年
推荐写法:
<pre class="brush:php;toolbar:false;">auto t = std::time(nullptr); auto* tm_ptr = std::localtime(&t); if (!tm_ptr) return -1; int year = tm_ptr->tm_year + 1900; bool is_leap = (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
为什么不用 strftime
或字符串解析来取年份有人会想用 strftime(buf, "%Y", tm_ptr) 再 std::stoi,这多此一举。不仅多一次内存拷贝和字符串解析开销,还引入了 locale 依赖——比如某些嵌入式平台 %Y 可能不支持或输出异常;更关键的是,它绕过了类型安全,把本该是整数的年份当成字符串中转。
性能与兼容性影响:
-
tm_year + 1900是整数加法,零成本 -
std::chrono::year::is_leap()是 constexpr 函数,编译期可优化 -
strftime涉及 locale 查表、格式化缓冲区分配,慢一个数量级,且不可 constexpr
闰年判断本身很简单,但年份来源容易出错——std::chrono::year 把“获取”和“判断”都封装得足够干净;而老式 API 需要你同时盯住时区、空指针、年份偏移三个坑。别省那两行 #include。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











