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。