是否仍需遵循UTC时间准则?C++20 <chrono>时区处理探讨
UTC时间准则在C++20 中的适用性与时区操作
这个后端存储、日志及内部逻辑统一用UTC,仅在人机交互时转换时区的黄金准则,在C++20及后续版本的<chrono>库中依然完全适用——这是软件工程的通用实践,和语言工具无关,而<chrono>只是给我们提供了更精准、更便捷的工具来落地这一准则。
为什么准则依然成立
UTC是无歧义的时间基准,能彻底避免夏令时切换、时区变更带来的时间混乱,后端用UTC存储可以保证数据的一致性,内部逻辑基于UTC计算也能简化跨时区场景的复杂度。<chrono>的设计完全贴合这一思路,核心类型都围绕UTC和时区转换做了优化。
C++20 的时区支持与实用示例
C++20扩展了<chrono>,新增了utc_clock、zoned_time、time_zone等类型,让时区转换和时间计算更直观,下面是几个实用场景的代码示例:
1. 存储与输出UTC时间(后端/日志场景)
直接用utc_clock获取当前UTC时间,存储为utc_time类型,输出时保持UTC格式:
#include <chrono> #include <iostream> #include <format> int main() { // 获取当前UTC时间 auto now_utc = std::chrono::utc_clock::now(); // 存储为UTC时间类型(适合后端持久化) std::chrono::sys_seconds utc_storage = std::chrono::floor<std::chrono::seconds>(now_utc); // 日志输出UTC时间 std::cout << std::format("UTC时间: {:%Y-%m-%d %H:%M:%S} UTC\n", utc_storage); return 0; }
2. 将UTC时间转换为本地时区显示(人机交互场景)
用zoned_time可以轻松把UTC时间转换为指定时区的本地时间,比如转换为中国标准时间:
#include <chrono> #include <iostream> #include <format> int main() { // 模拟后端存储的UTC时间 std::chrono::sys_seconds utc_time = std::chrono::sys_days{2024y/6/15} + 10h + 30min; // 转换为中国标准时间(Asia/Shanghai) std::chrono::zoned_time china_time{"Asia/Shanghai", utc_time}; // 转换为本地时区(系统默认时区) std::chrono::zoned_time local_time{std::chrono::current_zone(), utc_time}; std::cout << std::format("UTC时间: {:%Y-%m-%d %H:%M:%S} UTC\n", utc_time); std::cout << std::format("中国标准时间: {:%Y-%m-%d %H:%M:%S}\n", china_time); std::cout << std::format("本地时间: {:%Y-%m-%d %H:%M:%S}\n", local_time); return 0; }
3. 将用户输入的本地时间转换为UTC存储
当用户输入本地时间时,先解析为对应时区的时间,再转换为UTC存储:
#include <chrono> #include <iostream> #include <format> #include <string> int main() { // 用户输入的本地时间字符串(假设为中国标准时间) std::string input_time = "2024-06-15 18:30:00"; // 解析为中国时区的本地时间 std::chrono::local_seconds local_time; std::from_chars(input_time.data(), input_time.data() + input_time.size(), local_time, "%Y-%m-%d %H:%M:%S"); // 转换为UTC时间存储 std::chrono::zoned_time china_time{"Asia/Shanghai", local_time}; std::chrono::sys_seconds utc_storage = std::chrono::floor<std::chrono::seconds>(china_time.get_sys_time()); std::cout << std::format("用户输入的本地时间: {:%Y-%m-%d %H:%M:%S}\n", local_time); std::cout << std::format("转换后的UTC时间: {:%Y-%m-%d %H:%M:%S} UTC\n", utc_storage); return 0; }
4. 跨时区时间计算(统一用UTC基准)
如果需要计算不同时区事件的时间差,先统一转换为UTC再计算,避免时区差异带来的错误:
#include <chrono> #include <iostream> #include <format> int main() { // 纽约事件时间(America/New_York) std::chrono::zoned_time ny_time{"America/New_York", std::chrono::local_days{2024y/6/15} + 9h}; // 北京事件时间(Asia/Shanghai) std::chrono::zoned_time bj_time{"Asia/Shanghai", std::chrono::local_days{2024y/6/15} + 21h}; // 转换为UTC时间计算差值 auto utc_ny = ny_time.get_sys_time(); auto utc_bj = bj_time.get_sys_time(); auto diff = utc_bj - utc_ny; std::cout << std::format("纽约事件UTC时间: {:%Y-%m-%d %H:%M:%S} UTC\n", utc_ny); std::cout << std::format("北京事件UTC时间: {:%Y-%m-%d %H:%M:%S} UTC\n", utc_bj); std::cout << std::format("时间差: {}小时\n", std::chrono::duration_cast<std::chrono::hours>(diff).count()); return 0; }
内容的提问来源于stack exchange,提问作者Howard Hinnant
相关产品推荐
相关产品推荐

