
用 std::chrono 获取毫秒级时间戳最可靠
Windows 和 Linux 下都支持,且不依赖平台 API,避免了 gettimeofday 或 GetSystemTimeAsFileTime 的兼容性问题。核心是用 std::chrono::system_clock 配合 time_since_epoch() 转换为毫秒。
常见错误是直接用 time(nullptr) ——它只到秒级,且返回的是 time_t,无法满足毫秒需求。
-
std::chrono::system_clock::now().time_since_epoch().count()返回的是纳秒(Linux)或 100 纳秒(Windows)单位,需手动转毫秒 - 推荐统一除以
1'000'000得到毫秒数,类型用long long防溢出 - 若需字符串格式(如 "2024-05-22 14:30:22.123"),再用
std::chrono::system_clock::to_time_t+localtime_s/localtime_r拆解,但注意线程安全
auto now = std::chrono::system_clock::now(); auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count(); // ms 是自 Unix epoch 起的毫秒数,类型为 long long
Windows 下用 GetSystemTimeAsFileTime 的坑
它返回的是 FILETIME(100 纳秒为单位),看似精确,但容易在转换时出错:直接减去 Windows epoch(1601 年)再除 10000 得毫秒,结果可能因 64 位整数截断或符号处理错误而偏差几秒。
- FILETIME 是两个
DWORD拼成的 64 位无符号整数,必须用ULARGE_INTEGER或uint64_t接收,不能用long - Unix epoch(1970)比 Windows epoch(1601)晚 11644473600 秒,对应 116444736000000000 个 100 纳秒单位
- 转换公式必须是:
(filetime_as_uint64 - 116444736000000000) / 10000
跨平台封装一个毫秒时间戳函数
如果项目要同时跑在 Windows/Linux/macOS,别写两套逻辑。用 std::chrono 就够了,它在所有主流编译器(MSVC、GCC、Clang)中行为一致。
立即学习“C++免费学习笔记(深入)”;
- 不要用宏判断平台后调不同 API,徒增维护成本
- 避免用
clock_gettime(CLOCK_REALTIME, ...):Linux 支持,但 macOS 不支持CLOCK_REALTIME,得 fallback 到mach_absolute_time - 如果必须用 C 风格接口,可封装为 inline 函数,返回
long long类型毫秒值,不暴露内部时钟类型
inline long long current_ms() {
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
}
注意时区与精度的实际限制
system_clock 表示的是系统实时时钟(wall clock),受 NTP 同步、手动调时影响,可能回跳或跳变。它不是单调时钟,不适合测间隔。
- 测函数耗时请用
std::chrono::steady_clock,它不随系统时间调整而变 - 毫秒级“精度”不等于“准确度”:普通 PC 的 system_clock 实际分辨率常为 10–15ms(尤其 Windows),
QueryPerformanceCounter才能逼近微秒级 - 如果日志需要高一致时间戳,建议在程序启动时缓存一次
system_clock::now(),后续用steady_clock偏移计算,避免频繁调用带来的开销和抖动










