std::chrono无法直接获取某年某月天数,应手写逻辑:31天(1/3/5/7/8/10/12)、30天(4/6/9/11),2月按闰年规则判断(能被4整除且不被100整除,或被400整除则29天)。

用 std::chrono 判断某年某月的天数不靠谱
直接用 std::chrono 的 year_month_day 或 sys_days 无法反推某月天数——它只支持“日期 → 天数”,不支持“年+月 → 最大日”。想靠 last_day_of_month()?C++20 标准里压根没这个函数,那是某些第三方库(比如 Howard Hinnant’s date)的扩展,不是标准行为。
最稳妥:手写判断逻辑 + 闰年检查
核心就两步:先查月份固定天数,再对 2 月单独处理。别依赖系统 locale 或时区 API,它们不解决“2024 年 2 月有多少天”这种纯数学问题。
-
31天的月份:1、3、5、7、8、10、12 月 -
30天的月份:4、6、9、11 月 -
2月:先算闰年 —— 能被 4 整除但不能被 100 整除,或能被 400 整除 →29天,否则28天
示例函数:
int days_in_month(int year, int month) {
if (month 12) return -1;
static const int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month != 2) return days[month - 1];
bool is_leap = (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
return is_leap ? 29 : 28;
}
用 mktime 反推(兼容老标准,但有坑)
有人用 struct tm 设为下月 0 日来“绕出”当月天数,比如设 tm_mday = 0、tm_mon = 1(即 2 月 0 日 → 自动回滚到 1 月 31 日)。这方法可行,但要注意:
-
mktime会修改传入的tm结构体,必须初始化所有字段(尤其tm_isdst,否则行为未定义) - 跨年时(如 12 月 → 下年 1 月)没问题,但输入非法月份(如 13)可能返回 -1,需判空
- 性能比纯计算慢一个数量级,高频调用别这么干
别忘了边界和符号问题
用户传 month = 0 或负数很常见,别直接当数组下标用。返回值建议用 -1 表示非法输入,而不是静默返回 0 或 31。另外,year 用 int 就够了——Gregorian 日历规则在 ±10000 年内都适用,超出范围本就不该由这个函数负责。
真正容易被忽略的是:2 月天数永远依赖具体年份,不存在“2 月固定 28 天”的捷径。哪怕只是做 UI 默认值,也得把年份参数带上。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











