C++如何获取两个int类型日期闭区间内的所有日期?
实现方案
你现有思路完全可行,核心是利用std::mktime会自动归一化越界日期字段的特性:每次给tm_mday加1后调用std::mktime,函数会自动处理跨月、跨年、闰年、夏令时的偏移,不需要手动写复杂的日期进位逻辑。
基于std::tm的可运行实现
首先需要注意你现有make_tm函数的隐患:栈上创建的std::tm如果不做零初始化,tm_hour/tm_min/tm_sec/tm_isdst等字段会是随机垃圾值,可能导致std::mktime计算结果异常,修正后的工具函数和遍历逻辑如下:
#include <vector> #include <ctime> #include <cstdint> // 修正后的int转std::tm函数 std::tm make_tm(int32_t s) { int32_t s_year = s / 10000; int32_t s_mon = s % 10000 / 100; int32_t s_day = s % 100; std::tm st{}; // 零初始化所有字段,消除垃圾值影响 st.tm_year = s_year - 1900; st.tm_mon = s_mon - 1; st.tm_mday = s_day; st.tm_isdst = -1; // 交由系统自动判断夏令时,避免手动设置错误 std::mktime(&st); return st; } // 辅助函数:std::tm转回YYYYMMDD格式的int32_t int32_t tm_to_int(const std::tm& t) { return (t.tm_year + 1900) * 10000 + (t.tm_mon + 1) * 100 + t.tm_mday; } // 核心:生成闭区间日期序列 std::vector<int32_t> get_date_range(int32_t start_date, int32_t end_date) { std::vector<int32_t> res; // 非法输入直接返回空数组 if (start_date > end_date) { return res; } std::tm current = make_tm(start_date); res.push_back(start_date); while (true) { current.tm_mday += 1; std::mktime(¤t); // 自动修正日期越界 int32_t cur_val = tm_to_int(current); if (cur_val > end_date) { break; } res.push_back(cur_val); } return res; }
调用get_date_range(20220620, 20220622)即可得到你预期的std::vector<int32_t>{20220620, 20220621, 20220622}结果。
更轻量的无依赖实现
如果你的业务场景不需要处理复杂的时区、夏令时规则,只是处理常规公历日期,可以直接手动实现日期进位逻辑,完全不依赖C标准库时间函数,性能更高,也不会因为服务器时区配置异常出现计算偏差:
#include <vector> #include <cstdint> // 闰年判断 bool is_leap_year(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } // 获取指定年月的总天数 int get_month_max_day(int year, int month) { static const int month_days[] = {31,28,31,30,31,30,31,31,30,31,30,31}; if (month == 2 && is_leap_year(year)) { return 29; } return month_days[month - 1]; } std::vector<int32_t> get_date_range_fast(int32_t start_date, int32_t end_date) { std::vector<int32_t> res; if (start_date > end_date) { return res; } int year = start_date / 10000; int month = (start_date % 10000) / 100; int day = start_date % 100; while (true) { int32_t cur_date = year * 10000 + month * 100 + day; if (cur_date > end_date) { break; } res.push_back(cur_date); // 日期进位 day += 1; int max_day = get_month_max_day(year, month); if (day > max_day) { day = 1; month += 1; if (month > 12) { month = 1; year += 1; } } } return res; }
方案选择建议
- 若需要兼容历史日期、严格匹配本地时区时间规则,选择
std::tm实现,标准库已经覆盖了所有时间计算的边界场景 - 若只是处理常规业务日期、追求性能和稳定性,选手动进位的轻量实现,无隐式环境依赖
内容的提问来源于stack exchange,提问作者nick
相关产品推荐
相关产品推荐

