0

0

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

尼克

尼克

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

|

151人浏览过

|

来源于php中文网

原创

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() 返回对应本地时间。

雾象
雾象

WaytoAGI推出的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() 提高可移植性

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

887

2023.07.31

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

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

462

2024.06.27

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

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

562

2023.09.20

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

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

760

2023.08.03

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

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

221

2023.09.04

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

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

1567

2023.10.24

字符串介绍
字符串介绍

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

649

2023.11.24

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

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

1228

2024.03.22

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

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

精品课程

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

共48课时 | 10.5万人学习

Git 教程
Git 教程

共21课时 | 4.2万人学习

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

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