应将日期统一转换为绝对时间点(如std::chrono::sys_days)再比较,c++20推荐year_month_day+sys_days,c++11/17需用mktime并注意时区、无效日期和2038问题。

用 std::chrono 比较日期需要先统一成时间点
直接比较年月日结构(比如 struct tm 或自定义 Date)无法判断是否在时间跨度内,因为缺少时区、日历规则和可比性。必须转成可排序的绝对时间点,std::chrono::system_clock::time_point 是最常用选择。
关键前提是:你得有起始、结束和待测日期的完整时间点(至少精确到日)。如果只有年/月/日,需补零构造为当天 00:00:00 UTC(或本地时区,但必须一致)。
- 推荐用 C++20 的
std::chrono::year_month_day+sys_days转换,简洁且无歧义 - 若限于 C++11/14/17,可用
std::mktime,但注意它会修改tm_isdst、受本地时区影响,且 2038 年问题需警惕 - 避免用字符串比较(如
"2023-05-01" > "2023-04-30"),虽对 ISO 格式有效,但不表达语义,且无法处理跨年/闰秒等边界
C++20:用 year_month_day 和 sys_days 做安全区间判断
C++20 提供了类型安全、无时区陷阱的日历操作。核心是把日期转成 sys_days(即 system_clock::time_point 的天精度封装),再用常规比较运算符。
#include <chrono>
#include <iostream><p>namespace c = std::chrono;</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/shouce/1510" title="C函数速查手册(CHM版)"><img
src="https://img.php.cn/upload/manual/000/000/001/5d6de31fedca2993.png" alt="C函数速查手册(CHM版)" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/shouce/1510" title="C函数速查手册(CHM版)" class="overflowclass">C函数速查手册(CHM版)</a>
<p class="overflowclass">C函数速查手册(CHM版)</p>
</div>
<a rel="nofollow" href="/xiazai/shouce/1510" title="C函数速查手册(CHM版)" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p>bool is_in_range(int y, int m, int d,
c::year_month_day start, c::year_month_day end) {
c::sys_days target{c::year{y}/c::month{m}/c::day{d}};
c::sys_days s{start};
c::sys_days e{end};
return s </p>
<p>// 使用示例:判断 2024-02-29 是否在 [2024-01-01, 2024-12-31] 内
int main() {
auto start = c::year{2024}/c::month{1}/c::day{1};
auto end = c::year{2024}/c::month{12}/c::day{31};
std::cout </p></iostream></chrono>
-
c::year{y}/c::month{m}/c::day{d}构造合法year_month_day;若非法(如 2023-02-30),运行时抛std::runtime_error -
sys_days自动归一化:传入2024/2/30会被转成 2024-03-01,但建议先校验再转换 - 区间是闭区间:包含起始和结束当天的整个 24 小时
C++11/17:用 std::mktime 需手动处理时区与无效输入
老标准下没有日历类型,只能靠 std::tm + std::mktime。它把本地时间转为 time_t(通常为秒数),但行为依赖本地时区设置,且对无效日期返回 -1。
<pre class="brush:php;toolbar:false;">#include <ctime>
#include <climits><p>bool is_in_range_tm(int y, int m, int d, std::tm start, std::tm end) {
std::tm t = {};
t.tm_year = y - 1900;
t.tm_mon = m - 1; // 0-based
t.tm_mday = d;
t.tm_hour = t.tm_min = t.tm_sec = 0;
t.tm_isdst = -1; // 让 mktime 推断夏令时</p>
<pre class="brush:php;toolbar:false;"><code>std::time_t target = std::mktime(&t);
if (target == -1) return false;
std::time_t s = std::mktime(&start);
std::time_t e = std::mktime(&end);
return s != -1 && e != -1 && target >= s && target <p>}</p></code>
tm_isdst = -1
std::mktime 会修改传入的 tm 结构体(如调整 tm_wday),不能复用同一变量判断多个日期std::timegm(非标准但广泛支持),或用 std::put_time + std::get_time 手动解析容易被忽略的边界:闰年、月末、时区与精度
看似简单的“日期在范围内”判断,实际藏着几个高频翻车点:
- 2024-02-29 合法,但 2023-02-29 传给
std::mktime会静默变成 2023-03-01 —— 你本意是“无效日期即不在范围内”,结果却误判为在 - 用
std::chrono::system_clock::now()获取当前时间再截断到日,和用year_month_day构造的“今天”可能因时区偏移差一天(尤其在 UTC+13 或 UTC-12 地区) - 若时间跨度含小时分钟(如 “2024-01-01 14:00 到 2024-01-03 09:00”),仅比较日期会漏掉精度信息;此时必须用
sys_seconds或更高精度类型 - 跨年计算(如 2023-12-31 到 2024-01-02)看似简单,但手写逻辑易错;用
sys_days或time_t可交给标准库处理
真正麻烦的从来不是“怎么写”,而是“怎么定义‘落在范围内’——按本地日?UTC 日?还是带具体时刻的区间?” 这个前提没对齐,代码越写越像补丁。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










