最简洁方式是用std::chrono::system_clock::now()配合std::format("{:%y-%m-%d}", to_time_t(now));兼容性最强的是用std::localtime_s/r转std::tm后std::strftime;切勿手动拼接tm_year/tm_mon,因需修正偏移且易缺补零。

用 std::chrono + std::format(C++20)最简洁
如果你的编译器支持 C++20 且启用了 std::format(如 MSVC 2022 17.5+、GCC 13+ 配合 -std=c++20 -D_GLIBCXX_USE_CXX11_ABI=1),这是目前最直观的方式:
-
std::chrono::system_clock::now()获取当前时间点 -
std::format直接格式化为"YYYY-MM-DD"字符串,无需手动拆解年月日 - 注意:
std::format在某些旧版 libstdc++ 或 libc++ 中可能未完全实现,会报error: 'format' is not a member of 'std'
auto now = std::chrono::system_clock::now();
auto today = std::format("{:%Y-%m-%d}", std::chrono::system_clock::to_time_t(now));
// 输出示例:"2024-06-12"
用 std::localtime + std::strftime(C++11 起通用)
兼容性最强的方案,所有主流标准库都支持,但需注意线程安全和时区行为:
-
std::time(nullptr)获取秒级时间戳 -
std::localtime将其转为本地时区的std::tm结构(非线程安全,多线程下应改用std::localtime_r(POSIX)或std::localtime_s(MSVC)) -
std::strftime格式化输出,%Y是 4 位年,%m是补零月,%d是补零日
std::time_t t = std::time(nullptr);
std::tm tm_buf{};
#ifdef _WIN32
std::localtime_s(&tm_buf, &t);
#else
std::localtime_r(&t, &tm_buf);
#endif
char buf[11]; // "YYYY-MM-DD\0" → 11 字节
std::strftime(buf, sizeof(buf), "%Y-%m-%d", &tm_buf);
std::string date_str = buf; // "2024-06-12"
避免直接用 std::tm::tm_year 和 std::tm::tm_mon 手动拼接
新手常误以为可以直接读取 tm.tm_year 得到年份、tm.tm_mon 得到月份,然后拼字符串——这会导致严重错误:
-
tm.tm_year是「距 1900 年的偏移量」,2024 年对应值是124,不是2024 -
tm.tm_mon是「0 起始的月份」,6 月对应值是5,不是6 - 手动加法易出错,比如忘记补零("2024-6-5" 而非 "2024-06-05"),也难处理边界(如跨年、闰秒)
所以除非有特殊需求(如只取年份做计算),否则别绕过 std::strftime 或 std::format 自己拼。
立即学习“C++免费学习笔记(深入)”;
Windows 下用 GetLocalTime 的注意事项
在纯 Win32 环境中,有人倾向用 SYSTEMTIME 和 GetLocalTime,但它不跨平台,且默认不带格式化能力:
-
SYSTEMTIME.wYear、wMonth、wDay是正确值(无需加减),这点比std::tm友好 - 但你要自己补零、拼接字符串,容易写成
std::to_string(st.wYear) + "-" + std::to_string(st.wMonth)→ "2024-6" - 若需严格 ISO 格式,仍建议转成
std::tm后调用std::strftime,或用std::format
跨平台项目里,优先走标准库路径更省心。真正需要 Windows 原生 API 的场景,通常是配合 UI 控件或系统服务,而非单纯取日期字符串。











