system_clock::now() 返回 time_point,须用 system_clock::to_time_t() 转为 time_t 才能格式化;直接调用 time_since_epoch().count() 会因精度单位不明导致错误;跨平台时 epoch 和精度不一致,应避免硬编码换算,高精度测量优先用 steady_clock。

system_clock 获取当前时间戳要转成 time_t 才能格式化
直接用 system_clock::now() 拿到的是一个 time_point,不是秒数,也不能直接传给 strftime 或 localtime。必须先调用 time_point::time_since_epoch() 再转换为秒级整数,或者更稳妥地用 system_clock::to_time_t()。
- 错误写法:
auto tp = system_clock::now(); printf("%ld", tp.time_since_epoch().count());——count()返回的是纳秒或微秒(取决于实现),不是秒 - 正确做法:
time_t t = system_clock::to_time_t(system_clock::now());,之后可用localtime(&t)或gmtime(&t) - 注意:
to_time_t()舍入到秒,丢失亚秒精度;若需毫秒级日志,应保留time_point并手动计算毫秒偏移
跨平台时 system_clock 的 epoch 和精度不保证一致
system_clock 的起点(epoch)在标准里只规定“是某个任意时间点”,实际中 Windows 通常用 1970-01-01 UTC(同 POSIX),但某些旧 libc 实现可能不同;精度也因系统而异——Linux 通常支持纳秒,Windows QueryPerformanceCounter 底层可能只暴露毫秒级分辨率。
- 不要假设
system_clock::duration::period::den == 1000000000(即纳秒),应通过ratio计算:using sec = duration_cast<seconds>(tp.time_since_epoch()).count();</seconds> - 避免硬编码单位换算,比如写
tp.time_since_epoch().count() / 1000000得毫秒——改用duration_cast<milliseconds>(tp.time_since_epoch()).count()</milliseconds> - 若需高精度且可移植的时间差测量,优先用
steady_clock;system_clock只用于挂钟时间(如日志打时间、文件修改时间)
从 time_t 转回 system_clock::time_point 容易忽略时区和闰秒
system_clock::from_time_t(t) 总是把 t 当作 UTC 时间处理,不会自动适配本地时区。而且 C++ 标准库完全不处理闰秒,所有转换都按“平滑的 POSIX 秒”进行。
- 常见误解:把
localtime返回的struct tm直接塞进mktime,再用from_time_t—— 这会把本地时间当 UTC 解释,导致结果偏差 8 小时(东八区为例) - 安全做法:如果已有本地时间字符串,先用
std::get_time解析为tm,再调用mktime得到 UTC 对应的time_t,最后system_clock::from_time_t - 闰秒问题:2016-12-31 23:59:60 这一秒在
system_clock中不存在,会被跳过或合并——生产环境若依赖精确到秒的事件排序,得额外记录 UTC 时间字符串而非只存time_point
打印带毫秒的本地时间字符串要自己拼接
标准库没有内置的“%Y-%m-%d %H:%M:%S.xxx”格式化函数,strftime 不支持毫秒。必须拆开:先用 system_clock::to_time_t 得秒级时间,再用 duration_cast<milliseconds></milliseconds> 提取毫秒部分。
立即学习“C++免费学习笔记(深入)”;
- 示例:
auto now = system_clock::now(); auto ms = duration_cast<milliseconds>(now.time_since_epoch()) % 1000; time_t t = system_clock::to_time_t(now); tm buf{}; localtime_r(&t, &buf); // Linux;Windows 用 localtime_s char str[64]; strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &buf); sprintf(str + strlen(str), ".%03ld", ms.count()); - 注意:
localtime_r非 Windows 原生,MSVC 需用localtime_s;strftime不写入末尾 \0,sprintf拼接前要确认缓冲区足够 - 更健壮的做法是用第三方库(如 Howard Hinnant 的 date.h),但若仅需简单日志,手拼比引入依赖更轻量
system_clock 时,最常踩的坑不是语法,而是混淆“挂钟时间”和“持续时间”、忽略平台差异带来的精度/epoch 偏移、以及把本地时间和 UTC 当成一回事。这些地方一错,时间就对不上,排查起来特别慢。


















