最简洁方式是用 std::chrono + std::format(c++20):获取当前时间点并格式化为“yyyy-mm-dd hh:mm:ss”字符串,但需注意 std::localtime 的线程不安全性及 std::format 在 gcc/clang 上的实验性状态。

用 std::chrono + std::format(C++20)最简洁
如果你的编译器支持 C++20 且启用了 std::format(如 MSVC 19.3x+、GCC 13+ 配合 -std=c++20 -D_GLIBCXX_USE_CXX11_ABI=1),这是最直接的方式:
auto now = std::chrono::system_clock::now();
auto time_t = std::chrono::system_clock::to_time_t(now);
std::string s = std::format("{:%Y-%m-%d %H:%M:%S}", *std::localtime(&time_t));
注意:std::localtime 返回的是非线程安全的静态指针,多线程下需用 std::localtime_r(POSIX)或 localtime_s(Windows)替代;std::format 目前在 GCC/Clang 上仍属实验性,部分发行版默认未启用。
用 std::put_time(C++11 起)兼容性最好
这是目前最稳妥的跨平台方案,不依赖 C++20,也避开 strftime 的缓冲区管理麻烦:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
std::put_time需配合std::ostringstream和std::localtime使用 - 必须传入
const std::tm*,不能直接对time_t操作 - 同样要注意
std::localtime的线程安全性问题
auto now = std::time(nullptr); auto tm_ptr = std::localtime(&now); // ⚠️ 多线程请改用 localtime_r 或 localtime_s std::ostringstream oss; oss <h3>避免用 <code>ctime</code> 或 <code>asctime</code>——它们带换行且不可控</h3> <p>常见错误是直接写 <code>std::string s = std::ctime(&now);</code>,结果字符串末尾带 <code>\n</code>,而且格式固定(如 <code>"Wed Apr 10 15:30:45 2024\n"</code>),无法自定义。这不是 bug,是标准规定的行为。</p>
-
ctime(&t)等价于asctime(localtime(&t)) - 返回的 C 字符串以
\n\0结尾,std::string构造时会把\n一起包进去 - 若硬要清理,得额外调用
s.pop_back(),但不如一开始就选可控方式
需要毫秒级精度?别只靠 std::time_t
std::time(nullptr) 和 std::localtime 只能到秒级。若要包含毫秒(比如日志打点),必须从 std::chrono::system_clock::now() 出发:
auto now = std::chrono::system_clock::now(); auto time_t = std::chrono::system_clock::to_time_t(now); auto ms = std::chrono::duration_cast<:chrono::milliseconds>(now.time_since_epoch()) % 1000; std::ostringstream oss; oss <p>这里 <code>std::setw</code> 和 <code>std::setfill</code> 是关键,否则毫秒可能输出为 <code>7</code> 而不是 <code>007</code>;另外注意 <code>localtime</code> 的线程安全仍是隐患,生产环境建议封装成线程局部缓存或使用 <code>std::gmtime</code> + 手动时区偏移。</p></:chrono::milliseconds>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










