C++11 处理时间和日期的处理,以及chrono库介绍

C++11提供了日期和时间相关的库chrono,通过这个库可以很方便的对时间和日期进行处理:
chrono库主要包含三种类型:

1.时间间隔duration

介绍一下duraton的原型:

template<class Rep, class Period=std::ratio<1, 1>>
class duration;

Rep表示时钟数的类型,Period表示时钟周期。

C++标准库中的一些时间间隔:

typedf duration<Rep, ratio<3600, 1>> hours;
typedf duration<Rep, ratio<60, 1>> minutes;
typedf duration<Rep, ratio<3600, 1>> seconds;
typedf duration<Rep, ratio<1, 1000>> milliseconds; 

同时,还提供了获取时钟周期数的方法count().

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
#include <random>
#include <chrono>

int main()
{
	std::chrono::milliseconds ms(3);    // 3ms
	std::chrono::microseconds micro_s = 2 * ms;
	std::cout << "milliseconds count is " << ms.count() << std::endl;
	std::cout << "microseconds count is " << micro_s.count() << std::endl;

	std::chrono::duration<double, std::ratio<1, 30>> hz30(3.5);   // 30hz time clock

	// 时间相减
	std::chrono::minutes t1(10);
	std::chrono::seconds t2(64);
	std::chrono::seconds t3 = t1 - t2;
	std::cout << "t3 count is " << t3.count() << std::endl;
	std::cout << typeid(t3).name() << std::endl;   // 查看变量的类型

	// 对时钟周期的转换
	std::chrono::minutes h1 = std::chrono::duration_cast<std::chrono::minutes>(t3);    // 这个转换只能转换为整数
	std::cout << "The minute is " << h1.count() << std::endl;
    return 0;
}

运行结果如下所示:

2.时钟clock

clocks表示当前的系统时钟。clock包含三种时钟:
1. system_clock: 代表真实世界的挂钟时间,具体指依赖于系统。保证提供的时间值是一个可读的时间。

2. steady_clock: 不能被调整的时钟,保证先后得到的时间是递增的。

3. high_resulution_clock: 高精度时钟。

例如:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
#include <random>
#include <chrono>
#include <ctime>
#include <string>

int main()
{
	std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();  // 获取时间
	for (int i = 0; i < 10000; i++)
	{

	}
	std::chrono::system_clock::time_point t2 = std::chrono::system_clock::now();
	// 两个时间点之间相差的时钟周期
	std::cout << "Time elapsed " << (t2 - t1).count() << std::endl;
	// 将时间进行转换
	int mico_s = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();
	std::cout << "Time is " << mico_s << " microseconds" << std::endl;

	// time_point(chrono库)和c_time(ctime库)之间的转换
	// 函数to_time_t 和 from_time_t
	std::time_t t3 = clock();
	for (int i = 0; i < 1000; i++)
	{
		for (int j = 0; j < 1000; j++)
		{

		}
	}
	std::time_t elapsed = clock() - t3;
	std::cout << "t3 is " << elapsed << std::endl;

	std::time_t t_time =  std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
	std::chrono::system_clock::time_point tp = std::chrono::system_clock::from_time_t(elapsed);

    return 0;
}

3. 时间点time_point

time_point表示时间点,用来获取从纪元开始所经过的duration和当前时间,可以做一些时间的比较和算术运算。

#include "stdafx.h"
#include <iostream>
#include <random>
#include <chrono>

int main()
{
	// 计算从1970-1-1至今经过的天数
	typedef std::chrono::duration<int, std::ratio<60 * 60 * 24, 1>> day_type;   // 定义一天的duration
	std::chrono::time_point<std::chrono::system_clock, day_type> today =
		std::chrono::time_point_cast<day_type>(std::chrono::system_clock::now());
	std::cout << "Elapse days count is " << today.time_since_epoch().count() << std::endl;
    return 0;
}

两个time_point支持相加减操作。但是不同clock的time_point是不能相加减的。

#include "stdafx.h"
#include <iostream>
#include <random>
#include <chrono>
#include <ctime>
#include <string>
// 由于没有找到put_time函数,所以自定义一个时间转换的函数

int main()
{
	using namespace std::chrono;

	system_clock::time_point now = system_clock::now();
	std::time_t last = system_clock::to_time_t(now - hours(24));     // 向time_T转换
	std::time_t next = system_clock::to_time_t(now + hours(24));
	std::cout << "one day ago the time was " << std::localtime(&last)->tm_mon << std::endl;
    // std::localtime(&last)返回的是一个结构体指针,该结构体中包含具体的时间信息,std::put_time不可用的话需要自己将时间拼接成需要的格式
    return 0;
}

计时器Timer

利用high_resolution_clock可以实现一个计时器,这样的timer在测试程序性能时经常用到,计时器的实现代码如下所示:

#pragma once
#include <chrono>

using namespace std;

// 定义Timer类
class Timer
{
private:
	chrono::time_point<chrono::high_resolution_clock> begin;

public:
	Timer() : begin(chrono::high_resolution_clock::now()) {}   // 构造函数
	
	// reset方法
	void reset()
	{
		begin = chrono::high_resolution_clock::now();
	}

	// 输出经过的时间,定义为模板函数
	template<typename Duration=chrono::milliseconds>   // 默认输出毫秒ms
	int64_t elapsed() const
	{
		return chrono::duration_cast<Duration>(chrono::high_resolution_clock::now() - begin).count();
	}

	// 输出微妙
	int64_t elapsed_microseconds()
	{
		return elapsed<chrono::milliseconds>();
	}

	// 输出纳秒
	int64_t elapsed_nanoseconds()
	{
		return elapsed<chrono::nanoseconds>();
	}

	// 输出秒
	int64_t elapsed_seconds()
	{
		return elapsed<chrono::seconds>();
	}

	// 输出分minute
	int64_t elapsed_minutes()
	{
		return elapsed<chrono::minutes>();
	}

	// 输出时hour
	int64_t elapsed_hours()
	{
		return elapsed<chrono::hours>();
	}
};

Timer的基本用法:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
#include "stdafx.h"
#include "Timer.h"

int main()
{
	Timer timer;  // 开始计时
	for (int i = 0; i < 10000; i++)
	{
		for (int j = 0; j < 10000; j++) {}
	}
	std::cout << "Elapsed " << timer.elapsed() << " ms" << std::endl;
	std::cout << "Elapsed " << timer.elapsed_seconds() << " s" << std::endl;
	std::cout << "Elapsed " << timer.elapsed_nanoseconds() << " ns" << std::endl;
    return 0;
}

输出结果:

---------------------------------------------------------------------------------------------------------------------------

ctime库中测量时间的方法:

// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include <iostream>
#include <ctime>
#include "Timer.h"

const double CLOCK_PER_SECOND = static_cast<double>(CLOCKS_PER_SEC);  // 每秒钟的时钟数
const double CLOCK_PER_MILLISEC = CLOCK_PER_SECOND / 1000.0;          // 每毫秒的时钟数   

int main()
{
   std::time_t start = clock();
   for (int i = 0; i < 10000; i++)
   {
	   for (int j = 0; j < 10000; j++) {}
   }
   double elapsed_ms = (clock() - start) / CLOCK_PER_MILLISEC;
   std::cout << "Timer elapsed " << elapsed_ms << " ms" << std::endl;
   return 0;
}

将ctime中的测量时间的方法也可以封装为一个计时器Timer。

 

posted @ 2019-08-09 12:12  Alpha205  阅读(857)  评论(0编辑  收藏  举报