唯一可靠方式是用std::chrono::system_clock::now()获取当前时间点,转std::time_t后通过std::localtime解析年份,再用std::mktime构造当年12月31日00:00:00的时间点并计算差值。

用 std::chrono 和 std::localtime 获取当前年份最后一天
直接用 std::chrono::system_clock::now() 拿到当前时间点,再转成年/月/日结构,是唯一可靠且跨平台的方式。别试图手动算 365 或 366——闰年逻辑藏在标准库实现里,自己硬编码会出错。
关键步骤是:先取当前时间戳 → 转为 std::time_t → 用 std::localtime 解析出年份 → 构造年底时间点(12 月 31 日 23:59:59 不必要,取 12 月 31 日 00:00:00 就够):
auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);
std::tm tm_now = *std::localtime(&t);
int year = tm_now.tm_year + 1900;
<p>std::tm tm_end = {};
tm_end.tm_year = year - 1900;
tm_end.tm_mon = 11; // 12月 → 11
tm_end.tm_mday = 31;
tm_end.tm_hour = 0;
tm_end.tm_min = 0;
tm_end.tm_sec = 0;
tm_end.tm_isdst = -1; // 让 mktime 自动判断夏令时
</p>
用 std::mktime 转回时间戳再相减
std::mktime 是把 std::tm 转成 std::time_t 的唯一标准方式,它会归一化日期(比如传入 2 月 32 日会自动进位),还能处理时区和夏令时。不调用它直接拼秒数,结果一定不准。
注意两个坑:
-
std::mktime修改传入的std::tm对象,所以别复用解析当前时间的那个tm_now - 返回值是
std::time_t,要转成std::chrono::seconds才能和system_clock::time_point做减法
std::time_t end_time = std::mktime(&tm_end);
if (end_time == -1) {
// 解析失败,比如 year 超出范围
return -1;
}
auto end_tp = std::chrono::system_clock::from_time_t(end_time);
auto diff = end_tp - now;
int days = std::chrono::duration_cast<:chrono::days>(diff).count();
</:chrono::days>
为什么不用 std::chrono::year_month_day(C++20)?
如果你确定项目已启用 C++20 且编译器支持完整日历类型(如 GCC 12+、Clang 14+、MSVC 19.30+),那确实更简洁:
using namespace std::chrono;
auto today = floor<days>(system_clock::now());
year_month_day ymd{today};
year_month_day year_end{ymd.year(), December, day{31}};
auto days_left = (year_end - ymd).count();
</days>
但要注意:year_month_day 构造函数不校验日期有效性(比如 year{2024} / February / day{30} 不报错,但后续运算可能 UB);而且 December 和 day{31} 是字面量,不是 magic number,可读性好,但得确保头文件 <chrono></chrono> 被正确包含且无宏干扰。
跨年场景下 days_left 可能为负数
如果今天是 2024-12-31 23:59:59,计算出来是 0 天;但如果程序在 2024-12-31 23:59:59.5 运行,floor<days></days> 或 localtime 都可能落到 2025-01-01,导致年底变成 2025-12-31 —— 此时差值是正的 365 天以上。实际业务中,多数需求只关心“今年剩余”,所以必须显式限定年底为「当前年份的 12 月 31 日」,不能依赖自动推导。
最容易被忽略的是:不同地区时区下,std::localtime 返回的 tm_year 可能和 UTC 时间对应的年份不一致。如果服务部署在 UTC+8,而你用 UTC 时间戳做判断,就可能少算或多算整整一天。统一用 std::gmtime + 强制指定时区偏移,或全程用 UTC 时间点处理,才是健壮做法。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











