最简方式是先用localtime_r/gmtime_r将tv_sec转struct tm,再拼接tv_usec;需校验tv_usec范围并按意图选本地/utc时区函数。

timeval 转 std::string 最简方式
直接用 std::put_time 不行,因为 struct timeval 不是 std::tm;必须先转成 time_t + 微秒部分单独处理。
最常用且安全的做法是用 localtime_r(Linux/macOS)或 localtime_s(Windows)把 tv_sec 转成 struct tm,再拼接微秒:
#include <chrono>
#include <ctime>
#include <iostream>
#include <sstream>
std::string format_timeval(const struct timeval& tv) {
struct tm tm_buf;
#ifdef _WIN32
localtime_s(&tm_buf, &tv.tv_sec);
#else
localtime_r(&tv.tv_sec, &tm_buf);
#endif
std::ostringstream oss;
oss
<h3>避免时区错误的关键点</h3>
<p><code>timeval.tv_sec</code> 是 UTC 时间戳,但 <code>localtime_*</code> 默认按本地时区解析——如果你要输出 UTC 时间,得换 <code>gmtime_r</code> / <code>gmtime_s</code>。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img
src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a>
<p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p>
</div>
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>输出本地时间:用 <code>localtime_r</code>(POSIX)或 <code>localtime_s</code>(MSVC)</li>
<li>输出 UTC 时间:必须用 <code>gmtime_r</code> 或 <code>gmtime_s</code>,否则时间会偏移</li>
<li>不加锁的 <code>localtime</code> 在多线程下不安全,别用</li>
</ul>
<h3>用 std::format(C++20)更简洁但要注意兼容性</h3>
<p>C++20 的 <code>std::format</code> 不能直接格式化 <code>timeval</code>,仍需拆解。但它能简化字符串拼接:</p>
<pre class="brush:php;toolbar:false;">
// C++20,需编译器支持(GCC 13+ / Clang 15+ / MSVC 19.32+)
auto t = std::chrono::system_clock::from_time_t(tv.tv_sec);
auto us = std::chrono::microseconds(tv.tv_usec);
auto tp = t + us;
auto tms = std::chrono::time_point_cast<:chrono::milliseconds>(tp);
std::string s = std::format("{:%Y-%m-%d %H:%M:%S}.{:03}",
std::chrono::floor<:chrono::seconds>(tp),
tms.time_since_epoch().count() % 1000);
</:chrono::seconds></:chrono::milliseconds>
注意:std::format 对微秒精度支持有限,上面示例只保留毫秒;要完整 6 位微秒,还得手动补零或用 std::ostringstream。
常见错误:tv_usec 超出范围导致输出错乱
tv_usec 理论上应在 [0, 999999] 区间,但某些系统或手动生成的 timeval 可能越界(比如 1234567),直接打印会显示 “1.234567 秒” 这种非法值。
- 务必校验:
if (tv.tv_usec = 1000000) - 修正方式:进位到
tv_sec,再取模:tv.tv_sec += tv.tv_usec / 1000000; tv.tv_usec %= 1000000; - 尤其在跨平台接收网络时间戳、或用
gettimeofday+ 手动计算时容易踩坑
tv_usec 的合法性检查和时区意图是否明确——这两点漏掉一个,日志就可能对不上监控指标。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










