C++20 chrono库中的hh_mm_ss时间处理组件详解

发布时间:2026/9/14 21:02:27

C++20 chrono库中的hh_mm_ss时间处理组件详解 1. 理解std::chrono的hh_mm_ss组件C标准库中的chrono头文件提供了强大的时间处理能力而hh_mm_ss是C20引入的一个专门用于拆分时间的工具类。这个类的主要功能是将一个时间段duration拆解为小时、分钟、秒和亚秒部分让我们能够方便地获取时间的各个组成部分。1.1 hh_mm_ss的基本结构hh_mm_ss类模板的定义如下templateclass Duration class hh_mm_ss;它接受一个表示时间长度的Duration类型作为模板参数。这个设计使得hh_mm_ss可以处理各种精度的时间段从纳秒到小时甚至更长的时间跨度。这个类内部存储了四个主要成员小时部分hours分钟部分minutes秒部分seconds亚秒部分subseconds每个部分都是独立的duration类型这使得我们可以非常方便地获取和操作时间的各个组成部分。1.2 为什么需要hh_mm_ss在C20之前如果我们想要将一个时间段拆分为小时、分钟和秒需要手动进行计算auto total_seconds duration_castseconds(some_duration); auto h duration_casthours(total_seconds); auto m duration_castminutes(total_seconds % hours(1)); auto s total_seconds % minutes(1);这种方法不仅繁琐而且容易出错。hh_mm_ss的出现简化了这一过程提供了更直观、更安全的方式来处理时间拆分。2. hh_mm_ss的使用方法2.1 创建hh_mm_ss对象创建一个hh_mm_ss对象非常简单只需要将一个duration对象传递给它using namespace std::chrono; auto duration 3h 42min 15s 500ms; // 3小时42分15秒500毫秒 hh_mm_ss hms(duration);这里我们创建了一个表示3小时42分15秒500毫秒的duration对象然后将其转换为hh_mm_ss格式。2.2 获取时间各部分创建hh_mm_ss对象后我们可以轻松获取时间的各个组成部分std::cout Hours: hms.hours().count() \n; std::cout Minutes: hms.minutes().count() \n; std::cout Seconds: hms.seconds().count() \n; std::cout Subseconds: hms.subseconds().count() \n;对于上面的例子输出将是Hours: 3 Minutes: 42 Seconds: 15 Subseconds: 5002.3 处理负时间hh_mm_ss也能正确处理负的时间段auto negative_duration - (2h 30min); hh_mm_ss neg_hms(negative_duration); std::cout neg_hms.hours().count() : neg_hms.minutes().count() : neg_hms.seconds().count() \n;输出将是-2:-30:0注意所有组成部分都会保持相同的符号这确保了时间表示的完整性。3. hh_mm_ss的高级用法3.1 自定义精度处理hh_mm_ss可以处理各种精度的duration。例如我们可以处理纳秒级的时间auto precise_time 1h 23min 45s 678912345ns; hh_mm_ss precise_hms(precise_time); std::cout Nanoseconds: precise_hms.subseconds().count() \n;输出将是Nanoseconds: 6789123453.2 与时间点结合使用hh_mm_ss通常与time_point一起使用来计算从午夜开始的经过时间auto now system_clock::now(); auto today floordays(now); // 获取今天的0点 auto since_midnight now - today; // 计算从午夜开始的经过时间 hh_mm_ss hms(since_midnight); std::cout Current time: hms.hours().count() : hms.minutes().count() : hms.seconds().count() \n;这段代码会输出当前时间的小时、分钟和秒部分。3.3 格式化输出虽然hh_mm_ss本身不提供格式化功能但我们可以很容易地用它来创建格式化的时间字符串std::string format_time(const hh_mm_ssmilliseconds hms) { std::ostringstream oss; oss std::setfill(0) std::setw(2) hms.hours().count() : std::setw(2) hms.minutes().count() : std::setw(2) hms.seconds().count() . std::setw(3) hms.subseconds().count(); return oss.str(); }这个函数会输出类似03:42:15.500的格式化字符串。4. 实际应用案例4.1 计时器实现hh_mm_ss非常适合用于实现计时器功能。下面是一个简单的计时器示例class Timer { steady_clock::time_point start; public: Timer() : start(steady_clock::now()) {} void reset() { start steady_clock::now(); } auto elapsed() const { auto dur steady_clock::now() - start; return hh_mm_ss{dur}; } }; // 使用示例 Timer t; // ...执行一些操作... auto elapsed t.elapsed(); std::cout Elapsed time: elapsed.hours().count() h elapsed.minutes().count() m elapsed.seconds().count() s\n;4.2 处理用户输入时间当需要处理用户输入的时间字符串时hh_mm_ss可以派上用场std::optionalmilliseconds parse_time(const std::string input) { std::istringstream iss(input); char colon1, colon2, dot; int h, m, s, ms 0; if (iss h colon1 m colon2 s) { if (colon1 : colon2 : (iss dot ms || !iss.eof())) { if (dot . iss) { auto dur hours{h} minutes{m} seconds{s} milliseconds{ms}; return duration_castmilliseconds(dur); } } } return std::nullopt; } // 使用示例 if (auto dur parse_time(12:34:56.789)) { hh_mm_ss hms{*dur}; // 使用hms对象 }4.3 多媒体时间处理在多媒体应用中经常需要处理精确的时间戳struct MediaTimestamp { hh_mm_ssnanoseconds time; int frame_number; std::string to_string() const { std::ostringstream oss; oss time.hours().count() : time.minutes().count() : time.seconds().count() . std::setw(9) std::setfill(0) time.subseconds().count() frame: frame_number; return oss.str(); } };5. 性能考虑与最佳实践5.1 性能特点hh_mm_ss的设计考虑到了性能因素。它的构造函数会立即执行所有必要的计算将原始duration分解为各个组成部分。这意味着构造对象时有一次性的计算开销后续访问各部分时几乎没有额外开销对象本身占用固定大小的内存对于大多数应用场景hh_mm_ss的性能开销是可以忽略不计的。5.2 何时使用hh_mm_sshh_mm_ss最适合以下场景需要频繁访问时间的各个组成部分小时、分钟、秒等需要以人类可读格式显示时间需要处理不同精度的时间表示需要确保时间各部分的一致性特别是处理负时间时对于只需要简单duration计算而不需要拆分的场景直接使用duration可能更高效。5.3 常见陷阱与解决方案陷阱1精度丢失auto dur 1h 30min 45s 500ms; hh_mm_ssseconds hms(dur); // 毫秒部分会丢失解决方案确保模板参数精度足够高hh_mm_ssmilliseconds hms(dur); // 正确保留毫秒陷阱224小时以上的时间hh_mm_ss不会自动将小时部分模24如果需要时钟时间总是小于24小时需要先处理auto dur 25h 30min; auto clock_time dur % 24h; hh_mm_ss hms(clock_time); // 显示1:30:00而不是25:30:00陷阱3与C风格时间函数的混用当需要与ctime函数交互时注意转换std::time_t t std::time(nullptr); auto dur system_clock::from_time_t(t) - floordays(system_clock::now()); hh_mm_ss hms(dur);6. 与其他时间工具的对比6.1 与传统C时间函数对比相比于ctime中的tm结构体和相关函数hh_mm_ss有以下优势类型安全各部分都是强类型的duration更直观的接口直接通过成员函数访问各部分更好的精度支持可以处理纳秒级精度更一致的处理方式特别是对于负时间的处理6.2 与第三方库的对比许多第三方时间库如Boost.DateTime也提供类似功能但hh_mm_ss的优势在于标准库的一部分无需额外依赖与C其他时间工具无缝集成更现代的C设计模板、constexpr支持等6.3 与简单duration计算的对比对于简单的时间计算直接使用duration可能更合适。hh_mm_ss更适合需要频繁访问时间各部分或需要格式化输出的场景。7. C20中的其他相关特性hh_mm_ss通常与C20的其他时间工具一起使用7.1 日历和时区支持C20引入了完整的日历和时区支持可以与hh_mm_ss结合使用auto zt zoned_time{current_zone(), system_clock::now()}; auto tod hh_mm_ss{zt.get_local_time() - floordays(zt.get_local_time())};7.2 格式化和解析C20还引入了std::format对chrono类型的支持auto dur 3h 42min 15s 500ms; hh_mm_ss hms(dur); std::string s std::format({:%H:%M:%S}, hms); // 03:42:157.3 12小时制支持虽然hh_mm_ss本身不直接支持12小时制但可以很容易地转换auto format_12h(const hh_mm_ssmilliseconds hms) { auto h hms.hours().count(); bool pm h 12; h h % 12; h h ? h : 12; // 0点显示为12 std::ostringstream oss; oss h : std::setw(2) std::setfill(0) hms.minutes().count() : std::setw(2) hms.seconds().count() (pm ? PM : AM); return oss.str(); }8. 跨平台注意事项虽然hh_mm_ss是C20标准的一部分但在实际使用中仍需注意8.1 编译器支持确保你的编译器完全支持C20的chrono库。截至2023年GCC 10 完全支持Clang 12 完全支持MSVC 19.29 基本支持8.2 不同平台的精度限制虽然C标准定义了纳秒精度但不同平台的实际精度可能受限于系统时钟的精度硬件支持操作系统限制可以使用steady_clock::period来检查实际精度。8.3 与系统API的交互当需要与平台特定时间API交互时通常需要转换// Windows FILETIME转换示例 FILETIME ft; GetSystemTimeAsFileTime(ft); auto dur file_clock::from_sys(file_clock::time_point{ duration_castfile_clock::duration(nanoseconds{ ((static_castuint64_t(ft.dwHighDateTime) 32) | ft.dwLowDateTime) * 100 }) }); hh_mm_ss hms{dur - floordays(dur)};9. 测试与调试技巧9.1 单元测试策略测试hh_mm_ss相关代码时应考虑以下测试用例常规时间正数零值负时间24小时以上的时间边界情况如23:59:59.999...不同精度的时间9.2 调试输出为了方便调试可以为hh_mm_ss实现自定义的调试输出templatetypename Duration std::ostream operator(std::ostream os, const hh_mm_ssDuration hms) { os hms.hours().count() h hms.minutes().count() m hms.seconds().count() s; if constexpr (!std::is_same_vtypename decltype(hms.subseconds())::period, std::ratio1) { os hms.subseconds().count() subseconds; } return os; }9.3 常见错误排查精度不匹配确保hh_mm_ss的模板参数精度足够包含原始duration的精度。符号不一致当处理负时间时确保所有计算都考虑了符号。整数溢出对于非常大的duration计算时可能发生溢出。考虑使用更大范围的整数类型。格式化问题当格式化输出时注意前导零和字段宽度的设置。10. 扩展与自定义10.1 自定义duration类型hh_mm_ss可以用于自定义的duration类型using frames durationint32_t, std::ratio1, 60; // 60fps的视频帧 auto video_dur frames{12345}; // 205秒45帧 hh_mm_ss video_hms(video_dur);10.2 扩展功能可以基于hh_mm_ss构建更高级的时间处理工具class ExtendedTime : public hh_mm_ssmilliseconds { std::string timezone; public: ExtendedTime(system_clock::duration d, std::string tz UTC) : hh_mm_ss(d), timezone(std::move(tz)) {} std::string to_string() const { return std::format({} {:%H:%M:%S}, timezone, *this); } };10.3 与其他库集成hh_mm_ss可以方便地与序列化库如JSON集成void to_json(nlohmann::json j, const hh_mm_ssmilliseconds hms) { j { {hours, hms.hours().count()}, {minutes, hms.minutes().count()}, {seconds, hms.seconds().count()}, {milliseconds, hms.subseconds().count()} }; }在实际项目中我发现hh_mm_ss特别适合处理需要频繁显示或操作时间各部分的场景。相比手动计算小时、分钟和秒使用hh_mm_ss不仅代码更简洁而且更不容易出错。特别是在处理多媒体时间戳、性能分析和用户界面显示等场景下它能显著提高代码的可读性和可维护性。一个实用的技巧是当需要频繁格式化相同的时间格式时可以创建一个轻量级的包装器来缓存格式化结果避免重复计算。另外在处理用户界面时考虑将hh_mm_ss对象与观察者模式结合在时间变化时自动更新显示。
延伸阅读

