C++20的库新增日历与时区支持,提供year_month_day等类型表示日期、zoned_time处理时区转换,并自动处理闰年、夏令时等规则,无需手动计算。

C++20 的 库大幅扩展了日历与时区支持,不再是只有“纳秒差值”的纯时间点计算,而是真正能处理年月日、星期、时区转换、闰年、夏令时等现实问题。核心是引入了 日历类型(如 year_month_day)、时区支持(zoned_time、time_zone)和 UTC 与本地时间的明确分离。用法不难,但需转变思路:别再手动算天数,让标准库替你管日历规则。
日历类型:把时间点变成“可读日期”
C++20 新增了 `year`、`month`、`day`、`weekday`、`year_month_day` 等轻量类型,它们不带时区、不隐含时钟,只表示日历概念。
-
year_month_day ymd{2024y/3/15};构造一个日期;支持运算符如++ymd(跳到下一天)、ymd += months{1}(加一个月) -
ymd.ok()检查是否合法(例如2024y/2/30返回 false) - 可从
sys_days(系统时钟的“日期部分”)转换:auto ymd = floor→ 得到当天的(system_clock::now()); year_month_day - 反向转换也简单:
sys_days{ymd}得到该日零点的system_clock::time_point
时区支持:告别手写时区偏移
C++20 引入 的时区子库(需链接 -ltzdb 或启用编译器内置时区数据),关键类型有:
-
const time_zone* tz = locate_zone("Asia/Shanghai");获取时区对象(注意:不是所有平台默认提供完整数据库,Linux/macOS 通常支持,Windows 需额外配置或使用第三方 tzdb) -
zoned_time zt{tz, system_clock::now()};把系统时间绑定到指定时区,此时zt.get_local_time()就是北京时间 - 跨时区转换直接:
zoned_time{"America/New_York", zt.get_sys_time()}自动处理 DST 和历史规则 -
zt.get_info()返回time_zone::info,含当前 UTC 偏移、DST 偏移、是否在夏令时等细节
常见操作示例:今天是星期几?下个月同一天?UTC 转本地?
不用查表、不手动加减 8 小时,标准库全搞定:
立即学习“C++免费学习笔记(深入)”;
- 获取今天星期:
weekday{floor→ 返回(system_clock::now())} weekday{5}(即 Friday) - 下个月同日(自动处理 31 号不存在的情况):
year_month_day ymd{2024y/1/31}; auto next = ymd + months{1}; // 结果是 2024y/2/29 - UTC 时间转本地(假设系统时区为 CST):
zoned_time{"UTC", tp} -> zoned_time{current_zone(), tp},其中current_zone()是当前系统时区 -
格式化输出(配合
):std::format("{:%Y-%m-%d %H:%M}", zt);输出带时区的字符串
注意事项和兼容性提醒
这些功能虽强大,但实际使用要注意几点:
- Clang 13+ / GCC 12+ / MSVC 19.30+ 才完整支持;GCC 12 默认未启用时区数据库,需编译时加
-DENABLE_STD_TIMEZONE_DB=ON并确保安装 tzdata -
locate_zone("XXX")返回空指针表示时区未找到,务必检查;推荐用current_zone()或硬编码已知时区名 - 日历类型之间不能隐式转换,比如
year_month_day和sys_days必须显式构造或转换 - 所有日历运算都基于 ISO 日历(公历),不支持儒略历或其他历法
基本上就这些。C++20 的 chrono 日历与时区不是“锦上添花”,而是把过去靠 Boost.DateTime 或自定义代码实现的功能,变成了标准、安全、可移植的原生能力。用对了,日期逻辑会更清晰,出错率更低。










