std::chrono::system_clock 返回自1970-01-01 utc起的time_point,需转time_t再用gmtime/localtime解析为年月日;c++20可用year_month_day直接获取utc日期,时区处理须明确区分utc、本地时间及夏令时。

std::chrono::system_clock 只能拿到时间点,不能直接获取年月日
很多人以为 system_clock 像 C 的 localtime 一样能直接拆出年月日,其实它返回的是一个 time_point —— 本质是自纪元(1970-01-01 00:00:00 UTC)以来的纳秒/微秒计数。要得到日期,必须先转成 C 风格的 std::time_t,再用 std::gmtime 或 std::localtime 解析。
正确步骤:system_clock::now() → time_t → tm 结构体
这是最常用且跨平台安全的做法,注意时区处理:
-
system_clock::to_time_t(system_clock::now())转成time_t,这一步是 UTC 时间(不带时区偏移) - 用
std::gmtime得到 UTC 日期(tm中的tm_year是自 1900 年起算,tm_mon是 0–11) - 如果需要本地时区日期,改用
std::localtime,但它不是线程安全的;C++20 起推荐用std::chrono::zoned_time替代
示例:
auto now = std::chrono::system_clock::now(); std::time_t t = std::chrono::system_clock::to_time_t(now); std::tm tm_utc = *std::gmtime(&t); // UTC 日期 int year = tm_utc.tm_year + 1900; int month = tm_utc.tm_mon + 1; int day = tm_utc.tm_mday;
std::put_time 格式化输出时容易忽略 locale 设置
直接用 std::put_time 打印中文月份或星期会乱码或显示英文,因为默认 locale 是 "C":
- 加
std::locale::global(std::locale(""));可继承系统 locale(Linux/macOS 下通常有效,Windows 需用"Chinese_China"等具体名) - 更稳妥的方式是显式构造 locale:
std::locale loc("zh_CN.UTF-8");,然后传给std::put_time - 若只想要数字格式(如 2024-06-15),完全不用 locale,直接拼接
tm_year+1900等字段更轻量、无依赖
C++20 起有更现代的方案:使用 calendar 头文件
如果你能用 C++20,<chrono></chrono> 新增了日历类型,可避免 tm 的魔数和时区陷阱:
std::chrono::year_month_day ymd = std::chrono::floor<:chrono::days>(std::chrono::system_clock::now());</:chrono::days>- 之后用
ymd.year()、ymd.month()、ymd.day()直接取整型值,无需加减偏移 - 但注意:这仍是 UTC 时间;要转本地日期,得配合
std::chrono::current_zone()->to_local(...) - 目前 MSVC 和 GCC 12+ 支持较好,Clang 对部分 calendar 特性支持滞后
真正麻烦的不是“怎么拿日期”,而是“你要的是 UTC 日期、本地墙钟日期,还是考虑夏令时的本地日期”——这三个答案对应的实现完全不同,选错一步,线上时间就差八小时。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











