c++11 chrono全面解析(最高可达纳秒级别的精度)

本文详细介绍了C++11 chrono库的基本概念,包括时间精度、时间段、时间点及时钟等内容。通过实例展示了如何使用chrono进行时间的计算与转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

chrono是c++ 11中的时间库,提供计时,时钟等功能。

学习chrono,关键是理解里面时间段(Durations)、时间点(Time points)的概念。

1.精度:

时钟节拍(时间精度):

template <intmax_t N, intmax_t D = 1> class ratio;
其中N表示分子,D表示分母默认用秒表示的时间单位

N对应于其成员num,D对应于其成员den

常用的单位:

ratio<60, 1>                    minute

ratio<1, 1>                      second

ratio<1, 1000>               microsecond

...

ratio主要是是为后面将要讲解的时间段,时间点等提供精度(单位)

  1. #include<iostream>   
  2. #include<chrono>   
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     cout << "millisecond : ";  
  7.     cout << std::chrono::milliseconds::period::num << "/" << std::chrono::milliseconds::period::den << "s" <<endl;  
  8.     system("pause");  
  9.     return 0;  
  10. }  
#include<iostream>
#include<chrono>
using namespace std;
int main()
{
	cout << "millisecond : ";
	cout << std::chrono::milliseconds::period::num << "/" << std::chrono::milliseconds::period::den << "s" <<endl;
	system("pause");
	return 0;
}

2.时间段:

template <class Rep, class Period = ratio<1> >
class duration;
std::chrono::duration 表示一段时间,比如两个小时,12.88秒,半个时辰,一炷香的时间等等

Rep表示一种数值类型,用来表示Period的数量,比如int float double。
Period是ratio类型,用来表示上面所说的单位精度,比如second milisecond。
chrono中宏定义了许多特例化了的duration:
就是常见的hours,miniutes,seconds,milliseconds等,使用std::chrono::milliseconds直接使用。
(1)构造函数很简单
  1. (1)duration() = default;    //默认构造   
  2. (2)duration (const duration& dtn);        //(2)(3)拷贝构造   
  3. (3)template<class Rep2, class Period2>  
  4.    constexpr duration (const duration<Rep2,Period2>& dtn);  
  5. (4)template<class Rep2>      //传递一个某类型(int等)的数值,构造一个时间段      
  6.    constexpr explicit duration (const Rep2& n);  
(1)duration() = default;    //默认构造
(2)duration (const duration& dtn);        //(2)(3)拷贝构造
(3)template<class Rep2, class Period2>
   constexpr duration (const duration<Rep2,Period2>& dtn);
(4)template<class Rep2>      //传递一个某类型(int等)的数值,构造一个时间段   
   constexpr explicit duration (const Rep2& n);

(2)成员函数count()返回单位时间的数量。

  1. #include <iostream>   
  2. #include <chrono>   
  3. int main()  
  4. {  
  5.     std::chrono::milliseconds mscond(1000); // 1 second   
  6.     std::cout << mscond.count() << " milliseconds.\n";  
  7.   
  8.     std::cout << mscond.count() * std::chrono::milliseconds::period::num / std::chrono::milliseconds::period::den;  
  9.     std::cout << " seconds.\n";  
  10.     system("pause");  
  11.     return 0;  
  12. }  
#include <iostream>
#include <chrono>
int main()
{
	std::chrono::milliseconds mscond(1000); // 1 second
	std::cout << mscond.count() << " milliseconds.\n";

	std::cout << mscond.count() * std::chrono::milliseconds::period::num / std::chrono::milliseconds::period::den;
	std::cout << " seconds.\n";
	system("pause");
	return 0;
}

(2)当不要求截断值的情况下(时转换成秒是没问题,但是秒转换成时就不行)时间段的转换是隐式
的。显示转换可以由 std::chrono::duration_cast<> 来完成。
比如 std::chrono::milliseconds ms(54802);

std::chrono::seconds s=std::chrono::duration_cast<std::chrono::seconds>(ms);

这里的结果就是截断的,而不是进行了舍入,所以s最后的值将为54。

3.时间点:

template <class Clock, class Duration = typename Clock::duration>
  class time_point;

std::chrono::time_point 表示一个具体时间,如上个世纪80年代、今天下午3点、火车出发时间等,只要它能用计算机时钟表示。

第一个模板参数Clock用来指定所要使用的时钟(标准库中有三种时钟,system_clock,steady_clock和high_resolution_clock。见4时钟详解),第二个模板函数参数用来表示时间的计量单位(特化的std::chrono::duration<> )

时间点都有一个时间戳,即时间原点。chrono库中采用的是Unix的时间戳1970年1月1日 00:00。所以time_point也就是距离时间戳(epoch)的时间长度(duration)。

