推荐用 std::chrono::system_clock::now() 获取时间点,转 std::time_t 后调用 std::localtime(注意线程不安全)或 std::gmtime,再用 std::strftime 格式化;需毫秒级精度时用 duration_cast;避免 std::put_time 因 locale 导致格式异常。

用 std::chrono 和 std::time_t 获取本地时间(推荐)
现代 C++ 推荐用 std::chrono 配合 std::system_clock 转换为可读时间,再用 std::localtime 或 std::gmtime 格式化。注意 std::localtime 返回的是静态缓冲区指针,多线程下不安全。
- 先调用
std::system_clock::now()获取当前时间点 - 用
std::system_clock::to_time_t()转成std::time_t - 传给
std::localtime()(本地时区)或std::gmtime()(UTC)得到std::tm* - 用
std::strftime()输出格式化字符串,避免直接拼接tm_mday等字段(容易漏补零)
示例:
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); // 注意:不是 const,且非线程安全 char buf[64]; std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", <); // buf 现在是类似 "2024-05-21 14:32:18"
为什么不用 std::put_time 直接输出?
std::put_time 看起来简洁,但依赖 std::ostream 和流操作,实际使用中容易因 locale 设置导致格式意外变化(比如月份名变成中文、AM/PM 符号异常),且无法直接写入 C 风格字符串或 std::string 缓冲区。
- 它底层仍调用
strftime,但封装层屏蔽了错误检查(如缓冲区溢出) - 若需精确控制长度、避免 locale 干扰,优先选
std::strftime+ 固定大小数组 - 如果必须用
std::put_time,务必提前设置std::locale::global(std::locale::classic())
跨平台获取毫秒级时间戳(含小数秒)
仅靠 std::time_t 只能到秒级;要毫秒,必须用 std::chrono::milliseconds 或更高精度的 duration。
-
std::chrono::system_clock::now().time_since_epoch().count()返回纳秒数(具体单位取决于实现,通常是纳秒或微秒) - 转毫秒:除以
1'000'000(纳秒)或1'000(微秒),再用static_cast<long long></long>截断 - Windows 下
std::system_clock可能基于GetSystemTimeAsFileTime,Linux 下通常基于clock_gettime(CLOCK_REALTIME),两者都支持亚秒精度
示例(毫秒时间戳):
auto ms = std::chrono::duration_cast<:chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count(); // 类似 1716302538123</:chrono::milliseconds>
常见坑:时区、线程安全与 Windows 特殊行为
本地时间函数在不同平台表现不一,尤其 Windows 的 localtime_s 和 Linux 的 localtime_r 是线程安全替代版,但标准 C++ 不提供统一接口。
-
std::localtime在 Windows 上默认不是线程安全的;应改用localtime_s(MSVC)或localtime_r(POSIX) - macOS / Linux 默认使用系统时区,Windows 可能受注册表或控制面板设置影响,
setenv("TZ", "UTC", 1)后调用tzset()才能强制 UTC -
std::tm::tm_year是从 1900 开始的偏移量,tm_mon是 0–11,直接打印会出错 - C++20 引入了
<chrono></chrono>的日历类型(如std::chrono::year_month_day),但目前主流编译器支持有限,别贸然用
真正麻烦的从来不是“怎么拿到时间”,而是“拿到的时间到底属于哪个时区、能不能被并发访问、有没有隐式 locale 依赖”。这些细节不提前踩一遍,上线后就只能靠日志倒推。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











