c++11 时间模板库chrono

1.概述

C++11引入了库,它提供了一组用于处理时间间隔和时间点的实用工具。该库旨在提供一种类型安全且全面的方式来处理与时间相关的操作。

2.主要关键组件

std::ratio:表示的是时间单位,例如std::ratio<1,1>表示1s,std::ratio<60,1>表示1min
std::chrono::duration:表示时间长度,可以表示一天,一个月,一年等等
std::chrono::time_point:表示时间点,定义为自纪元(1900.1.1 00:00:00)以来的持续时间
std::chrono::system_clock:表示系统范围的实时挂钟
std::chrono::steady_clock:一个不受系统时钟调整影响的单调时钟。用于测量时间间隔
std::chrono::duration_cast:在不同的持续时间类型之间进行转换
std::chrono::time_point_cast:在不同的时间点类型之间进行转换

细则

std::ratio

模板定义 template<intmax_t _Nx, intmax_t _Dx = 1> struct ratio;
ratio表示时间单位,它表示的是以Nx/Dx的值表示最小刻度的单位。
ratio<1,1> 表示以1s为最小单位
ratio<60,1> 表示以1min为最小单位
ratio<6060,1> 表示以1h为最小单位
ratio<1,1000> 表示以1毫秒为最小单位
ratio<1,1000
1000> 表示以1微秒为最小单位
ratio<1,100010001000> 表示以1纳秒为最小单位

std::chrono::duration

模板定义

template<class _Rep,
	class _Period>
	class duration
	{	// represents a time duration
public:
	using rep = _Rep;
	using period = typename _Period::type;

	static_assert(!_Is_duration_v<_Rep>,
		"duration can't have duration as first template argument");
	static_assert(_Is_ratio_v<_Period>,
		"period not an instance of std::ratio");
	static_assert(0 < _Period::num,
		"period negative or zero");
		.......

_Rep为数值类型_Period为ratio类型,主要表示的是一段时间距离。
直接看例子 分别表示1s、1min、 1h、1day等的不同方式

	//分别表示1s、1min、 1h、1day的不同方式
	std::chrono::duration<int, std::ratio<1, 1>>				du_s(1);//最小单位为1秒
	std::chrono::duration<int, std::ratio<60, 1>>				du_m(1);//最小单位为1min
	std::chrono::duration<int, std::ratio<60*60, 1>>			du_h(1);//最小单位为h
	std::chrono::duration<int, std::ratio<60*60*24, 1>>			du_d(1);//最小单位为day
	//分别表示1毫秒、1微秒、1纳秒
	std::chrono::duration<int, std::ratio<1, 1000>>				du_mi(1);//最小单位为1毫秒
	std::chrono::duration<int, std::ratio<1, 1000000>>			du_mc(1);//最小单位为1微秒
	std::chrono::duration<int, std::ratio<1, 1000000000>>		du_no(1);//最小单位为1纳秒
	//duration还提供了对应的接口函数++ -- *=value 不过这些都是以最小单位为1刻度进行相加时间 例如
	du_s * 3;	//表示3秒
	du_s ++;	//表示2秒

	du_m * 5;		//表示5天
	du_m * 3 * 5;	//表示15天
	//相同类型的duration可以直接相加减不同类型的需要借助std::chrono::duration_cast进行转换成相同类型后再相加
	
	//相同类型
	std::chrono::duration<int, std::ratio<60 * 60 * 24, 1>>			du_d2(5);
	du_d + du_d2; //6day
	//不同类型
	//(du_d += du_s; //会报错)
	//会先将du_s转换成最小单位为day的类型 然后再相加
	//因为是小单位转换成大单位所以精度会丢失 既相加后还是1天
	du_d += std::chrono::duration_cast<std::chrono::duration<int, std::ratio<60 * 60 * 24, 1>>>(du_s); 

std::chrono::time_point

表示某一个时间点 直接看源码

template<class _Clock,
	class _Duration = typename _Clock::duration>
	class time_point
	{	// represents a point in time
public:
	using clock = _Clock;
	using duration = _Duration;
	using rep = typename _Duration::rep;
	using period = typename _Duration::period;

	static_assert(_Is_duration_v<_Duration>,
		"duration must be an instance of std::duration");

	constexpr time_point() = default;

	constexpr explicit time_point(const _Duration& _Other)
		: _MyDur(_Other)
		{	// construct from a duration
		}

	template<class _Duration2,
		class = enable_if_t<is_convertible_v<_Duration2, _Duration>>>
		constexpr time_point(const time_point<_Clock, _Duration2>& _Tp)
		: _MyDur(_Tp.time_since_epoch())
		{	// construct from another duration
		}

	_NODISCARD constexpr _Duration time_since_epoch() const
		{	// get duration from epoch
		return (_MyDur);
		}

	_CONSTEXPR17 time_point& operator+=(const _Duration& _Dur)
		{	// increment by duration
		_MyDur += _Dur;
		return (*this);
		}

	_CONSTEXPR17 time_point& operator-=(const _Duration& _Dur)
		{	// decrement by duration
		_MyDur -= _Dur;
		return (*this);
		}

	_NODISCARD static constexpr time_point (min)() noexcept // Strengthened, P0972
		{	// get minimum time point
		return (time_point((_Duration::min)()));
		}

	_NODISCARD static constexpr time_point (max)() noexcept // Strengthened, P0972
		{	// get maximum time point
		return (time_point((_Duration::max)()));
		}

private:
	_Duration _MyDur{duration::zero()};	// duration since the epoch
	};
}	// namespace chrono

