推荐用std::chrono解析字符串日期再转为time_point计算差值,避免手动处理闰年、时区等;需用std::get_time解析、std::mktime转换、duration_cast获取天数等。

用 std::chrono 算两个日期差(推荐,C++11+)
直接用 std::chrono 解析字符串日期再转为时间点最稳妥,避免手动处理闰年、时区、月份天数。核心是把日期转成 std::chrono::system_clock::time_point,再相减得到 duration。
常见错误:用 std::mktime 传入未初始化的 tm 结构体,或忽略 tm_year 是从1900年起算、tm_mon 是 0–11。
- 先用
std::get_time从字符串(如"2023-05-12")解析到std::tm - 调用
std::mktime转为time_t,再用std::chrono::system_clock::from_time_t转成时间点 - 两时间点相减得
std::chrono::days或std::chrono::hours等 duration,用.count()取整数值
示例:
std::string s1 = "2023-01-01", s2 = "2023-12-31";
std::tm t1 = {}, t2 = {};
std::istringstream ss1(s1), ss2(s2);
ss1 >> std::get_time(&t1, "%Y-%m-%d");
ss2 >> std::get_time(&t2, "%Y-%m-%d");
auto tp1 = std::chrono::system_clock::from_time_t(std::mktime(&t1));
auto tp2 = std::chrono::system_clock::from_time_t(std::mktime(&t2));
auto diff = std::chrono::duration_cast(tp2 - tp1);
std::cout << diff.count(); // 输出 364
用 time_t 和 difftime(兼容旧代码)
如果已有 time_t 值(比如从文件读出的秒数),直接用 difftime 最简单。它返回 double,单位是秒,需自行换算成天/小时。
立即学习“C++免费学习笔记(深入)”;
注意点:Windows 下 time_t 是 64 位,但某些嵌入式平台仍是 32 位,2038 年问题仍需留意;difftime 不处理时区,输入必须同属一个时区(通常都按本地或 UTC 处理)。
-
time_t表示自 1970-01-01 00:00:00 UTC 起的秒数(POSIX 定义) - 用
std::mktime得到的是本地时间对应的time_t;若需 UTC,改用std::timegm(非标准,Linux/MSVC 支持)或_mkgmtime(MSVC) - 差值为负说明第一个时间在第二个之后
别直接用时间戳做日期加减(易错)
看到“时间戳”就用 time_t + 86400 * n 加减天数?危险。因为夏令时切换日会导致当天不是 24 小时(比如 23 或 25 小时),直接加秒会跨错日期。
正确做法永远基于日历语义:用 std::tm 修改 tm_mday 后再调用 std::mktime 归一化——它会自动处理溢出、闰秒(忽略)、DST 调整。
- 错误写法:
t += 86400 * 30;→ 可能跳过或重复某天 - 正确写法:解构
time_t到tm,tm.tm_mday += 30,再mktime(&tm) - 若需高精度(毫秒级)或纳秒级间隔,坚持用
std::chrono::steady_clock或system_clock,别碰clock()(它只保证单调,不映射真实时间)
跨平台读取日期字符串的坑
std::get_time 在不同 STL 实现中行为不一致:libstdc++(GCC)对格式宽松,libc++(Clang/macOS)和 MSVC 更严格。比如 "2023-05-01" 中的前导零缺失可能失败。
生产环境建议:用第三方库(如 Howard Hinnant 的 date.h)或自己写简易解析器,至少确保输入格式统一且校验有效。
- 强制补零:用
std::put_time格式化输出时加%02d,输入时也要求补零 - 避免依赖 locale:显式传
std::locale::classic()给std::istringstream - 解析失败时
ss.fail()为 true,必须检查,否则后续mktime用垃圾数据
真正麻烦的从来不是“怎么算差”,而是“怎么把字符串变成可比的时间点”——格式、时区、DST、平台差异,每一层都可能埋雷。











