用 std::chrono::system_clock::now() 获取时间点,再通过 localtime_r(linux/macos)或 localtime_s(windows)转为 struct tm,最后用 std::put_time 格式化输出;c++20 可用 std::chrono::zoned_time 或 std::format,但生产环境推荐 std::put_time + std::ostringstream 中转。

如何用 std::chrono 获取并格式化本地时间
Linux 的 date 命令本质是读系统时钟、按模板格式化输出。C++11 起,std::chrono + std::format(C++20)或 std::put_time(C++11)就能覆盖绝大多数需求。别碰 time() + localtime() 这套老接口——它线程不安全,且时区处理模糊。
关键点:必须用 std::chrono::system_clock::now() 获取时间点,再通过 std::chrono::zoned_time(C++20)或手动调用 localtime_r(POSIX)转为本地日历时间。Windows 下需额外处理时区偏移,否则 localtime 可能返回错误结果。
-
std::put_time依赖 C 风格的struct tm,需先用localtime_r(&sec, &tm)(Linux/macOS)或localtime_s(&tm, &sec)(Windows)安全转换 - C++20 的
std::format支持{:%Y-%m-%d %H:%M:%S}这类格式,但目前 GCC/Clang 对宽字符和时区支持仍不稳定,生产环境建议降级用std::put_time - 注意
std::put_time返回的是std::basic_ostream&,不能直接赋值给std::string;得用std::ostringstream中转
解析类似 date +"%H:%M:%S" 的格式字符串
Linux date 的 + 后格式串(如 %Y、%Z)不是正则,而是 strftime 标准。C++ 里对应 std::put_time 的格式符完全兼容该标准,但仅限于 struct tm 能提供的字段——比如 %N(纳秒)或 %s(秒数)无法直接用 put_time 输出,得手动提取。
常见陷阱:%Z 在不同平台行为不一:Linux 返回时区缩写(如 CST),macOS 可能为空,Windows 返回宽字符字符串;%z(UTC 偏移)更可靠,但需确保 tm 结构中 tm_gmtoff 字段已正确填充(glibc 默认有,MSVC 没有)。
- 若需支持
%s(自 Epoch 起秒数),直接用std::chrono::system_clock::to_time_t(now) - 若需毫秒/微秒,从
std::chrono::system_clock::now()减去 epoch 时间点,再用.time_since_epoch().count()提取整数,自行除以 1000 或 1000000 - 不要尝试用
std::regex解析格式串——strftime规则简单,硬编码映射表(如"%H"→tm_hour)更轻量、无依赖
处理时区与夏令时(DST)偏差
单纯调用 localtime 不保证 DST 正确性:它依赖系统 TZ 环境变量,且对历史时间或跨年时间点可能失效。例如 date -d "2005-04-01" "+%Z" 在某些 libc 版本上返回错误缩写。
PyCharm 2026.2.0.1 Linux版提供 JetBrains 官方 2026.2.0.1 版本安装包,适合需要指定 PyCharm 版本进行 Python 项目开发、运行和调试的用户。
真正可靠的方案是使用 IANA 时区数据库,但 C++ 标准库至今未内置。折中做法:用 std::chrono::zoned_time(C++20)配合 std::chrono::current_zone(),或调用系统命令 date +"%Z %z" 反查当前时区信息(仅限调试)。
- Linux 下可读
/etc/localtime符号链接目标(如/usr/share/zoneinfo/Asia/Shanghai),但注意容器环境可能缺失该文件 - 避免用
setenv("TZ", "...", 1); tzset();动态切时区——这会污染整个进程,且多线程下极不安全 - 如果程序只需输出“当前本地时间”,用
std::chrono::current_zone()->to_local(...)是最干净的路径(C++20)
绕过 C++20 依赖实现最小可行版本
很多项目还卡在 C++17,没法用 std::format 或 zoned_time。此时核心逻辑就三步:获取时间戳 → 转 struct tm → 格式化字符串。关键是把 strftime 的能力封装成易用接口,而不是重复造轮子。
示例片段(C++11 兼容):
std::time_t now = std::time(nullptr);
std::tm tm_buf;
#ifdef _WIN32
localtime_s(&tm_buf, &now);
#else
localtime_r(&now, &tm_buf);
#endif
std::ostringstream oss;
oss
<p>这段代码能跑通大多数场景,但要注意:<code>std::put_time</code> 对宽字符支持差,如果格式串含中文(如 <code>"%Y年%m月%d日"</code>),必须确保 locale 已设为 <code>std::locale("zh_CN.UTF-8")</code>,且终端编码匹配,否则输出乱码。</p>
<p>真正难啃的是带相对时间计算的功能(如 <code>date -d "next Monday"</code>),那已经超出标准库能力范围,得引入第三方库(如 Howard Hinnant 的 date.h)或调用系统 <code>date</code> 命令本身——后者反而更稳,毕竟你本来就在模拟它。</p>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










