时间操作chrono库
C++中chrono
库是一个用于处理时间的库。它提供了一种方便、安全且高精度的方式来进行时间的测量和持续时间操作。
时间长度(Durations)
在chrono
库中,时间长度是通过duration
类模板表示的,它表示两个事件之间的时间差。这个模板包含两个参数:一个是代表时间的数值类型(Rep),另一个是一个比率类型(Period),表示每个时间单位代表的秒数的分数。
template<class Rep, class Period = std::ratio<1, 1>>
class duration;
这个模板类在内部使用Rep类型的变量来存储时间长度,并使用Period来解释这个值代表的时间单位。
标准时间单位
为了方便,chrono
已经定义了一些常见的duration类型,用于表示常用的时间单位,如小时、分钟、秒等。这些预定义的类型是基于chrono::duration
的特化。
using hours = duration<long long, std::ratio<3600>>; // 小时
using minutes = duration<long long, std::ratio<60>>; // 分钟
using seconds = duration<long long>; // 秒
using milliseconds = duration<long long, std::milli>; // 毫秒
using microseconds = duration<long long, std::micro>; // 微秒
using nanoseconds = duration<long long, std::nano>; // 纳秒
duration的操作
duration对象可以进行常规的算术操作,如加法、减法和比较。这让时间计算变得直观且容易理解。
- 算术运算:可以直接使用标准的算术运算符(如
+
,-
)来对duration对象进行计算。 - 比较:duration对象可以使用比较运算符(如
==
,!=
,<
,>
)进行比较。 - 获取数值:使用
count()
方法可以获取存储在duration对象中的原始数值(即时间长度)。
下面是一个完整示例:
#include <iostream>
#include <chrono> // 引入时间库
using namespace std;
int main() {
// 创建不同的时间单位
chrono::hours t1(1); // 1小时
chrono::minutes t2(60); // 60分钟
chrono::seconds t3(60 * 60); // 3600秒
chrono::milliseconds t4(60 * 60 * 1000); // 3600000毫秒
// 比较不同时间单位间的等价性
if (t1 == t2) cout << "1 hour is equal to 60 minutes\n";
if (t1 == t3) cout << "1 hour is equal to 3600 seconds\n";
if (t1 == t4) cout << "1 hour is equal to 3600000 milliseconds\n";
// 打印各时间单位的原始值
cout << "1 hour in hours: " << t1.count() << '\n';
cout << "60 minutes in minutes: " << t2.count() << '\n';
cout << "3600 seconds in seconds: " << t3.count() << '\n';
cout << "3600000 milliseconds in milliseconds: " << t4.count() << '\n';
// 创建更多的时间单位
chrono::seconds t7(1); // 1秒
chrono::milliseconds t8(1000); // 1000毫秒
chrono::microseconds t9(1000 * 1000); // 1000000微秒
chrono::nanoseconds t10(1000 * 1000 * 1000); // 1000000000纳秒
// 比较新创建的时间单位间的等价性
if (t7 == t8) cout << "1 second is equal to 1000 milliseconds\n";
if (t7 == t9) cout << "1 second is equal to 1000000 microseconds\n";
if (t7 == t10) cout << "1 second is equal to 1000000000 nanoseconds\n";
// 打印更多时间单位的原始值
cout << "1 second in seconds: " << t7.count() << '\n';
cout << "1000 milliseconds in milliseconds: " << t8.count() << '\n';
cout << "1000000 microseconds in microseconds: " << t9.count() << '\n';
cout << "1000000000 nanoseconds in nanoseconds: " << t10.count() << '\n';
return 0;
}
系统时间
C++中的std::chrono::system_clock
类是处理系统相关时间的重要工具。它是chrono
库的一部分,主要用于表示和操作系统时间。system_clock
提供了几个功能,包括获取当前时间、将时间点转换为传统的时间表示(如time_t
),以及**从传统时间类型创建时间点。**下面是关于system_clock
各个方面的详细解释:
- 获取当前时间点(系统时间):
std::chrono::system_clock::now()
是一个静态成员函数,返回一个代表当前系统时间的time_point
对象。这是你获取系统当前时间的起点。
auto now = chrono::system_clock::now();
在这里,now
是一个time_point
类型的对象,代表了调用now()
时的时间点。
-
将时间点
time_point
类型转换为std::time_t
类型:C++中的
time_t
通常用来存储自纪元(1970年1月1日)以来的秒数。它是C和C++中传统的时间处理方式。
auto t_now = chrono::system_clock::to_time_t(now);
这里,t_now
是一个time_t
类型的对象,包含了与time_point
对象now
相对应的UTC时间(协调世界时)。
-
将
std::time_t
类型转换为时间点time_point
类型:与
to_time_t
相反的是,from_time_t
函数可以让你从一个time_t
对象创建一个time_point
对象,这在你需要与使用time_t
的老旧代码交互时非常有用。
std::time_t tt = std::time(nullptr); // 获取当前的系统时间
auto timepoint = std::chrono::system_clock::from_time_t(tt);
- 处理本地时间:
你可以将time_t
类型的时间转换为结构化的时间,这通常更方便人们阅读和处理。C++中使用std::tm
结构体来表示结构化时间。
auto tm_now = std::localtime(&t_now);
在这里,tm_now
是一个指向tm
结构体的指针,它包含了本地时间(考虑了时区的时间)。请注意,localtime
是不安全的,因为它在内部使用了静态存储区域,所以在多线程环境下需要谨慎使用。
- 格式化时间输出:
当你想以一种可读的方式打印或显示时间时,可以使用C++中的std::put_time
来格式化tm
结构体的输出。
cout << std::put_time(tm_now, "%Y-%m-%d %H:%M:%S") << endl;
这行代码会按照"年-月-日 时:分:秒"的格式输出时间。你可以使用不同的格式化字符串来改变输出的格式。
cout << std::put_time(tm_now, "%Y-%m-%d %H:%M:%S") << std::endl;
cout << std::put_time(tm_now, "%Y-%m-%d") << std::endl;
cout << std::put_time(tm_now, "%H:%M:%S") << std::endl;
cout << std::put_time(tm_now, "%Y%m%d%H%M%S") << std::endl;
-
使用字符串流格式化时间:
stringstream ss; ss << std::put_time(tm_now, "%Y-%m-%d %H:%M:%S"); string timestr = ss.str(); cout << timestr << endl;
在这里,我们使用了一个
std::stringstream
来创建一个格式化的时间字符串。stringstream
可以像使用流操作符(如<<
)操作std::cout
那样来操作字符串。这使得字符串的创建和操作更加灵活和强大。
下面是一个完整示例:
#include <iostream> // 包含输入/输出流的头文件
#include <chrono> // 包含chrono库的头文件,用于处理时间
#include <ctime> // 包含处理日期和时间的函数
#include <iomanip> // 包含格式化输出的函数,如put_time
#include <sstream> // 包含字符串流
using namespace std; // 使用std命名空间
int main() {
// 步骤1: 获取当前系统时间
auto now = chrono::system_clock::now();
// 步骤2: 将时间点转换为time_t类型
auto t_now = chrono::system_clock::to_time_t(now);
// 步骤3: 对时间进行操作(如果需要的话)
// t_now = t_now + 24*60*60; // 例如,增加一天的秒数
// 步骤4: 将time_t转换为本地时间
auto tm_now = localtime(&t_now); // 转换为本地时间
// 步骤5: 格式化时间的输出
cout << "Current time in various formats:" << endl;
cout << put_time(tm_now, "%Y-%m-%d %H:%M:%S") << endl; // 年-月-日 时:分:秒
cout << put_time(tm_now, "%Y-%m-%d") << endl; // 年-月-日
cout << put_time(tm_now, "%H:%M:%S") << endl; // 时:分:秒
// 步骤6: 使用字符串流格式化时间
stringstream ss;
ss << put_time(tm_now, "%Y-%m-%d %H:%M:%S"); // 向流中插入格式化时间
string timestr = ss.str(); // 从流中获取字符串
cout << "Time from stringstream: " << timestr << endl; // 输出从字符串流获取的时间
return 0; // 主函数返回0,表示程序成功结束
}
计时器
在许多情况下,开发人员需要测量特定操作的执行时间,例如性能测试、基准测试或简单的时间追踪。C++中的chrono
库包含steady_clock
类相当于秒表,操作系统只要启动就会进行时间的累加,常用于耗时的统计(精确到纳秒)。
以下是如何使用 steady_clock
创建一个计时器的步骤概述:
#include <iostream>
#include <chrono>
using namespace std;
int main()
{
// 静态成员函数chrono::steady_clock::now()获取开始的时间点。
auto start = chrono::steady_clock::now();
// 执行一些代码,让它消耗一些时间。
cout << "计时开始 ...... \n";
for (int ii = 0; ii < 1000000; ii++) {
// cout << "我是一只傻傻鸟。\n";
}
cout << "计时完成 ...... \n";
// 静态成员函数chrono::steady_clock::now()获取结束的时间点。
auto end = chrono::steady_clock::now();
// 计算消耗的时间,单位是纳秒。
auto dt = end - start;
cout << "耗时: " << dt.count() << "纳秒("<<(double)dt.count()/(1000*1000*1000)<<"秒)";
}