正确做法是用std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()获取自Unix纪元起的毫秒级整数时间戳,类型为long long,避免精度丢失和跨平台不一致问题。

怎么用 system_clock 获取毫秒级时间戳(整数)
直接取 system_clock::now() 的毫秒值,核心是两步:先获取时间点,再转成毫秒数。别用 time_t 转换再手动算——精度会丢,而且跨平台行为不一致。
正确做法是用 duration_cast 把时钟的 duration 转成 milliseconds,再调用 .count():
#include <chrono>
#include <iostream>
auto now_ms = std::chrono::duration_cast<:chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
// now_ms 是 long long 类型的毫秒时间戳(自1970-01-01 00:00:00 UTC起)
</:chrono::milliseconds></iostream></chrono>
- 必须用
.time_since_epoch()拿到duration,不能对time_point直接duration_cast - 返回类型是
std::chrono::milliseconds::rep,通常是long long,别用int接,2038年之后会溢出 - Windows 上
system_clock实际精度可能只有 15ms 左右(取决于系统定时器),别误以为能稳定输出每毫秒变化的值
duration_cast 截断还是四舍五入?
duration_cast 永远向下截断(truncates toward zero),不是四舍五入。比如 1234.8ms 会被转成 1234ms,1234.1ms 也是 1234ms。
- 如果需要“向上取整到毫秒”,得手动加偏移:
duration_cast(d + 999us) - 如果只是记录日志或做简单差值计算,截断完全够用;但做定时调度、帧同步等场景,得意识到这个偏差可能累积
- 不要用
round或floor等函数套在duration上——它们不接受duration类型,强行转 double 会损失精度(尤其大数值时)
为什么不用 steady_clock?
因为 steady_clock 不保证对应 Unix 时间戳。它的起点是未指定的某个时刻,且不随系统时间调整而变——适合测间隔,不适合生成可持久化、可比较的全局时间戳。
-
system_clock是唯一被标准要求能通过to_time_t转成time_t的时钟,也意味着它锚定在 UTC - 如果你看到有人用
steady_clock算“毫秒时间戳”,那大概率是错的:重启后值归零,NTP 调整时也不连续,存数据库或传给前端会出乱子 - 例外:仅限单次进程内做相对计时(如函数耗时统计),这时才该选
steady_clock
Windows 下 system_clock::now() 精度不够怎么办?
默认情况下,system_clock 在 Windows 上依赖 GetSystemTimeAsFileTime,分辨率约 15.6ms。真要更高精度(比如想逼近 1ms),得绕开标准库,用 QueryPerformanceCounter 自己封装,但代价是失去可移植性和 Unix 时间语义。
- 99% 的业务场景(HTTP 日志、DB 写入时间、心跳上报)根本不需要高于 15ms 的精度,硬改反而引入复杂性
- 若确实需要高精度单调时间(非 Unix 时间戳),优先考虑
steady_clock+high_resolution_clock(注意:后者在 MSVC 中常 alias 到steady_clock) - 别试图用
std::chrono::high_resolution_clock::now()替代system_clock来取时间戳——它的 epoch 未定义,time_since_epoch().count()没有意义
实际写的时候,最常被忽略的是 .time_since_epoch() 这一步。漏掉它,编译不过;写成 duration_cast,GCC/Clang 会报错说无法从 time_point 转 duration。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










