最可靠的方法是将日期字符串解析为std::tm,调用mktime归一化后转为std::time_t,再用difftime计算秒差并除以86400得天数;必须注意tm_year减1900、tm_mon从0开始,且mktime会自动处理闰年、跨月等边界。

用 std::chrono 和 std::tm 手动转换最可靠
标准库没有直接的“日期差”函数,std::chrono::system_clock::time_point 虽然能表示时间点,但不能直接解析字符串如 "2023-04-01"。必须先把日期转成 std::tm,再通过 std::mktime 转为 std::time_t,最后相减——这是跨平台且不依赖第三方库的稳妥做法。
常见错误是忽略 tm_year 要减 1900、tm_mon 从 0 开始(1 月是 0),以及忘记调用 mktime 将 tm 归一化(否则 tm_mday=32 不会自动进位)。
-
tm_year设为2023 - 1900,不是2023 -
tm_mon设为3表示 4 月(0-indexed) - 设完字段后必须调用
mktime(&tm),否则时间计算结果不可靠 - 返回值是秒数差,除以
86400得整数天数(注意:负数截断方向,建议用std::floor或直接static_cast<int></int>向零取整,视业务而定)
遇到闰年或跨月时,别自己写逻辑
手动算天数(比如累加每月天数、判断闰年)极易出错。2000 年是闰年,1900 年不是;2 月有 28 或 29 天;11 月只有 30 天——这些边界在 mktime 内部已处理。只要输入合法的 tm 结构体,它会自动归一化并返回正确的 time_t 值。
例如把 tm_day = 32、tm_mon = 0(1 月)传给 mktime,它会自动转成 2 月 1 日。这就是为什么必须走这一步,而不是直接用结构体字段做算术。
- 不要用
(y2-y1)*365 + (m2-m1)*30 + (d2-d1)这类估算 - 不要手写闰年判断(
y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)容易漏括号或优先级) - 如果日期来自用户输入,先校验合法性(比如 2 月 30 日会被
mktime调整,但可能不是你想要的行为)
Windows 下 GetDateDifference 不是标准 API
有人搜到 GetDateDifference 或 SystemTimeToFileTime,这些是 Windows 特有 API,不可移植。C++ 标准只保证 <ctime></ctime> 提供的 mktime/difftime 等函数可用。Linux/macOS 下没有 GetDateDifference,链接会失败。
如果你项目限定 Windows 且已用 Win32 API,那可以用 SystemTimeToVariantTime 转成浮点天数再相减,但纯 C++ 工程应避免绑定平台。
- 跨平台代码一律走
std::tm → std::time_t → difftime()流程 -
difftime(t2, t1)返回double,比直接t2 - t1更语义清晰,且在某些旧系统上更安全 - 不要依赖
__DATE__宏或编译时计算——它只给出编译日期,不是运行时输入日期
ISO 格式字符串解析要自己拆分
C++20 引入了 <chrono></chrono> 的日历支持(year_month_day),但目前主流编译器(GCC 12/Clang 14/MSVC 2022)对它的完整支持仍有限,尤其 parse 功能不稳定。所以对 "2023-04-01" 这类字符串,最稳的方式还是用 sscanf 或 std::stoi 拆解:
int y, m, d;
if (sscanf(date_str.c_str(), "%d-%d-%d", &y, &m, &d) != 3) {
// 解析失败
}
// 然后填入 tm 结构体
注意 sscanf 不检查范围(比如 m=13),后续 mktime 会处理,但若需提前报错,得手动验证 m ∈ [1,12]、d ∈ [1,31] 等。
- 别用
std::istringstream配合operator>>拆 ISO 字符串——它不会跳过-分隔符 - 别用
std::regex解析简单日期——性能差、编译慢、移动端可能禁用 - 如果项目已用
fmt库,可用fmt::sscanf替代,语法更安全
实际天数差的精度取决于你是否考虑时区和夏令时。mktime 默认按本地时区解释输入,若两个日期需按 UTC 计算,得用 timegm(POSIX)或手动设 tm_isdst = 0 并配合 setenv("TZ", "UTC", 1) ——这点常被忽略。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











