




推荐用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 从字符串(如 "2025-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 = "2025-01-01", s2 = "2025-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,单位是秒,需自行换算成天/小时。
注意点: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 更严格。比如 "2025-05-01" 中的前导零缺失可能失败。
生产环境建议:用第三方库(如 Howard Hinnant 的 date.h)或自己写简易解析器,至少确保输入格式统一且校验有效。
std::put_time 格式化输出时加 %02d,输入时也要求补零std::locale::classic() 给 std::istringstream
ss.fail() 为 true,必须检查,否则后续 mktime 用垃圾数据真正麻烦的从来不是“怎么算差”,而是“怎么把字符串变成可比的时间点”——格式、时区、DST、平台差异,每一层都可能埋雷。