(1)构造函数:

(1)
time_point();           //默认构造函数,时间戳作为其值
(2)
template <class Duration2>
time_point (const time_point<clock,Duration2>& tp);  //拷贝构造函数
(3)
explicit time_point (const duration& dtn);           //使用duration构造,就是距离时间戳的时间长度
(2)时间点有个重要的函数:duration time_since_epoch()  (用于获取当前时间点距离时间戳的时间长度)

即经常用来得到当前时间点到1970年1月1日00:00的时间距离、该函数返回的duration的精度和构造time_point的时钟(Clock)有关(见4时钟详解)。

  1. #include <iostream>   
  2. #include <chrono>   
  3. #include <ctime>   
  4. using namespace std;  
  5. int main()  
  6. {  
  7.     //距离时间戳2两秒   
  8.     chrono::time_point<chrono::system_clock, chrono::seconds> tp(chrono::seconds(2));  
  9.     cout << "to epoch : " <<tp.time_since_epoch().count() << "s" <<endl;  
  10.     //转化为ctime,打印输出时间点   
  11.     time_t tt = chrono::system_clock::to_time_t(tp);  
  12.     char a[50];  
  13.     ctime_s(a, sizeof(a), &tt);  
  14.     cout << a;  
  15.     system("pause");  
  16.     return 0;  
  17. }  
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
int main()
{
	//距离时间戳2两秒
	chrono::time_point<chrono::system_clock, chrono::seconds> tp(chrono::seconds(2));
	cout << "to epoch : " <<tp.time_since_epoch().count() << "s" <<endl;
	//转化为ctime,打印输出时间点
	time_t tt = chrono::system_clock::to_time_t(tp);
	char a[50];
	ctime_s(a, sizeof(a), &tt);
	cout << a;
	system("pause");
	return 0;
}

可以看出,时间戳就是使用的Unix的时间戳。

4.时钟:(代表当前系统的时间)

chrono中有三种时钟:system_clock,steady_clock和high_resolution_clock。每一个clock类中都有确定的time_point, duration, Rep, Period类型。

system_clock是不稳定的。因为时钟是可调的,即这种是完全自动适应本地账户的调节。这种调节可能造成的是,首次调用now()返回的时间要早于上次调用now()所返回的时间,这就违反了节拍频率的均匀分布。稳定闹钟对于超时的计算很重要,所以C++标准库提供一个稳定时钟 std::chrono::steady_clock。std::chrono::high_resolution_clock 是标准库中提供的具有最小节拍周期(因此具有最高的精度的时钟)。

上文所说time_since_epoch(),以及将要介绍的now()函数的返回值都依赖于时钟的精度,测试时钟的精度的一种方法就是:

  1. <SPAN style="FONT-SIZE: 18px">#include <iostream>  
  2. #include <chrono>   
  3. using namespace std;  
  4. int main()  
  5. {  
  6.     cout << "system clock          : ";  
  7.     cout << chrono::system_clock::period::num << "/" << chrono::system_clock::period::den << "s" << endl;  
  8.     cout << "steady clock          : ";  
  9.     cout << chrono::steady_clock::period::num << "/" << chrono::steady_clock::period::den << "s" << endl;  
  10.     cout << "high resolution clock : ";  
  11.     cout << chrono::high_resolution_clock::period::num << "/" << chrono::high_resolution_clock::period::den << "s" << endl;  
  12.     system("pause");  
  13.     return 0;  
  14. }</SPAN>  
#include <iostream>
#include <chrono>
using namespace std;
int main()
{
	cout << "system clock          : ";
	cout << chrono::system_clock::period::num << "/" << chrono::system_clock::period::den << "s" << endl;
	cout << "steady clock          : ";
	cout << chrono::steady_clock::period::num << "/" << chrono::steady_clock::period::den << "s" << endl;
	cout << "high resolution clock : ";
	cout << chrono::high_resolution_clock::period::num << "/" << chrono::high_resolution_clock::period::den << "s" << endl;
	system("pause");
	return 0;
}

windows系统的测试结果是system_clock的精度是100纳秒,而high_resolution的精度是1纳秒,对于程序来说,一般毫秒级就够了,所以说chrono提供的时钟精度绰绰有余。

(1)成员函数static time_point now() noexcept; 用于获取系统的当前时间。

(2)由于各种time_point表示方式不同,chrono也提供了相应的转换函数 time_point_cast。

template <class ToDuration, class Clock, class Duration>
  time_point<Clock,ToDuration> time_point_cast (const time_point<Clock,Duration>& tp);
