c++oding="utf-8" ?>
应将日期归一化为 std::chrono::system_clock::time_point 再比较,避免直接比较年月日结构体导致闰年、月份天数、时区等逻辑错误。

用 std::chrono 比较日期需要先转成时间点
直接比较年月日结构体(比如自定义的 Date)容易出错,因为闰年、月份天数不一致、时区等逻辑要自己处理。C++ 标准库推荐的方式是把日期归一化为 std::chrono::system_clock::time_point,再用 、<code> 等操作符判断范围。
关键前提是:必须把年/月/日转换为系统时钟能理解的绝对时间点。最稳妥的是用 std::chrono::year_month_day(C++20)配合 sys_days:
using namespace std::chrono;
year_month_day ymd{year{2023}, month{5}, day{15}};
sys_days tp = ymd; // 自动转成 time_point,精度为天
注意:sys_days 本质是 time_point,底层是自纪元以来的天数,不带时分秒,适合纯日期比较。
手动构造 sys_days 时月份和日期容易越界
C++20 的 year_month_day 构造函数不会自动归一化输入值。如果传入 month{13} 或 day{32},它会保留非法值,后续转 sys_days 时行为未定义(常见表现是程序崩溃或返回错误时间点)。
安全做法是先用 year_month_day{year, month, day}.ok() 校验有效性:
-
year_month_day{year{2023}, month{13}, day{1}}.ok()返回false -
year_month_day{year{2023}, month{2}, day{29}}.ok()在非闰年也返回false - 只有校验通过后,才调用
sys_days转换
判断是否在范围内:用 和 <code>,别用 <code> 和 <code>
日期范围通常是“包含起止”的,比如“2023-05-01 到 2023-05-31”。如果用 比较终点,会漏掉最后一天:
sys_days start = year_month_day{year{2023}, month{5}, day{1}};
sys_days end = year_month_day{year{2023}, month{5}, day{31}};
sys_days target = year_month_day{year{2023}, month{5}, day{31}};
// ❌ 错误:target = start) && (target = start) && (target
<p>另外注意:<code>sys_days</code> 是离散类型,相邻两天差值为 1 天,不存在“中间时刻”,所以 <code> 是自然且安全的选择。</code></p>
<h3>兼容 C++17 或需支持历史日期时慎用 <code>sys_days</code>
</h3>
<p><code>sys_days</code> 基于 <code>system_clock</code>,其纪元是 1970-01-01,部分标准库实现对早于该日期的 <code>sys_days</code> 支持不完整(例如 libc++ 在负天数时可能溢出)。若业务需处理 1900 年前的日期,不要依赖 <code>sys_days</code>。</p>
<p>替代方案是手写比较逻辑(仅限年月日):</p>
<pre class="brush:php;toolbar:false;">struct Date {
int y, m, d;
bool operator
<p>这种写法简单可控,但需自行确保 <code>y/m/d</code> 合法(比如 <code>m</code> 在 1–12),否则比较结果无意义。</p>
<p>真正麻烦的不是怎么写判断,而是怎么定义“合法日期”——闰年规则、大小月、儒略历/格里高利历切换点,这些边界一旦涉及历史数据,就很难靠几个 <code>if</code> 覆盖全。</p>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











