
C++20 的 确实带来了日历和时区的原生支持,不再是靠第三方库(如 Howard Hinnant 的 date 库)打补丁了——它直接把 date 库的核心逻辑“收编”进了标准。用起来清晰、类型安全、无运行时依赖,但需要理解几个新概念才能真正上手。
核心新增类型:年月日 + 时分秒 = civil time
C++20 引入了 std::chrono::year、std::chrono::month、std::chrono::day、std::chrono::year_month_day 等“日历类型”,它们不带时区、不带偏移,纯粹表示民用时间(civil time)。
例如:
-
std::chrono::year_month_day{2024y/3/15}表示 2024 年 3 月 15 日(注意2024y是字面量后缀,需包含) -
auto ymd = sys_days{2024y/3/15};把日期转成系统时间点(即自 1970-01-01 的天数) -
ymd.time_since_epoch()返回days类型,可转为整数天数
把日期转成精确时间点:用 sys_days 和 sys_time
std::chrono::sys_days 是 system_clock::time_point 的“天粒度”别名,代表 UTC 时间轴上的某一天零点(00:00:00 UTC)。
立即学习“C++免费学习笔记(深入)”;
想得到带具体时刻的时间点?组合使用:
-
auto tp = sys_days{2024y/3/15} + 14h + 30min;→ 得到 2024-03-15 14:30:00 UTC -
auto tp_local = clock_cast→ 转成本地时区(非 UTC,但仍是本地系统时区,不含 IANA 时区名)(tp);
⚠️ 注意:local_t 不是某个具体时区(比如 “Asia/Shanghai”),只是当前系统的本地时区(由 std::chrono::current_zone() 返回的时区对象决定)。
真正用上 IANA 时区(如 “America/New_York”、“Asia/Shanghai”)
C++20 支持完整的 IANA 时区数据库,但需满足两个前提:
- 编译器/标准库实现必须提供时区数据(libstdc++ ≥ 13、libc++ ≥ 16、MSVC 2022 17.5+ 已支持)
- 运行环境需有可用的时区数据库(Linux/macOS 通常自带;Windows 需启用
_ENABLE_EXTENDED_ALIGNED_STORAGE或使用 ICU)
典型用法:
-
const auto tz = std::chrono::locate_zone("Asia/Shanghai");→ 获取时区指针 -
auto tp_utc = tz->to_sys(2024y/3/15 / 14h + 30min);→ 把本地时间(东八区)转为 UTC 时间点 -
auto tp_local = tz->to_local(tp_utc);→ 反向转换(含夏令时自动处理) -
tz->get_info(tp_utc).offset;→ 查该时刻的 UTC 偏移(如 +0800)
格式化与解析: 配合 std::chrono
C++20 的 直接支持日历和时区类型:
-
std::format("{:%Y-%m-%d %H:%M %Z}", tp_utc);→ 输出 "2024-03-15 06:30 UTC" -
std::format("{:%F %T %Z}", tp_local_in_shanghai);→ 输出 "2024-03-15 14:30:00 CST" - 解析需用
std::chrono::parse(C++20 提供): -
std::istringstream s{"2024-03-15 14:30"};std::chrono::sys_seconds tp;s >> std::chrono::parse("%F %T", tp);
⚠️ 注意:parse 默认按 UTC 解析;若要按特定时区解析,需先转成对应时区时间再调用 to_sys。
不复杂但容易忽略:所有日历操作默认不检查有效性(如 2024y/2/30),但可通过 .ok() 成员函数验证,例如 (2024y/2/30).ok() 返回 false。











