std::chrono不提供直接获取某年某月天数的函数,需手动实现闰年判断和月份天数查表;闰年必须按格里高利历规则:(能被4整除且不能被100整除)或能被400整除;2月天数须动态计算,其他月份可静态查表。

用 std::chrono 判断月份天数需要手动处理闰年
标准库没有直接返回“某年某月多少天”的函数,std::chrono 提供的是时间点和持续期抽象,不封装日历逻辑。你得自己实现:先判断是否闰年,再查对应月份的天数表。别指望 std::chrono::year_month_day 的构造函数自动校验——它允许构造出像 2023y/February/30d 这样的非法值,且不报错。
is_leap_year() 的实现必须严格按格里高利历规则
常见错误是只写 year % 4 == 0,这会把 1900、2100 等整百年份误判为闰年。正确逻辑是:
- 能被 4 整除但不能被 100 整除 → 是闰年
- 能被 400 整除 → 是闰年
- 其余情况 → 不是闰年
示例:
bool is_leap_year(int y) {
return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}
月份天数查表要带年份参数,2月必须动态计算
硬编码 12 个月天数数组可以,但第 2 项(2月)不能固定写 28。必须传入年份,调用 is_leap_year() 再决定返回 28 还是 29。其他月份可静态查表:
int days_in_month(int year, int month) {
static constexpr int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month 12) return -1;
if (month == 2 && is_leap_year(year)) return 29;
return days[month - 1];
}
注意:month 通常按 1–12 输入,别和 C 风格的 0–11 混淆;输入非法值时建议返回 -1 或抛异常,别静默截断。
用 std::tm + mktime() 是可行但有陷阱的替代方案
有人用设置 std::tm 的 tm_mday 为 32 再调 mktime() 让它“溢出”到下个月,然后比较日期差。这方法依赖 C 运行时行为,且 mktime() 会修改原结构体、可能跨月甚至跨年(比如 12 月 32 日变成下年 1 月 1 日),误差风险高。更糟的是,tm 年份字段是距 1900 的偏移量,tm_mon 是 0–11,极易填错。除非已有 tm 结构在手且确定环境一致,否则不推荐。
真正容易被忽略的是:不同地区对“月份第一天/最后一天”的定义可能影响业务逻辑,比如财务周期或报表截止日。纯数学天数只是起点,边界情况(如 2024-02-29 是否有效)得结合具体场景验证。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











