C++20中可用std::format结合time_t手动拼接毫秒,C++23支持直接格式化time_point含毫秒,或退而用std::put_time与ostringstream兼容C++20。

如果您需要在 C++20 或更高标准中将 std::chrono 的时间点格式化为包含毫秒的可读字符串,std::format 提供了简洁且类型安全的方式。以下是实现该目标的多种方法:
一、使用 std::format 配合 time_t 和 std::chrono::system_clock::to_time_t
该方法将系统时钟时间点转换为 time_t,再通过 std::format 的日期格式说明符进行基础格式化,毫秒部分需手动提取并拼接。
1、获取当前时间点:auto now = std::chrono::system_clock::now();
2、提取毫秒部分:auto ms = std::chrono::duration_cast<:chrono::milliseconds>(now.time_since_epoch()) % 1000;
立即学习“C++免费学习笔记(深入)”;
3、转换为 time_t 并格式化主干:auto t = std::chrono::system_clock::to_time_t(now); auto base = std::format("{:%Y-%m-%d %H:%M:%S}", std::chrono::system_clock::from_time_t(t));
4、拼接毫秒:auto result = std::format("{}.{:03}", base, ms.count());
二、使用 std::format 直接格式化 std::chrono::time_point(C++23 扩展)
C++23 标准扩展了 std::format 对 std::chrono 类型的支持,允许直接格式化带毫秒精度的时间点,前提是编译器启用 C++23 并支持该特性。
1、声明当前时间点:auto now = std::chrono::system_clock::now();
2、使用 C++23 格式说明符:auto result = std::format("{:%Y-%m-%d %H:%M:%S.}{:03}", now, std::chrono::duration_cast<:chrono::milliseconds>(now.time_since_epoch()).count() % 1000);
3、注意:必须确保编译器支持 C++23 的 chrono 格式化扩展,否则会编译失败。
三、借助 std::put_time 与 std::ostringstream 拼接毫秒(兼容 C++20)
当 std::format 对 chrono 的直接支持受限时,可退而使用 std::put_time 格化秒级部分,再以流方式追加毫秒,保证 C++20 兼容性。
1、获取时间点与毫秒:auto now = std::chrono::system_clock::now(); auto ms = std::chrono::duration_cast<:chrono::milliseconds>(now.time_since_epoch()).count() % 1000;
2、转换为 std::tm:std::time_t t = std::chrono::system_clock::to_time_t(now); std::tm tm_buf {}; gmtime_s(&tm_buf, &t); // Windows;Linux 用 gmtime_r(&t, &tm_buf)
3、构造字符串流:std::ostringstream oss; oss
4、提取结果:auto result = oss.str();
四、封装为可复用函数模板(支持任意时钟)
为提升复用性与类型安全性,可定义模板函数,接受任意 std::chrono::time_point 类型,并统一输出为“YYYY-MM-DD HH:MM:SS.mmm”格式。
1、声明模板函数:template
2、内部计算毫秒偏移:auto ms = std::chrono::duration_cast<:chrono::milliseconds>(tp.time_since_epoch()).count() % 1000;
3、转换为 system_clock 时间点以便格式化:auto sys_tp = Clock::to_sys(tp); auto t = std::chrono::system_clock::to_time_t(sys_tp);
4、组合字符串:return std::format("{:%Y-%m-%d %H:%M:%S}.{:03}", std::chrono::system_clock::from_time_t(t), ms);
五、处理本地时区而非 UTC 的时间戳
默认 std::format 使用 UTC,若需本地时区,必须显式转换 time_t 到本地 std::tm,且注意线程安全性与平台差异。
1、获取本地 time_t:auto now = std::chrono::system_clock::now(); auto t = std::chrono::system_clock::to_time_t(now);
2、转换为本地 struct tm:std::tm local_tm {}; localtime_s(&local_tm, &t); // Windows;Linux 用 localtime_r(&t, &local_tm)
3、提取毫秒:auto ms = std::chrono::duration_cast<:chrono::milliseconds>(now.time_since_epoch()).count() % 1000;
4、格式化并拼接:auto base = std::format("{:%Y-%m-%d %H:%M:%S}", local_tm); auto result = std::format("{}.{:03}", base, ms);
5、注意:localtime_s 和 localtime_r 是线程安全版本,不可使用非安全的 localtime。


















