不能,std::chrono::system_clock::now()返回自1970-01-01 UTC起的time_point(纳秒/微秒计数),需先转time_t再用localtime/gmtime转为tm结构才能获取年月日时分秒。

std::chrono::system_clock 能不能直接得到年月日时分秒?
不能。它返回的是一个 time_point,本质是自纪元(1970-01-01 00:00:00 UTC)起经过的纳秒/微秒数,不是人类可读的时间结构。想转成年月日,必须经过 std::chrono::system_clock::to_time_t() + std::localtime() 或 std::gmtime() 两步转换。
获取本地时间(含时区)的正确三步写法
常见错误是直接对 time_point 调用 std::localtime() —— 它只接受 time_t。必须先转成 time_t:
auto now = std::chrono::system_clock::now(); std::time_t t = std::chrono::system_clock::to_time_t(now); std::tm* lt = std::localtime(&t); // 注意:返回静态缓冲区指针,非线程安全
-
std::localtime()会按当前系统时区调整,比如东八区会比 UTC 快 8 小时 - 如果多线程环境使用,改用
std::localtime_r()(POSIX)或std::localtime_s()(Windows / C++11 后部分实现) -
std::tm中的tm_year是从 1900 开始的偏移量,tm_mon是 0–11,打印前务必修正
获取 UTC 时间(无时区偏移)的写法
只要把 std::localtime() 换成 std::gmtime() 即可,其他步骤完全一致:
auto now = std::chrono::system_clock::now(); std::time_t t = std::chrono::system_clock::to_time_t(now); std::tm* utc = std::gmtime(&t); // 返回 UTC 时间,不随系统时区变化
-
std::gmtime()同样返回静态缓冲区指针,线程不安全 - 如果你需要高精度(比如毫秒级),
system_clock::now()的精度取决于平台,Linux 通常为纳秒,Windows 可能只有 15ms;别指望它总能精确到毫秒 - 注意:
system_clock在某些系统上可能被手动调整(如 NTP 同步或用户修改系统时间),它的值不单调——这点和steady_clock不同
用 std::format(C++20)一行输出格式化时间
C++20 引入了 std::format,配合 std::chrono::zoned_time 可以更安全、更清晰地处理时区和格式化:
#include <format>
#include <chrono>
#include <iostream><p>auto now = std::chrono::system_clock::now();
auto zt = std::chrono::zoned_time{std::chrono::current_zone(), now};
std::cout </p></iostream></chrono></format>
- 这行代码自动使用系统当前时区,且
zoned_time内部管理时区转换,避免std::localtime()的静态缓冲区问题 - 但要注意:
std::chrono::current_zone()在某些旧 libc 实现中可能不可用(如 glibc - 如果只用 C++11/14/17,老老实实走
to_time_t→localtime→strftime这条路更稳妥
真正容易被忽略的是:system_clock 的 time_point 和 time_t 之间转换会丢精度(time_t 通常是秒级整数),而 to_time_t() 会向下取整到最近的秒。如果你依赖毫秒级时间戳做日志或排序,别只靠 std::tm,得保留原始 time_point 做计算。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











