应先解析日期字符串获取年份和月份,再用(m-1)/3计算季度编号,最后同时比较年份和季度编号是否相等;需校验月份范围[1,12]及日期有效性,避免std::get_time或std::chrono::parse的静默纠错导致误判。

如何从日期字符串提取年份和季度
直接比对原始日期字符串(如 "2023-04-15")无法判断季度,必须先解析出年份和季度编号。C++ 标准库中 std::get_time 可用于解析,但要注意:它不验证日期有效性(比如 "2023-13-01" 会被截断为 2023-12-01),且对格式错误静默失败——返回 failbit 但不抛异常。
推荐做法是用 std::sscanf 或手动切分,确保年月日字段可提取:
int y1, m1, d1, y2, m2, d2;
if (sscanf(date1.c_str(), "%d-%d-%d", &y1, &m1, &d1) != 3 ||
sscanf(date2.c_str(), "%d-%d-%d", &y2, &m2, &d2) != 3) {
return false; // 格式不对,无法比较
}
季度计算统一用:(m - 1) / 3 + 1(m 是 1–12 的月份),避免手写 if 判断。
为什么不能只比年份或只比季度
季度跨年很常见:比如 "2023-12-25" 和 "2024-01-10" 都属于 Q1?错,前者是 Q4,后者是 Q1——年份不同,季度编号相同但实际不属于同一自然季度。反过来,"2023-01-01" 和 "2023-04-01" 年份相同但季度不同(Q1 vs Q2)。
所以必须同时校验两个条件:
y1 == y2-
(m1 - 1) / 3 == (m2 - 1) / 3(用整除比季度编号更安全,避免 +1 后再比)
注意:不要用浮点除法或 ceil(m/3.0),整数除法 (m-1)/3 对 1–12 月输出恒为 0(Q1)、1(Q2)、2(Q3)、3(Q4),逻辑清晰且无精度风险。
使用 std::chrono 解析时的陷阱
C++20 的 std::chrono::parse 看似简洁,但默认不检查日期合法性。例如:
auto tp = std::chrono::sys_days{};
std::istringstream ss{"2023-13-01"};
ss >> std::chrono::parse("%Y-%m-%d", tp); // 成功解析,但 tp 实际是 2024-01-01
这意味着你拿到的年份和月份可能已被“矫正”,导致季度误判。若坚持用 std::chrono,务必配合 ss.fail() 和手动范围校验:
- 月份必须 ∈ [1, 12]
- 日期需按年月校验(考虑闰年),至少保证
d ≤ days_in_month(y, m)
对多数业务场景,手动 sscanf + 范围检查反而更可控、更轻量。
边界情况:季度起止日是否必须严格在同季内
题目问的是“是否处于同一个年度的同一季度内”,重点在“同一季度”,而非“是否跨季度”。因此只要两个日期所属的(年, 季度)二元组一致即可,无需检查是否都在该季度的第1天到第90/91/92天之间。
举例:"2023-01-01"(Q1 开始)和 "2023-03-31"(Q1 结束)→ 同季;"2023-03-31" 和 "2023-04-01" → 不同季,哪怕只差一天。
真正容易被忽略的是:季度定义依赖于日历规则,不是简单按3个月切分。例如 ISO 周年季度与公历年季度一致,但某些财务系统可能用 4-4-5 周制——这种情况下,必须按业务规则重新映射日期到季度,不能硬套 (m-1)/3。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











