c++怎么计算两个日期之差_c++日期计算方法【实战】

1次阅读

最稳方法是用std::chrono结合std::tm转换:先设tm_isdst=-1,再mktime转time_t,最后整除86400;需校验mktime返回值,避免非法日期导致溢出或偏差。

c++怎么计算两个日期之差_c++日期计算方法【实战】

std::chrono 算两个日期差最稳

直接用 std::chrono + std::tm 转换,别碰 time_t 手动算天数——跨闰年、时区、夏令时全会翻车。c++20 的 std::chrono::year_month_day 更好,但老项目大概率还在用 C++11/14,所以重点讲兼容写法。

核心思路:把两个日期转成 std::time_t(秒级时间点),再相减除以 86400。但必须注意:两个 std::tm 都得设好 tm_isdst = -1,否则本地时区规则可能让结果偏一天。

  • std::mktime() 会修改传入的 std::tm,比如把 tm_mon = 12 自动进位,所以别复用同一结构体
  • 月份要减 1(tm_mon 是 0–11),年份要加 1900(tm_year 是距 1900 年的偏移)
  • 如果只关心“日历天数差”,忽略时分秒,建议统一设成中午 12:00,避免某天凌晨跨时区导致 mktime 返回前一天

std::mktime 返回 -1 就是输入非法

常见错误:传了 tm_mday = 0tm_mon = 13mktime 不报错也不修正,直接返回 -1,接着 std::difftime 算出来就是负的巨大值。不是 bug,是标准行为。

  • 务必检查 mktime(&tm1) == -1 || mktime(&tm2) == -1
  • tm_wdaytm_yday 不用填,mktime 会自动算;但 tm_isdst 必须设为 -1 让系统推断
  • windowsmktime 对超大年份(如 10000 年)支持弱,linux 一般撑到 2100 年左右没问题

只要日差?别用浮点除法

static_cast<int>(std::difftime(t2, t1) / 86400)</int> 看似简单,但 std::difftime 返回 double,对长跨度(比如 100 年)可能丢失精度——double 在 2^53 后无法精确表示每个整数秒,日差误差可能达 ±1 天。

立即学习C++免费学习笔记(深入)”;

  • 改用整数截断:(t2 - t1) / 86400,前提是确认 t2 >= t1 且差值不溢出 time_t 有符号范围
  • 更安全的做法:用 std::lldiv 做整除,或直接用 C++20 的 std::chrono::duration_cast<:chrono::days></:chrono::days>
  • 如果两个日期在同一年且月份已知,手动按月累加天数反而更准(避开 mktime 的时区陷阱)

跨年/跨月计算容易漏掉边界

比如算 2023-01-31 到 2023-02-28,有人按“2 月有 28 天”直接减,得出 28 天,实际是 28 天没错;但若算 2024-01-31 到 2024-02-29,手动硬算就容易错——2 月有 29 天,但起始日 31 日在 2 月不存在,mktime 会自动折成 3 月 2 日,结果变成 33 天而非 29 天。

  • 这就是为什么不能跳过 mktime 直接数学算:它处理了所有“不存在的日期”的归约逻辑
  • 测试时至少覆盖:1 月 31 日→2 月 28/29 日、12 月 31 日→次年 1 月 1 日、闰年前后各一年
  • 如果业务明确只要“日历上看起来的天数差”(比如合同有效期),那得另写逻辑,和系统时间无关

真正麻烦的不是怎么算,而是搞清你要的到底是“经过多少个 24 小时”,还是“日历上翻了多少页”。前者靠 mktime,后者得自己建日期表或用第三方库比如 date.h

text=ZqhQzanResources