0

0

如何使用c++20的std::chrono处理本地时间和UTC的转换? (时区库实践)

尼克

尼克

发布时间:2026-01-17 15:55:22

|

151人浏览过

|

来源于php中文网

原创

c++kquote>std::chrono::zoned_time 是 C++20 中唯一可靠处理时区转换的类型,它绑定时区与 UTC 时间点,自动查 IANA 数据库处理 DST 和历史变更,不可用 local_time 算术或手动加减偏移。

如何使用c++20的std::chrono处理本地时间和utc的转换? (时区库实践)

std::chrono::zoned_time 是本地时间与 UTC 转换的核心

在 C++20 中,std::chrono::zoned_time 是唯一能可靠处理时区转换的类型。它不是“时间点”,而是“带时区的时间表示”——绑定一个 std::chrono::time_zone 和一个 std::chrono::sys_time(即系统时间,等价于 UTC)。直接用 std::chrono::system_clock::now() 得到的是 UTC,想转本地时间,必须通过时区对象构造 zoned_time

常见错误是试图对 std::chrono::local_time 做算术或比较——它没有时区信息,无法跨 DST 边界安全使用;也不该手动加减固定偏移(如 +8h),因为夏令时和历史时区变更会让结果错乱。

  • zoned_time 构造时会自动查表(IANA 时区数据库),处理 DST 切换、历史规则变更
  • Windows 上需确保已启用 _ENABLE_EXTENDED_ALIGNED_STORAGE(MSVC 默认开启),且运行时有 IANA 时区数据(C++20 实现通常内置或依赖系统)
  • Linux/macOS 一般无额外配置;但若用 libc++,需确认编译时链接了 -ltzdb(Clang 15+ 默认启用)

获取当前本地时间并转为 UTC(正向转换)

zoned_time 包装当前系统时间,并指定本地时区名(如 "Asia/Shanghai"),再调用 .get_sys_time() 即得对应 UTC 时间点。

auto now_local = std::chrono::zoned_time{"Asia/Shanghai", std::chrono::system_clock::now()};
auto utc_time = now_local.get_sys_time(); // std::chrono::sys_time,即 UTC
// 输出示例:2024-06-15 07:23:45.123 UTC
std::cout << std::format("{:%Y-%m-%d %H:%M:%S}", utc_time) << " UTC\n";

注意:std::chrono::current_zone() 可读取系统默认时区,但返回的是 const time_zone*,不能直接用于 zoned_time 构造(因构造函数要求字符串或 time_zone const* 指针,而 current_zone() 的指针是合法的):

立即学习C++免费学习笔记(深入)”;

auto tz = std::chrono::current_zone();
auto local_now = std::chrono::zoned_time{tz, std::chrono::system_clock::now()}; // ✅ 正确
auto utc = local_now.get_sys_time();

从 UTC 时间点转为指定本地时间(反向转换)

给定一个 std::chrono::sys_time(即 UTC),构造 zoned_time 时传入目标时区名即可。此时 .get_local_time() 返回对应本地时间。

医真AI+开放平台
医真AI+开放平台

医真AI+ 医学AI开放平台

下载
auto utc_point = std::chrono::sys_days{2024y/June/15} + 10h + 30min;
auto shanghai_time = std::chrono::zoned_time{"Asia/Shanghai", utc_point};
auto beijing_local = shanghai_time.get_local_time(); // local_time 类型

// 格式化输出(需用 to_stream 或 std::format)
std::cout << std::format("{:%Y-%m-%d %H:%M}", beijing_local) << " CST\n"; // 2024-06-15 18:30 CST

关键点:

  • sys_time 是 UTC,不依赖任何时区;local_time 是纯日历时间,无时区语义;只有 zoned_time 才承载“某地某时刻”的完整含义
  • 格式化 local_time 时,std::format 支持 {:%H:%M} 等,但不会自动补零(需用 {:%H:%M:%S} 或显式 {:02}
  • 若时区名拼写错误(如 "China/Beijing"),zoned_time 构造会抛 std::runtime_error,务必捕获

跨时区转换与 DST 边界行为

真正考验时区库能力的是 DST 切换前后的时间转换。例如美国东部时间 2024 年 11 月 3 日 2:00 AM 会回拨一小时,出现两个 1:30 AM;而 3 月 10 日 2:00 AM 会跳过,不存在 2:30 AM。

C++20 的 zoned_time 在构造时会根据 IANA 数据库自动选择正确偏移(get_info().offset),并报告是否为 DST(get_info().is_dst):

auto tz = std::chrono::locate_zone("America/New_York");
auto nov3_2024 = std::chrono::sys_days{2024y/November/3} + 5h; // UTC 5AM → EDT? EST?
auto zt = std::chrono::zoned_time{tz, nov3_2024};
auto info = zt.get_info();

std::cout << "Offset: " << info.offset.count() << "s\n"; // -18000 (EST)
std::cout << "Is DST: " << info.is_dst << "\n"; // false
std::cout << "Abbrev: " << info.abbrev << "\n"; // "EST"

容易被忽略的细节:

  • 同一个 local_time 值(如 1:30 AM)在 DST 边界可能对应两个不同 sys_timezoned_time 构造时默认选较早的那个(可通过 choose::earliest/choose::latest 显式控制)
  • std::chrono::zoned_time 不可赋值,只能移动;其内部缓存时区规则,频繁构造不同区域的实例性能尚可,但不应在 tight loop 中反复 locate_zone
  • Windows 上若未设置时区数据库路径(TZDIR 环境变量),locate_zone 可能失败;建议优先用硬编码时区名而非 current_zone() 提高可移植性

相关专题

更多
format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

618

2023.07.31

python中的format是什么意思
python中的format是什么意思

python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

430

2024.06.27

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

524

2023.09.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

257

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1465

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

619

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

550

2024.03.22

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

27

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.3万人学习

Git 教程
Git 教程

共21课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号