C++20推荐用std::chrono::floor+std::format实现线程安全、自定义分隔符的时间格式化;旧标准需用std::put_time配合localtime_r/s并加锁;避免使用线程不安全且格式固定的std::ctime/asctime。

用 std::chrono + std::format(C++20)最干净
如果你用的是 C++20 且编译器支持 std::format(如 MSVC 19.3x、GCC 13+、Clang 15+),这是最直接、线程安全、无时区陷阱的方式:
-
std::chrono::system_clock::now()获取当前时间点 - 用
std::chrono::floor<:chrono::seconds>(...)</:chrono::seconds>截断到秒级(避免毫秒干扰格式) -
std::format支持类似 Python 的格式字符串,分隔符可任意指定,比如"{:%Y-%m-%d_%H:%M:%S}"中的-和_就是分隔符
#include <chrono>
#include <format>
#include <iostream>
int main() {
auto now = std::chrono::system_clock::now();
auto t = std::chrono::floor<std::chrono::seconds>(now);
auto s = std::format("{:%Y_%m_%d %H:%M:%S}", t); // 输出:2024_05_22 14:30:45
std::cout << s << '\n';
}
兼容 C++11/14/17:用 std::put_time + std::localtime
老标准下不能用 std::format,但 std::put_time 是可靠选择;注意它依赖 std::localtime,不是线程安全的——多线程必须加锁或改用 std::localtime_r(POSIX)或 localtime_s(MSVC)
- 分隔符由格式字符串控制:
%Y/%m/%d %H:%M:%S→2024/05/22 14:30:45 - 不要直接传
std::time(nullptr)给std::put_time;必须先转成std::tm* - Windows 下推荐用
localtime_s避免 CRT 警告;Linux/macOS 用localtime_r
#include <chrono>
#include <iomanip>
#include <iostream>
#include <sstream>
int main() {
auto now = std::chrono::system_clock::to_time_t(
std::chrono::system_clock::now()
);
std::tm tm_buf{};
#ifdef _WIN32
localtime_s(&tm_buf, &now);
#else
localtime_r(&now, &tm_buf);
#endif
std::ostringstream oss;
oss << std::put_time(&tm_buf, "%Y.%m.%d_%H.%M.%S"); // 输出:2024.05.22_14.30.45
std::cout << oss.str() << '\n';
}
别踩 std::ctime 和 asctime 的坑
这两个函数返回 char*,内容写在静态缓冲区里,多次调用会互相覆盖;而且格式完全固定(如 Wed May 22 14:30:45 2024\n),无法自定义分隔符
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 即使只调用一次,也得立刻拷贝结果,否则下次调用就失效
-
std::ctime(&t)返回带换行符的字符串,常被忽略导致日志换行错乱 - 它们不接受自定义格式,所谓“特定符号分隔”根本做不到
跨平台分隔符定制的关键点
真正影响分隔符自由度的不是语言版本,而是你选的格式化接口是否支持 strftime-style 模板。只要支持,%Y%m%d 之间塞什么字符都行——下划线、点、冒号、中文顿号甚至 emoji(只要终端能显示)
立即学习“C++免费学习笔记(深入)”;
- 分隔符位置只在格式字符串里体现,和系统 locale 无关(除非你用了
%c这类本地化宏) - 如果要 UTC 时间,别用
std::localtime,改用std::gmtime_r/gmtime_s,再配std::put_time - C++20 前若需毫秒级,得手动提取:用
std::chrono::duration_cast<std::chrono::milliseconds>算出毫秒数再拼接,别指望put_time支持%f
分隔符本身没技术门槛,难的是选对 API 层——用错一层,后面全得绕路补救。

