更多相关文章

2026/9/12 14:16:57

音乐格式解锁神器:让你的加密音乐文件重获自由

音乐格式解锁神器:让你的加密音乐文件重获自由 【免费下载链接】unlock-music-electron Unlock Music Project - Electron Edition 在Electron构建的桌面应用中解锁各种加密的音乐文件 项目地址: https://gitcode.com/gh_mirrors/un/unlock-music-electron 你…

2026/9/14 21:00:31

Matlab/Simulink柴油发电机微电网仿真建模实践

1. 柴油发电机仿真系统概述柴油发电机作为微电网系统中的关键备用电源,其动态特性直接影响整个系统的稳定性。在Matlab/Simulink环境下搭建柴油发电机仿真模型,能够有效评估其在并网/孤岛模式下的运行性能。典型的微电网架构包含光伏阵列(PV&…

2026/9/14 21:00:31

基于Django与微信小程序的智能制造业ERP系统开发实践

1. 项目背景与核心价值制造业ERP系统作为企业资源管理的核心平台,其移动化转型已成为行业刚需。这个基于Django框架的智能制造业ERP解决方案,通过微信小程序实现移动端接入,解决了传统ERP系统在以下场景的痛点:车间主任需要实时审…

2026/9/14 21:00:31

海尔Horizon冰箱技术解析与市场战略

1. 项目概述:海尔Horizon冰箱英国首发的战略意义2023年海尔在英国市场推出的Horizon系列冰箱,是其全球化战略中的关键落子。作为定位高端的旗舰产品线,Horizon的命名本身就蕴含着三重战略意图:首先"地平线"象征技术边界…

2026/9/14 21:00:31

Vue3双向绑定组件开发:多变量与修饰符实战

1. Vue3双向绑定组件的核心需求解析双向绑定是Vue框架最标志性的特性之一,在Vue3中通过组合式API得到了进一步增强。当我们谈到"支持多绑定变量和修饰符的双向绑定组件"时,实际上是在解决以下三个核心问题:多变量同步:传…

2026/9/14 21:00:31

IntelliJ IDEA社区版:开源轻量IDE的调优与ARM边缘设备实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/14 20:55:30

Vue3双向绑定进阶:defineModel多变量与修饰符实战

1. Vue3双向绑定组件的核心价值与挑战双向绑定一直是Vue框架最标志性的特性之一。在Vue3中,随着Composition API的成熟和defineModel宏的引入,双向绑定的实现方式变得更加优雅和强大。但在实际开发中,我们经常会遇到需要处理多个绑定变量和自…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码