判断当月首日只需检查 day() 是否为 1:用 year_month_day{floor(tp)} 提取日期,验证 ymd.ok() 后 static_cast(ymd.day()) == 1;跨时区需明确使用 localtime(本地)或 gmtime(utc),避免混用。

用 std::chrono 提取年月日再比对是否为 1 号
标准库不提供直接的“当月起始日”判断函数,但 std::chrono::year_month_day 能可靠拆解日期。关键不是“算第一天”,而是“看 day 是否等于 1”。year_month_day 会自动归一化非法日期(比如 2024-02-30 → 2024-03-01),所以必须确保输入是合法日期,否则比对结果无意义。
实操建议:
- 先用
sys_days将输入时间点转为日历日,再构造year_month_day - 直接访问
.day()成员,它返回day类型,需调用.operator int()或隐式转换为int - 避免手动拼字符串或用
strftime解析,易受 locale 和格式影响
auto ymd = year_month_day{floor<days>(tp)}; // tp 是 system_clock::time_point
if (static_cast<int>(ymd.day()) == 1) { /* 是当月首日 */ }</int></days>
用 tm 结构体判断时要注意 tm_mday 的偏移
tm_mday 是从 1 开始计数的(不是 0),这点和 tm_mon(0–11)不同。误以为它从 0 开始会导致逻辑翻车——比如把 tm_mday == 0 当作首日,实际永远不成立。
常见错误场景:
- 从
localtime或gmtime拿到tm*后,直接写tm->tm_mday == 0 - 没检查
tm是否为 null(gmtime在无效时间下可能返回 null) - 忽略
tm_isdst等字段不影响判断,但若用于后续计算,需注意夏令时边界
tm* t = localtime(&ttime);
if (t && t->tm_mday == 1) { /* 正确 */ }
跨时区场景下,“当月起始日”依赖本地时间还是 UTC
“当月第一天”不是绝对概念:北京时间 2024-03-01 00:00:00 对应 UTC 是 2024-02-29 16:00:00。若业务要求按用户本地时区判断(如运营活动开启),必须用 localtime;若按服务器统一时区(如 UTC 日志分区),则用 gmtime 或 zoned_time 显式指定时区。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
实操要点:
- 不要混用
localtime和gmtime结果做比较 - C++20
zoned_time更安全,但需确认编译器支持(GCC 12+ / Clang 14+) - 若用第三方库(如 Howard Hinnant 的 date.h),优先走
zoned_seconds+year_month_day流程
注意 year_month_day 构造失败时不抛异常,但值无效
year_month_day{year{2024}, month{2}, day{30}} 不会报错,而是生成一个未指定值(ok() == false)。如果后续调用 .day(),行为是未定义的——可能返回 0、随机值或触发断言(取决于实现)。这比抛异常更隐蔽。
安全做法:
- 构造后立即检查
ymd.ok() - 不要依赖默认构造或隐式转换,显式初始化并验证
- 若输入来自用户或外部 API,务必先校验日期合法性(如用
is_leap_year+ 月份天数表辅助)
year_month_day ymd{y, m, d};
if (!ymd.ok() || static_cast<int>(ymd.day()) != 1) { /* 非法或非首日 */ }</int>
判断的核心就两件事:拿到合法日期的“日”字段,确认它等于 1。所有绕路方案(比如减去一天再比年月)都增加出错概率,也掩盖了问题本质。真正容易被忽略的是日期来源是否可信——时间戳越界、时区混乱、闰秒残留,都会让“第 1 天”变成假阳性。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










