文章目录
自从C++11之后,标准库中出现了一个std::chrono库,这个库对时间的一些感念进行抽象,在灵活性和扩展性上要好于C风格的时间函数。下面就梳理一下这个库。
概貌
这个库源自Boost.Chrono,N2661 - A Foundation to Sleep On提供了这个设计的背景和动机。
Boost.Chrono除了有标准库std::chrono的基本功能外,它还有很多其它功能,而且多了几个clock。
要使用chrono库,需要包含#include<chrono>
,其所有实现均在std::chrono namespace中。这个库定义了三个主要类型:
- Durations 用于测量时间跨度。像1分钟,2小时或者10毫秒。在这个库中,它们由
duration
类模板对象表示,它们由计数(count representation)和时间单位(period precision)组成,例如10毫秒由10(计数)和毫秒(时间单位)组成。 - Time points 代表一个特定的时间点,像某人的生日,下一趟火车的经过时间。在这个库中,
time_point
类模板的对象靠使用相对于标准时间点(epoch)的duration
来表示特定时间点。 - Clocks 一个将时间点映射到真实物理时间的框架。一个时钟包含一个开始时间点(例如1970年1月1日)和计时周期(例如秒)。这个库提供了至少3个时钟,这些时钟提供了以
time_point
表示当前时间的方法。有system_clock
,steady_clock
和high_resolution_clock
.
Durations
duration
1 | template <class Rep, class Period = ratio<1> > |
Rep是一个算术类型,或者一个具有算法运算的类,用于表示计数。
Period是一个ratio类型,表示以秒为单位的周期。
成员函数:1
2count() //返回计数,时间单位不一定是秒
operators() //各种算术运算
一些有用的辅助类型:
type | Representation | Period |
---|---|---|
hours | signed integral type of at least 23 bits | ratio<3600,1>3600,1> |
minutes | signed integral type of at least 29 bits | ratio<60,1>60,1> |
seconds | signed integral type of at least 35 bits | ratio<1,1>1,1> |
milliseconds | signed integral type of at least 45 bits | ratio<1,1000>1,1000> |
microseconds | signed integral type of at least 55 bits | ratio<1,1000000>1,1000000> |
nanoseconds | signed integral type of at least 64 bits | ratio<1,1000000000>1,1000000000> |
这里说明一下ratio
类型1
template <intmax_t N, intmax_t D = 1> class ratio;
这个模板类能在编译时计算有理数。
N是分子,D是分母,ratio<1,1000>
表示单位时间是毫秒。
Clocks
system_clock
是一个系统时钟,有以下特性:
- 真实时间
它被用于表示真实时间,因此它可以和time_t进行转换。 - 有符号的计数
它的time_point
可以表示epoch前的时间(负值)。 - 系统级
运行在系统中的所有程序会得到同样的time_point
值。
成员函数:1
2
3now() //获取当前时间time_point
to_time_t() //将time_point转换成time_t秒
from_time_t() //将time_t转换成time_point
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>
int main ()
{
using std::chrono::system_clock;
std::chrono::duration<int,std::ratio<60*60*24> > one_day (1);
system_clock::time_point today = system_clock::now();
system_clock::time_point tomorrow = today + one_day;
std::time_t tt;
tt = system_clock::to_time_t ( today );
std::cout << "today is: " << ctime(&tt);
tt = system_clock::to_time_t ( tomorrow );
std::cout << "tomorrow will be: " << ctime(&tt);
return 0;
}
steady_clock
稳定时钟,表示一个单调递增时钟,它与系统时钟(wall clock time)无关,如果修改了系统时间,也不会影响到此时钟。适用于测量时间间隔,例如算法计时。
成员函数:1
now() //获取当前时间点
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>
int main ()
{
using namespace std::chrono;
steady_clock::time_point t1 = steady_clock::now();
std::cout << "printing out 1000 stars...\n";
for (int i=0; i<1000; ++i) std::cout << "*";
std::cout << std::endl;
steady_clock::time_point t2 = steady_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
std::cout << "It took me " << time_span.count() << " seconds.";
std::cout << std::endl;
return 0;
}
high_resolution_clock
高精度时钟,是一个拥有最短计时周期的时钟,是system_clock
或者steady_clock
的别名。
成员函数:1
now() //获取当前时间点
Time points
time_point
1 | template <class Clock, class Duration = typename Clock::duration> |
是一个时间点,是从标准时间点(epoch,起始时间,一个时间参考点)开始的时间长度。内部存储了一个duration
对象,并使用Clock
作为标准时间点(epoch)的参考。
成员函数:1
2time_since_epoch() //返回从它的epoch开始到当前时间点的duration时间(时间段)
operators //各种算式运算操作和关系运算操作
注意:两个time_point
相减,得到duration
类型。
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>
int main()
{
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24));
std::cout << "24 hours ago, the time was "
<< std::put_time(std::localtime(&now_c), "%F %T") << '\n';
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
std::cout << "Hello World\n";
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "Printing took "
<< std::chrono::duration_cast<std::chrono::microseconds>(end - start).count()
<< "us.\n";
}
其它辅助函数
time_point_cast
1 | template <class ToDuration, class Clock, class Duration> |
转换time_point从一个duration
到另一个duration
。相当于转换了time_point的时间单位。
注意:此函数的模板参数是duration
类型,而不是time_point
类型。
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <iostream>
#include <ratio>
#include <chrono>
int main ()
{
using namespace std::chrono;
typedef duration<int,std::ratio<60*60*24>> days_type;
time_point<system_clock,days_type> today = time_point_cast<days_type>(system_clock::now());
std::cout << today.time_since_epoch().count() << " days since epoch" << std::endl; // 15490 days since epoch
return 0;
}
duration_cast
1 | template <class ToDuration, class Rep, class Period> |
功能与time_point_cast
一样,只是作用的对象是duration
类型。
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <iostream> // std::cout
#include <chrono> // std::chrono::seconds, std::chrono::milliseconds
// std::chrono::duration_cast
int main ()
{
std::chrono::seconds s (1); // 1 second
std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds> (s);
ms += std::chrono::milliseconds(2500); // 2500 millisecond
s = std::chrono::duration_cast<std::chrono::seconds> (ms); // truncated
std::cout << "ms: " << ms.count() << std::endl; //ms: 3500
std::cout << "s: " << s.count() << std::endl; //s: 3
return 0;
}
格式化时间
time_point
格式化
time_point
不能直接输出到stream中,需要转换成std::time_t
或者std::tm
,使用ctime
、asctime
、strftime
或者std::put_time
格式化成字符串。
示例:1
2
3
4
5
6
7
8system_clock::time_point today = system_clock::now();
time_t tt;
tt = system_clock::to_time_t ( today );
std::cout << "today is: " << ctime(&tt);
std::cout << "today is: "
<< std::put_time(std::localtime(&tt), "%F %T") << '\n';
总结
durationS
代表了一个时间段,即多少个时间单位。time_pointS
代表了从一个时间参考点开始经历了多长时间,是一个时间点。例如,开机后3小时,从计时器开始后的3秒钟等等。其中时间参考点由clockS
提供,时长由duration
表示。当两个时间点拥有同样的时间参考点,就可以进行比较和计算。clockS
代表一个现实时钟,由参考时间点和计时周期组成。可以自定义clock
。now()
函数返回当前时间点time_point
。clockS
和time_pointS
之间紧密的相互联系和引用。
参考
版权声明