std::chrono 获取高精度本地时间需先用 system_clock::now() 获取时间点,转 time_t 后通过 localtime_s(Windows)或 localtime_r(POSIX)解析为 tm 结构;C++20 可用 zoned_time + current_zone() 配合 chrono::format 实现时区感知格式化。

用 std::chrono 获取高精度本地时间(C++11 及以上)
直接用 std::chrono + std::time_t 转换是最轻量、跨平台的方案,但注意它默认返回的是 UTC 时间,需手动转为本地时区。
- 先调用
std::chrono::system_clock::now()获取当前时间点 - 用
std::chrono::system_clock::to_time_t()转成time_t - 再用
std::localtime()(非线程安全)或std::localtime_r()(POSIX,线程安全)解析为tm结构 -
std::localtime()会受TZ环境变量或系统时区影响,Windows 下可能忽略该变量,建议显式调用_tzset()后再用
auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);
std::tm tm_buf{};
#ifdef _WIN32
localtime_s(&tm_buf, &t); // Windows 安全版本
#else
localtime_r(&t, &tm_buf); // Linux/macOS 线程安全
#endif
// tm_buf.tm_year + 1900, tm_buf.tm_mon + 1, tm_buf.tm_mday 等即为本地日期
用 std::format 格式化输出(C++20)
如果项目已支持 C++20,std::format 是最简洁的格式化方式,但需注意编译器支持度和标准库实现完整性。
- GCC 13+、Clang 15+、MSVC 19.35+ 才完整支持
std::format的日期格式化 - 必须配合
std::chrono::zoned_time或std::chrono::current_zone()才能正确处理本地时区,仅靠std::chrono::system_clock::now()默认输出 UTC - 格式字符串如
"%Y-%m-%d %H:%M:%S"需通过std::chrono::format()(非std::format)调用,容易混淆
// C++20 示例(需启用 -std=c++20)
auto zt = std::chrono::zoned_time{std::chrono::current_zone(), std::chrono::system_clock::now()};
std::cout << std::chrono::format("%Y-%m-%d %H:%M:%S", zt) << "\n";
避免 ctime() 和 asctime() 的陷阱
这两个函数返回静态缓冲区指针,多次调用会覆盖内容,且结果不可重入,在多线程或嵌套调用中极易出错。
-
ctime(&t)返回形如"Sun Sep 17 12:34:56 2023\n"的字符串,末尾带换行符,常被忽略导致日志错位 -
asctime(&tm)同样使用内部静态缓冲区,且不检查tm字段有效性(如tm_year小于 70 会溢出) - 它们都不支持自定义格式,也无法区分 UTC/本地时间——
ctime()实际调用的是localtime(),但行为隐晦
Windows 下获取精确毫秒级本地时间(GetLocalTime)
若只跑 Windows 且需要毫秒级精度(比如性能打点),GetLocalTime() 比 localtime_r 更直接,但完全不跨平台。
立即学习“C++免费学习笔记(深入)”;
- 返回
SYSTEMTIME结构,字段名直观(wYear,wMonth,wMilliseconds),无需加偏移 - 注意
wMilliseconds是毫秒部分,不是自纪元以来的毫秒数;如需绝对毫秒数,应改用GetSystemTimeAsFileTime()再转换 - 该 API 不受 C 运行时区设置影响,始终返回系统本地时间,适合对时区逻辑要求明确的场景
SYSTEMTIME st; GetLocalTime(&st); // st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds跨平台代码里混用
std::localtime_r 和 localtime_s 很常见,但真正容易出问题的是时区缓存——localtime 系列函数内部会缓存时区规则,若程序运行中系统时区变更,旧缓存未刷新就会返回错误时间。Linux 下可调用 tzset() 强制刷新,Windows 则需重启进程或自行维护时区状态。


