源码内容十分简单 模板类会接收一个Clock模板从Clock模板中获取_Duration,也就是说time_point的最小单位取决于
Clock中的_Duration中的ratio。
与此同时还提供了±=(const _Duration& _Dur)接口用来计算下一时刻、下一段距离后的时刻点
其中提供了time_since_epoch返回内部的_Duration。

clock

上一个类中用到的clock分别有三种类型:system_clock、steady_clock、high_resolution_clock

system_clock

表示系统范围的实时挂钟,也就是电脑时间
上源码

struct system_clock
	{	// wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime
	using rep = long long;

	using period = ratio_multiply<ratio<_XTIME_NSECS_PER_TICK, 1>, nano>;

	using duration = chrono::duration<rep, period>;
	using time_point = chrono::time_point<system_clock>;
	static constexpr bool is_steady = false;

	_NODISCARD static time_point now() noexcept
		{	// get current time
		return (time_point(duration(_Xtime_get_ticks())));
		}

	_NODISCARD static __time64_t to_time_t(const time_point& _Time) noexcept
		{	// convert to __time64_t
		return ((__time64_t)(_Time.time_since_epoch().count()
			/ _XTIME_TICKS_PER_TIME_T));
		}

	_NODISCARD static time_point from_time_t(__time64_t _Tm) noexcept
		{	// convert from __time64_t
		return (time_point(duration(_Tm * _XTIME_TICKS_PER_TIME_T)));
		}
	};

从源码中可以看出system_clock的单位主要是以std::ratio<100,nano>为最小单位。
其中static time_point now()获取的是当前的时间点(从纪元开始算起1900年)。
还提供了两个函数to_time_t和from_time_t分别实现time_point到秒级别的转换。
to_time_t从代码上看
_Time.time_since_epoch().count()表示的是n / std::ratio<100,nano>,其中n是多少秒
例如10s的count为 10 / 100/1000000000 = 100000000
而#define _XTIME_TICKS_PER_TIME_T 10000000LL
则count/_XTIME_TICKS_PER_TIME_T =10s

steady_clock

一个不受系统时钟调整影响的单调时钟。用于测量时间间隔

struct steady_clock
	{	// wraps QueryPerformanceCounter
	using rep = long long;
	using period = nano;
	using duration = nanoseconds;
	using time_point = chrono::time_point<steady_clock>;
	static constexpr bool is_steady = true;

	_NODISCARD static time_point now() noexcept
		{	// get current time
		const long long _Freq = _Query_perf_frequency();	// doesn't change after system boot
		const long long _Ctr = _Query_perf_counter();
		static_assert(period::num == 1, "This assumes period::num == 1.");
		const long long _Whole = (_Ctr / _Freq) * period::den;
		const long long _Part = (_Ctr % _Freq) * period::den / _Freq;
		return (time_point(duration(_Whole + _Part)));
		}
	};

using high_resolution_clock = steady_clock;
}	// namespace chrono

steady_clock只是用来测量时间间隔的类,简单写个了例子。

	std::chrono::time_point p1 = std::chrono::steady_clock::now();
	int s = 0;
	for (int i = 0; i < 2000000010; i++)
	{
		s += i;
	}
	std::chrono::time_point p2 = std::chrono::steady_clock::now();

	std::chrono::duration<int, std::ratio<1>> seconde = std::chrono::duration_cast<std::chrono::duration<int, std::ratio<1>>>(p2.time_since_epoch() - p1.time_since_epoch());
	std::cout << "seconde: " << seconde.count();

high_resolution_clock

c++11中的high_resolution_clock 和steady_clock一致
即uing high_resolution_clock = steady_clock;

工作中可能会用到当前日期

	//获取自1900.1.1 00:00:00到当前的时间点
	std::chrono::time_point point =  std::chrono::system_clock::now();
	//获取自1900.1.1 00:00:00到当前的秒
	time_t secondes = std::chrono::system_clock::to_time_t(point);
	std::tm* t =  std::localtime(&secondes);

	std::cout << t->tm_year + 1900 << " " << t->tm_mon + 1 << " " << t->tm_mday<<" ";
	std::cout << t->tm_hour << ":" << t->tm_min<< ":" << t->tm_sec;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值