平年判断的核心逻辑是闰年的否定,即非闰年:!(year % 4 == 0 && year % 100 != 0 || year % 400 == 0);std::chrono不提供直接判断接口,必须手写函数,且条件顺序不可颠倒,否则1900等年份会误判。

平年判断的核心逻辑是什么 平年就是不能被4整除,或者能被100整除但不能被400整除的年份。换句话说,**闰年才是例外**,其余都是平年。所以最直接的做法是先写清楚闰年条件,再取反——别硬凑“平年公式”,容易漏 case。
闰年规则(公历):
- 能被4整除且不能被100整除,或
- 能被400整除
!(is_leap_year(year)),而不是单独写一长串“非闰年”条件。
用 std::chrono 能否直接判断
不能。std::chrono 提供的是时间点、时长和日历转换(如 year_month_day),但它**不提供年份属性判断接口**。你无法调用类似 year.is_leap() 这样的方法(C++20 的 std::chrono::year 也无此成员函数)。
常见误操作:
- 试图用
std::chrono::year{2025}.month_day(2, 29)看是否构造成功 —— 不合法,编译不过 - 依赖
std::chrono::sys_days加减天数再比对 —— 过度复杂,且 2 月 29 日本身在平年就不是有效日期,无法构造
std::chrono 只负责表示和转换,不负责语义判定。
手写判断函数要注意哪些边界 公历闰年规则只对 **1582 年 10 月 15 日之后**(格里高利历推行起)严格适用;此前是儒略历,规则不同(仅看能否被4整除)。但绝大多数业务场景默认按格里高利历处理,且年份通常为正整数。
实操建议:
- 输入年份建议限定为
[1, 9999](匹配std::chrono::year范围),避免负数或极大值引发溢出或未定义行为 - 用
int就够,别用unsigned—— 负年份虽少见,但若从std::chrono::year构造可能为负,unsigned会导致模运算异常 - 推荐写法:
bool is_leap(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } bool is_common_year(int year) { return !is_leap(year); }
为什么 year % 400 == 0 必须放在后面
因为逻辑短路:|| 左边为真时右边不执行。而 year % 400 == 0 是更严格的条件(比如 2000 年),它隐含满足 year % 4 == 0 和 year % 100 == 0。如果把 year % 400 == 0 放前面,像 1900 这种年份(能被100整除但不能被400整除)会错误判为闰年——因为它先满足了 year % 4 == 0,但没拦住 year % 100 == 0 的排除逻辑。
顺序不能颠倒,否则 1900、2100、2200 都会误判为闰年。这是最容易被忽略的细节,调试时得拿这几个典型年份手动验一遍。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。

















