推荐用 std::chrono::system_clock::now() 转 time_t 后调用线程安全的 localtime_r(POSIX)或 localtime_s(Windows)获取 tm 结构体,再读取 tm.tm_hour、tm.tm_min、tm.tm_sec 字段得到时分秒整数,确保时区明确且跨平台安全。

用 std::chrono 提取当前时间的时分秒整数
推荐用 std::chrono 配合 std::time_t 和 std::tm,这是 C++11 起最可靠、时区感知可控的方式。直接调 std::chrono::system_clock::now() 得到时间点,再转成本地时间(或 UTC)后拆解。
关键不是“获取”,而是“以什么时区为准”——std::localtime 用系统本地时区,std::gmtime 用 UTC。多数场景要本地时间,但服务端日志可能需要 UTC。
- 必须调
std::localtime或std::gmtime把time_t转成tm结构体,不能手动算 —— 夏令时、闰秒、时区偏移都会出错 -
tm.tm_hour、tm.tm_min、tm.tm_sec就是你要的int值,范围分别是[0,23]、[0,59]、[0,60](60 表示闰秒,极少见) - 注意
std::localtime返回的是静态缓冲区指针,多线程下不安全;用std::localtime_r(POSIX)或std::localtime_s(Windows)更稳妥
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
std::localtime_s(&tm_buf, &t);
#else
std::localtime_r(&t, &tm_buf);
#endif
int hour = tm_buf.tm_hour;
int minute = tm_buf.tm_min;
int second = tm_buf.tm_sec;
为什么不用 std::put_time 或字符串解析
std::put_time 是格式化输出用的,它生成字符串再 std::stoi 拆解纯属绕路,既慢又容易因格式变化(比如补零与否)导致解析失败。
- 例如
%H输出"09",但你不能假设总两位;%I还是 12 小时制,完全偏离需求 - 字符串 → 整数多一次内存分配和转换,无必要开销
- 如果真要格式化,也该在拿到
tm后直接读字段,而不是倒回去 parse 字符串
Windows 下 GetLocalTime 的坑
WinAPI 的 GetLocalTime 看似简单,但它返回的是本地时间,且结构体字段名不同(wHour、wMinute、wSecond),跨平台时容易埋雷。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
- 返回值是
SYSTEMTIME,不是标准tm,字段类型是WORD(即unsigned short),需显式转int - 它不经过
time_t,无法和std::chrono时间点直接对齐,做时间差计算时会麻烦 - 若项目要跨 Linux/macOS,硬绑 WinAPI 会让移植成本陡增
时区不一致导致小时错 1 小时的典型场景
常见于容器环境或 CI/CD:镜像默认用 UTC,但代码用 std::localtime,结果拿到的是 UTC 时间而非你期望的东八区时间。
- 检查
TZ环境变量:echo $TZ,Docker 默认为空,std::localtime会 fallback 到 UTC - 解决办法:启动容器时加
-e TZ=Asia/Shanghai,或代码里用setenv("TZ", "Asia/Shanghai", 1); tzset();(注意tzset()必须调) - 更健壮的做法是明确用 UTC(
std::gmtime),所有时间逻辑统一基准,显示时再转本地
真正麻烦的不是拿不到数字,而是拿对了却没意识到它属于哪个时区。一旦涉及定时任务、日志归档、跨服务时间比对,时区偏差会悄无声息地让逻辑错乱。

