传一个要转换为的精度的duration模板参数和一个要转换的time_point参数(用法见下面综合应用)

(3)其他成员函数:

to_time_t() time_point转换成time_t秒

from_time_t() 从time_t转换成time_point

综合应用:

输出当前时间,并且计算当前的时间距离1970年1月1日00:00的毫秒数

  1. #include <iostream>   
  2. #include <chrono>   
  3. #include <ctime>   
  4. using namespace std;  
  5. int main()  
  6. {  
  7.     //定义毫秒级别的时钟类型   
  8.     typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;  
  9.     //获取当前时间点,windows system_clock是100纳秒级别的(不同系统不一样,自己按照介绍的方法测试),所以要转换   
  10.     microClock_type tp = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());  
  11.     //转换为ctime.用于打印显示时间   
  12.     time_t tt = chrono::system_clock::to_time_t(tp);  
  13.     char _time[50];  
  14.     ctime_s(_time,sizeof(_time),&tt);  
  15.     cout << "now time is : " << _time;  
  16.     //计算距离1970-1-1,00:00的时间长度,因为当前时间点定义的精度为毫秒,所以输出的是毫秒   
  17.     cout << "to 1970-1-1,00:00  " << tp.time_since_epoch().count() << "ms" << endl;  
  18.     system("pause");  
  19.     return 0;  
  20. }  
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
int main()
{
	//定义毫秒级别的时钟类型
	typedef chrono::time_point<chrono::system_clock, chrono::milliseconds> microClock_type;
	//获取当前时间点,windows system_clock是100纳秒级别的(不同系统不一样,自己按照介绍的方法测试),所以要转换
	microClock_type tp = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
	//转换为ctime.用于打印显示时间
	time_t tt = chrono::system_clock::to_time_t(tp);
	char _time[50];
	ctime_s(_time,sizeof(_time),&tt);
	cout << "now time is : " << _time;
	//计算距离1970-1-1,00:00的时间长度,因为当前时间点定义的精度为毫秒,所以输出的是毫秒
	cout << "to 1970-1-1,00:00  " << tp.time_since_epoch().count() << "ms" << endl;
	system("pause");
	return 0;
}


通过两张图片对比,时间点上相差48-34=14秒、、下面的一长串数字,切掉3位(毫秒)、是28-14=14秒、、正确!说明这一串数字的最后三位就是毫秒数、、充分说明了达到了毫秒级别。

将上面的程序中millisconds换成microseconds或者更小的单位,便可达到微妙,甚至更高的精度。

