推荐用 std::chrono 获取高精度系统时间,它类型安全、无时区歧义、支持纳秒级精度;避免混用 system_clock 与 steady_clock,前者用于显示和日志,后者仅适用于测间隔。

用 std::chrono 获取高精度系统时间(推荐)
现代 C++ 项目应优先用 std::chrono,它类型安全、无时区歧义、支持纳秒级精度,且不依赖 C 风格全局状态。
常见错误是直接用 system_clock::now() 转 time_t 再丢给 localtime —— 这绕过了 chrono 的设计初衷,还可能因时区转换引入未定义行为。
实操建议:
- 获取当前时间点:
auto now = std::chrono::system_clock::now(); - 转为自纪元以来的毫秒数(常用日志打点):
auto ms = std::chrono::duration_cast<:chrono::milliseconds>(now.time_since_epoch()).count();</:chrono::milliseconds> - 转为可读字符串(C++20 起可用
std::format;C++17 及之前需经time_t中转,但务必用gmtime或明确指定时区)
用 ctime 系列函数获取本地时间(兼容旧代码)
ctime、localtime、strftime 是 C 标准库遗留接口,线程不安全(localtime 返回静态缓冲区指针),且隐式依赖本地时区环境变量(如 TZ)。
立即学习“C++免费学习笔记(深入)”;
典型错误现象:localtime 在多线程中返回错误时间,或容器里反复调用后值被覆盖。
实操建议:
- 必须用
localtime_r(POSIX)或localtime_s(Windows)替代localtime以保证线程安全 - 获取时间结构体后,用
strftime格式化,例如:strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); - 注意
time()返回的是秒级time_t,精度远低于chrono,不适合性能敏感场景
system_clock 与 steady_clock 别混用
system_clock 对应系统挂钟时间(可被 NTP 或手动调整),适合显示、日志、定时任务触发;steady_clock 单调递增、不受系统时间跳变影响,只适合测间隔(如 duration 计算)。
容易踩的坑:
- 误用
steady_clock::now()去生成“当前日期字符串”——它根本不提供日历语义,转time_t会失败或得到荒谬值 - 在定时循环中用
system_clock判断超时,结果因系统时间被校准导致逻辑错乱
跨平台格式化输出的最小可行方案
C++20 前没有标准方式直接把 chrono::time_point 格式化为带时区的字符串。硬要跨平台又不想引入第三方库,只能妥协:
实操建议:
- Windows 下用
GetLocalTime+SystemTimeToTzSpecificLocalTime控制时区,再GetDateFormatEx格式化 - Linux/macOS 下设
TZ环境变量后调用localtime_r,注意setenv("TZ", "Asia/Shanghai", 1); tzset();必须在首次调用前完成 - 若只要 UTC 时间,最简方案:
auto t = system_clock::to_time_t(now); gmtime_r(&t, &tm); strftime(...)
真正麻烦的不是怎么取时间,而是“你是否清楚这个时间代表什么含义:它是 UTC?本地?是否受夏令时影响?能否被系统管理员改写?”——这些语义问题,chrono 不替你回答,得靠上下文约束。


















