c++oding="utf-8" ?>
最简洁方式是用c++20的std::chrono+std::format:先用floor截断到当日零点,再转year_month_day,最后用{:%y%m%d}格式化;兼容性最强的是strftime,但需注意localtime线程安全问题。

用 std::chrono + std::format(C++20)最简洁
如果你的编译器支持 C++20 且启用了 std::format(如 GCC 13+、Clang 15+、MSVC 2022 17.5+),这是最直接的方式。它避免了 C 风格时间函数的易错点,类型安全,语法清晰。
常见错误是直接对 system_clock::now() 调用 std::format——不行,必须先转换为 std::chrono::sys_days 或 std::chrono::year_month_day。
- 先用
std::chrono::floor<:chrono::days>(std::chrono::system_clock::now())</:chrono::days>截断到当日零点 - 再转成
std::chrono::year_month_day,才能用{:%Y%m%d}格式化 - 注意:
%Y是 4 位年份,%m是补零月,%d是补零日,正好满足YYYYMMDD
auto now = std::chrono::system_clock::now();
auto ymd = std::chrono::year_month_day{std::chrono::floor<:chrono::days>(now)};
std::string s = std::format("{:%Y%m%d}", ymd); // 如 "20240521"
</:chrono::days>
用 std::strftime(C++11 及以上,兼容性最强)
几乎所有平台都支持,但需要经过 std::time_t → std::tm 转换,且 std::localtime 不是线程安全的——这是最容易踩的坑。
关键点在于:必须用 std::gmtime 或带锁的 std::localtime_r(POSIX)/ localtime_s(Windows)替代裸 std::localtime,否则多线程下会崩溃或返回错误日期。
- 用
std::chrono::system_clock::to_time_t获取time_t - Windows 下优先用
localtime_s(&tm, &t);Linux/macOS 用localtime_r(&t, &tm) - 格式化字符串用
"%Y%m%d",std::strftime返回的是写入长度,不是字符串
std::time_t t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
std::tm tm{};
#ifdef _WIN32
localtime_s(&tm, &t);
#else
localtime_r(&t, &tm);
#endif
char buf[9]; // YYYYMMDD + \0 → 9 字节
std::strftime(buf, sizeof(buf), "%Y%m%d", &tm);
std::string s(buf); // "20240521"
为什么不用 std::put_time?
它看起来更现代,但实际有隐藏陷阱:默认绑定到 std::cout 或任意 std::basic_ostream,不能直接返回 std::string;想存字符串得用 std::ostringstream 中转,代码变长且容易漏 导致末尾多换行。
更麻烦的是,std::put_time 接收的是 const std::tm*,同样面临线程安全问题,且不处理时区隐式转换(比如你期望本地时间,但它可能按 UTC 解析)。
- 若硬要用,必须配
std::ostringstream+std::put_time+str() - 仍需解决
std::localtime的线程安全问题,没比strftime省事 - 性能略低于直接
strftime到栈数组,因为涉及流缓冲和格式解析
跨平台构建时要注意的编译器差异
C++20 的 std::format 在 MSVC 上默认启用,但 GCC 需要 -std=c++20 -D_GLIBCXX_USE_C99_FORMAT(部分版本),Clang 则依赖 libc++ 版本。如果 CI 报 error: 'format' is not a member of 'std',八成是标准库没跟上。
而 strftime 方案虽老,但只要定义好 _CRT_SECURE_NO_WARNINGS(Windows)或包含 <ctime></ctime> 就基本无坑。真正容易被忽略的是:不同系统对 %Y 解释一致,但某些嵌入式 libc(如 newlib)可能不支持 %Y,只认 %y(两位年份)——这时就得手动拼接 tm_year + 1900。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