<think>嗯,用户问的是在C++中如何将系统时间转换为数字表示,比如像1704112496这样的时间戳,以及更高精度的微秒和纳秒怎么处理。首先,我需要回顾一下C++中处理时间的相关库和方法。C++11之后引入了<chrono>库,它提供了更现代的时间处理功能,可能比传统的C函数更方便。 用户提到的例子,1704112496对应2024-01-01的某个时间,这显然是一个Unix时间戳,也就是从1970年1月1日UTC开始的秒数。这时候需要解释如何获取当前时间的秒级时间戳,以及如何将其转换为可读的日期时间格式。 然后是关于更高精度的问题,比如微秒和纳秒C++chrono库支持不同精度的时间点,比如milliseconds、microseconds、nanoseconds。需要展示如何获取当前时间的高精度表示,并转换成对应的数字形式。 另外,用户可能想知道如何在不同精度之间转换,比如如何将纳秒转换为秒,或者如何处理时间点之间的转换。此外,可能还需要涉及到时间戳和日期时间的相互转换,包括如何将时间戳转换为具体的年月日时分秒,以及反向操作。 需要注意的是,不同平台可能有不同的实现方式,尤其是在获取高精度时间时。例如,Windows和Linux可能有不同的函数,但使用chrono库可以跨平台。同时,解释一下epoch时间的概念,以及为什么使用1970年作为起点。 还有可能用户在实际开发中需要处理时区的问题,这时候可能需要提到chrono库中的时区支持,或者使用其他库如date.h(Howard Hinnant的日期库)来处理更复杂的日期时间操作。 最后,总结一下步骤:获取当前时间点,转换为特定精度的时间戳,展示如何转换回可读格式,以及处理高精度时间的方法。确保代码示例简洁明了,并解释关键部分,比如duration_cast的作用,以及time_since_epoch()的意义。</think>在C++中,系统时间的数字表示通常基于 **时间戳(Timestamp)** 实现,其本质是计算从某个固定时间起点(称为 **epoch**)到当前时刻的时间间隔。不同精度(秒、毫秒、微秒、纳秒)的实现方式如下: --- ### **一、时间戳的核心原理** - **Epoch(时间起点)**: 大多数系统采用 **1970-01-01 00:00:00 UTC**(Unix时间),但C++标准允许实现自定义起点。 - **数字表示**: 将时间间隔转换为整数(如秒数、毫秒数等),例如: - `1704112496` → 从epoch到2024-01-01 12:34:56的秒数 - `1704112496123456` → 同一时刻的微秒级表示(秒部分 + 微秒部分) --- ### **二、C++中的实现方式** #### **1. 秒级精度(经典方法)** 使用 `<ctime>` 库: ```cpp #include <ctime> // 获取当前时间戳(秒) std::time_t now_seconds = std::time(nullptr); // 转换为可读时间 std::tm* local_time = std::localtime(&now_seconds); printf("当前时间:%04d-%02d-%02d %02d:%02d:%02d\n", local_time->tm_year + 1900, // 年份从1900开始 local_time->tm_mon + 1, // 月份0~11 local_time->tm_mday, local_time->tm_hour, local_time->tm_min, local_time->tm_sec); ``` #### **2. 高精度时间戳(C++11及以上)** 使用 `<chrono>` 库实现微秒、纳秒精度: ```cpp #include <chrono> #include <iostream> // 获取当前时间戳(纳秒级) auto now = std::chrono::system_clock::now(); // 转换为从epoch开始的持续时间 auto duration_since_epoch = now.time_since_epoch(); // 提取不同精度 auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration_since_epoch).count(); auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(duration_since_epoch).count(); auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(duration_since_epoch).count(); auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(duration_since_epoch).count(); std::cout << "秒: " << seconds << "\n" << "毫秒: " << milliseconds << "\n" << "微秒: " << microseconds << "\n" << "纳秒: " << nanoseconds << std::endl; ``` --- ### **三、时间戳与日期互转** #### **1. 时间戳 → 日期时间** ```cpp #include <chrono> #include <iostream> // 假设时间戳为1704112496123456(微秒级) int64_t timestamp = 1704112496123456; // 转换为chrono时间点 auto time_point = std::chrono::system_clock::time_point( std::chrono::microseconds(timestamp) ); // 转换为本地时间(需要C++20或第三方库如date.h) // 示例使用C++20: #include <format> std::time_t t = std::chrono::system_clock::to_time_t(time_point); std::cout << std::format("{:%Y-%m-%d %H:%M:%S}", *std::localtime(&t)) << std::endl; ``` #### **2. 日期时间 → 时间戳** ```cpp #include <chrono> #include <sstream> // 解析字符串时间(如"2024-01-01 12:34:56") std::tm tm = {}; std::istringstream ss("2024-01-01 12:34:56"); ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S"); // 转换为time_t(秒级) std::time_t t = std::mktime(&tm); // 转换为chrono时间点 auto time_point = std::chrono::system_clock::from_time_t(t); // 获取微秒级时间戳 int64_t timestamp = std::chrono::duration_cast<std::chrono::microseconds>( time_point.time_since_epoch() ).count(); ``` --- ### **四、精度与平台差异** | 精度 | 实现方式 | 典型应用场景 | |------------|-----------------------------------|-----------------------| | **秒** | `std::time_t` + `<ctime>` | 日志记录、简单计时 | | **毫秒** | `std::chrono::milliseconds` | 性能测试、API超时控制 | | **微秒** | `std::chrono::microseconds` | 高精度传感器数据 | | **纳秒** | `std::chrono::nanoseconds` | 实时系统、硬件级操作 | - **注意**:Windows系统下 `std::chrono::system_clock` 的精度通常为 **100纳秒**,而Linux/MacOS可达 **纳秒级**。 --- ### **五、关键代码解释** - `time_since_epoch()`: 返回从epoch到当前时间点的持续时间(`duration`对象)。 - `duration_cast`: 用于在不同时间单位间转换(如纳秒→秒)。 - `std::chrono::system_clock`: 系统范围的挂钟时间(可能受时区影响)。 - `std::chrono::steady_clock`: 单调时钟,适合测量时间间隔(不受系统时间调整影响)。 --- ### **六、扩展:处理时区** 若需处理时区,可借助第三方库(如 [date.h](https://github.com/HowardHinnant/date)): ```cpp #include "date/date.h" #include <iostream> int64_t timestamp = 1704112496123456; auto tp = std::chrono::system_clock::time_point(std::chrono::microseconds(timestamp)); // 转换为带时区的时间 date::zoned_time zt{"Asia/Shanghai", tp}; std::cout << zt << std::endl; // 输出:2024-01-01 20:34:56 CST ``` --- 通过上述方法,可以灵活地在C++中实现时间与数字表示的转换,并根据需求选择合适精度
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值