c++oding="utf-8" ?>
std::chrono::zoned_time自c++20起可用,需编译器支持(gcc 11+/clang 12+且启用-std=c++20)及运行时iana时区数据库;构造依赖时区与时间点绑定,支持utc/本地时间输入及预查时区对象;提取、转换与格式化须注意语义安全,dst边界易引发nonexistent_local_time异常。

std::chrono::zoned_time 在 C++20 中才可用,且依赖时区数据库
如果你用的是 GCC 11/Clang 12 或更高版本,并启用了 -std=c++20,std::chrono::zoned_time 才能正常编译。但光有标准库支持还不够——它需要运行时加载 IANA 时区数据库(如 Europe/London、America/New_York)。libstdc++ 默认不自带时区数据,你得手动安装或启用 __GLIBCXX_USE_TZDB 宏并链接 tzdb 库;libc++ 则需确保系统有 /usr/share/zoneinfo 或通过 std::chrono::locate_zone() 能访问到。
常见错误现象:std::chrono::locate_zone("Asia/Shanghai") 抛出 std::runtime_error: Unknown time zone,说明时区数据缺失或路径不可达。
- Linux 上检查
/usr/share/zoneinfo/Asia/Shanghai是否存在 - macOS 可能需要安装
tzdata(例如 via Homebrew) - Windows 没有原生 zoneinfo 目录,需自己提供或用第三方 tzdb 实现(如 Howard Hinnant 的
date库)
构造 zoned_time 的三种常用方式及参数差异
std::chrono::zoned_time 本质是“时区 + 时间点”的绑定,不是独立的时间类型。构造时必须明确指定时区和时间值,且二者语义不能混淆:传入的 sys_time(UTC 时间)和 local_time(本地时间)会触发不同转换逻辑。
- 用 UTC 时间构造:
zoned_time{"Asia/Shanghai", sys_seconds{1717027200s}}→ 自动转为东八区本地时间(2024-05-30 00:00:00 CST) - 用本地时间构造:
zoned_time{"Asia/Shanghai", local_seconds{1717027200s}}→ 解释为“上海本地时间 2024-05-30 00:00:00”,再转成对应 UTC 时间戳 - 用已有时区对象构造:
auto zt = zoned_time{locate_zone("UTC"), sys_seconds{...}};避免重复查找时区,性能更好
注意:local_seconds 不等于“当前机器本地时间”,它只是带 local_t 标签的秒数;真正获取当前本地时间要用 current_zone()->to_local(system_clock::now())。
从 zoned_time 提取时间、转换时区或格式化输出的实操要点
提取时间推荐用 .get_sys_time()(返回 sys_time,即 UTC)或 .get_local_time()(返回该时区下的 local_time),而不是直接 cast 或隐式转换——后者可能触发意外的时区回查。
- 跨时区转换:构造新
zoned_time即可,例如zoned_time{"America/New_York", zt.get_sys_time()} - 格式化输出:C++20 的
std::format支持{:%Y-%m-%d %H:%M:%S %Z},但%Z输出缩写(如 CST),%z输出偏移(+0800);若需全称(China Standard Time),得查zoned_time::get_info().abbrev或name() - 避免
zt.to_local(zt.get_sys_time())这种冗余调用——zt.get_local_time()更直接且安全
示例:
auto zt = zoned_time{"Asia/Shanghai", system_clock::now()};
std::cout
<h3>夏令时切换期的陷阱:同一个 local_time 可能对应两个 sys_time</h3>
<p>在 DST 开始或结束日(如美国 3 月第二个周日、11 月第一个周日),一个 <code>local_time</code> 可能映射到两个不同的 UTC 时间点(“重复小时”或“跳过小时”)。此时用 <code>zoned_time{zone, local_time}</code> 构造会抛出 <code>std::ambiguous_local_time</code> 或 <code>std::nonexistent_local_time</code> 异常。</p>
- 处理歧义:捕获
std::ambiguous_local_time后,用zone->get_info(local_tp).begin_offset和.end_offset查两个偏移,再按业务选早/晚版本 - 跳过小时(如 2:00–2:59 不存在):异常类型是
std::nonexistent_local_time,只能调整输入时间或拒绝解析 - 不要假设
zoned_time总能 round-trip:从local_time构造再取回local_time,可能因 DST 规则变化而不同
这类问题在金融、日志归档等场景容易被忽略——系统时间看似正常,但跨 DST 边界的时间计算结果可能错位一小时。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











