最稳妥方式是用std::chrono::system_clock::now()获取时间点,分别提取time_t日期部分和duration_cast毫秒部分:先转time_t再localtime解析年月日时分秒,再用duration_cast取毫秒余数。

用 std::chrono 获取毫秒级时间戳字符串(无分隔符)
直接拼接年月日时分秒毫秒,最稳妥的方式是用 std::chrono::system_clock::now() 获取时间点,再转为 std::time_t 提取年月日时分秒,用 std::chrono::duration_cast 单独提取毫秒部分。别用 std::time(nullptr) ——它只到秒级,丢掉毫秒。
常见错误是把 std::chrono::system_clock::to_time_t() 和 std::chrono::duration_cast<:chrono::milliseconds>()</:chrono::milliseconds> 混在一起算总毫秒数,结果溢出或跨天错位。正确做法是分两段处理:日期部分走 std::localtime 或 std::gmtime,毫秒部分从时间点减去整秒后单独取余。
- 用
std::chrono::system_clock::now()得到当前时间点 - 用
std::chrono::system_clock::to_time_t(tp)转成time_t,再用std::localtime解析年月日时分秒 - 用
tp.time_since_epoch().count() % 1000得到毫秒(注意:count()返回的是纳秒或微秒,取决于实现;稳妥起见用duration_cast<:chrono::milliseconds></:chrono::milliseconds>)
auto tp = std::chrono::system_clock::now();
auto ms = std::chrono::duration_cast<:chrono::milliseconds>(tp.time_since_epoch()).count() % 1000;
std::time_t t = std::chrono::system_clock::to_time_t(tp);
std::tm tm_buf{};
#ifdef _WIN32
localtime_s(&tm_buf, &t);
#else
localtime_r(&t, &tm_buf);
#endif
std::ostringstream oss;
oss <h3>避免 <code>std::put_time</code> 的陷阱:它不支持毫秒</h3>
<p><code>std::put_time</code> 只能格式化 <code>std::tm</code>,没有毫秒字段。试图用 <code>%f</code> 或自定义扩展会编译失败或输出未定义内容。很多开发者卡在这儿,以为加个 <code>%f</code> 就行,实际标准库根本不认。</p>
<p>如果你硬要一行写完,别碰 <code>std::put_time</code>。要么自己拼字符串(如上),要么用第三方库如 <code>date.h</code>(Howard Hinnant’s date library),它支持 <code>format("%Y%m%d%H%M%S%ms", tp)</code> 这种写法,但引入外部依赖需权衡。</p>
<ul>
<li>
<code>std::put_time</code> 的格式符里没有毫秒对应项</li>
<li>
<code>%f</code> 是 POSIX 扩展,C++ 标准不保证支持</li>
<li>即使编译通过,不同平台输出可能为空、乱码或崩溃</li>
</ul>
<h3>跨平台时注意 <code>localtime</code> 的线程安全</h3>
<p>Windows 下 <code>localtime</code> 不是线程安全的,Linux/macOS 下 <code>localtime_r</code> 是安全替代。直接调 <code>localtime</code> 在多线程环境可能返回错误日期,尤其高并发生成时间戳时容易复现。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2659" title="C++"><img
src="https://img.php.cn/upload/skill/000/000/081/178927213426672.jpg" alt="C++" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill2659" title="C++" class="overflowclass">C++</a>
<p class="overflowclass">"空空如也"</p>
</div>
<a rel="nofollow" href="/xiazai/skill2659" title="C++" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<p>别写 <code>std::tm* tm_ptr = std::localtime(&t);</code> ——这是隐患。统一用带 <code>_r</code> 后缀版本(POSIX)或 <code>localtime_s</code>(Windows),并传入栈上分配的 <code>std::tm</code> 缓冲区。</p>
<ul>
<li>Linux/macOS:必须用 <code>localtime_r(&t, &tm_buf)</code>
</li>
<li>Windows:用 <code>localtime_s(&tm_buf, &t)</code>
</li>
<li>缓冲区必须是可写的 <code>std::tm</code> 实例,不能是 <code>nullptr</code> 或只读内存</li>
</ul>
<h3>要不要用 UTC 时间?看场景</h3>
<p>如果时间戳用于日志归档或分布式系统对账,强烈建议用 UTC,避免夏令时跳变或本地时区切换导致排序错乱。用 <code>std::gmtime</code>(或 <code>gmtime_r</code>/<code>gmtime_s</code>)代替 <code>localtime</code> 即可,其余逻辑完全一样。</p>
<p>但注意:UTC 时间戳字符串和本地时间戳字符串长度一致,只是数值不同。比如北京时间 2024-05-21 15:30:00 对应 UTC 是 07:30:00,字符串变成 <code>"20240521073000123"</code>。别在调试时误以为“少了8小时就是错了”。</p>
<ul>
<li>日志/文件名/数据库主键:优先 UTC</li>
<li>用户界面显示:用本地时间</li>
<li>和 Java/Python 服务交互:确认对方约定用 UTC 还是本地时间,不一致就会出 bug</li>
</ul>
<p>毫秒部分本身与时区无关,但日期部分受时区影响极大——这是最容易被忽略的点。</p></:chrono::milliseconds>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










