c/c++中各种时间函数
time_t
time()提供了秒级的精确度
函数time_t time(time_t * timer),返回从TC1970-1-1 0:0:0开始到现在的秒数,
如果需要更高的时间精确度,就需要struct timespec 和 struct timeval来处理
timeval & timespec
- struct timespec有两个成员,一个是秒,一个是纳秒, 所以最高精确度是纳秒。
一般由函数int clock_gettime(clockid_t, struct timespec *)获取特定时钟的时间,常用如下4种时钟:- CLOCK_REALTIME 统当前时间,从1970年1.1日算起
- CLOCK_MONOTONIC 系统的启动时间,不能被设置
- CLOCK_PROCESS_CPUTIME_ID 本进程运行时间
- CLOCK_THREAD_CPUTIME_ID 本线程运行时间
- struct timeval有两个成员,一个是秒,一个是微秒, 所以最高精确度是微秒。一般由函数int gettimeofday(struct timeval *tv, struct timezone *tz)获取系统的时间
struct tm
tm的成员包括:tm_sec, tm_mday(day of the month, 注意只有它索引是从1开始), tm_mon等
- 通过localtime_r(time_t* t, tm* buf)在buf中存储t所对应的时间
- 通过asctime(tm* tm)可以将其转化为类似Www Mmm dd hh:mm:ss yyyy\n形式的字符串
- 通过strftime(const char* dest, size_t n, const char* format, tm* tm) 可以将tm转化为和format形式相同的日期格式并储存在dest数组中,最多不能超过n个字节
c++中的chrono库
chrono 库定义三种主要类型以及工具函数和常用 typedef
- 时钟(clock)
- system_clock
- steady_clock
C++ 标准不提供有关时钟精度、起始点或有效时间范围的保证。通常, std::chrono:system_clock的起点是 1.1.1970,即所谓的UNIX-epoch。对于std::chrono::steady_clock,通常是 PC 的启动时间。 - 每种clock都有类似的成员函数:
- rep
- period
- std::chrono::duration<rep, period>(见后文)
- std::chrono::timepoint
(见后文)
- 使用now方法可以获得当前的timepoint
- 时间点(timepoint)
- 类模板原型:
template <class Clock, class Duration = typename Clock::duration> class time_point;
- 表示时间中的一个点。它被实现成如同存储一个 Duration 类型的值,指定自 Clock 的纪元起始开始的时间间隔。
- 使用timepoint的time_since_epoch方法获得离epoch的duration,或者对两个不同的time_point进行加减操作也可以获取duration(当然,也可以获得一个新的timepoint),但不能通过直接输出timepoint来获取duration
- 类模板原型:
- 时长(duration)
template<class rep, class Period = ratio<1> > class duration
Rep 表示一种数值类型,用来表示Period的数量,比如int float double
Period是ratio类型,用来表示【用秒表示的时间单位】比如second,milisecondtemplate <intmax_t N, intmax_t D = 1> class ratio;
N代表分子,D代表分母,所以ratio表示一个分数值。
若 Rep 是浮点类型,则 duration 能表示小数的计次数- 有些duration类型可以简写,比如
std::chrono::milliseconds = std::chrono::duration</* int45 */, std::milli>
1 |
|
- 我们在使用chrono库中的小时,分钟,秒等时间单位时,需要创建如
hours(1)
,seconds(30)
来表示时间长度,可以加入using namespace literals
或using namespace chrono_literals
以使用标准后缀如秒(s),毫秒(ms)和小时(h)等简化在C++14中的代码,其中标准后缀基于C++11对用户自定义常量的支持。这些后缀在std::literals命名空间中实现,因此上述代码可以按照以下方式重写:1h, 30s
literals标准后缀规定了string和chrono::duration的各种后缀,二者有相同后缀名s,在string中”abcd\0111”s表示使用类型为const char *的”abcd\0111”来构建字符串并且忽略\0作为结束符,同样的,我们可以引入
using namespace string_literals
来使用s后缀
chrono一些特性
- system_clock :: to_time_t(time_point& t)将time_point 转换为 time_t 类型:
1
2auto const now = std::chrono::system_clock::now();
std::time_t newt = std::chrono::system_clock::to_time_t(now);c++11前获取当前时间 std::time_t oldt = std::time({});
chrono注意事项
- 由于各种duration表示不同,chrono库提供了duration_cast类型转换函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 无精度损失的整数尺度转换:无转型
std::cout << std::chrono::milliseconds(1s).count() << " 毫秒\n"
<< std::chrono::microseconds(1s).count() << " 微秒\n"
<< std::chrono::nanoseconds(1s).count() << " 纳秒\n";
// 有精度损失的整数尺度转换:需要转型
std::cout << std::chrono::duration_cast<std::chrono::minutes>(1s).count()
<< " 分\n";
const auto t1 = std::chrono::high_resolution_clock::now();
f();
const auto t2 = std::chrono::high_resolution_clock::now();
// 浮点时长不需要转型
const std::chrono::duration<double, std::milli> fp_ms = t2 - t1;
// 浮点转整数需要转型
const auto int_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1); - system_clock 和 steady_clock对应的duration的period都是纳秒, 也就是10的负9次方,当二者使用now获得的timepoint进行操作时,比如二者相减获取相差时间,输出的duration的单位即为period所对应的单位,比如period为std::micro / std::ratio<1, 1000000>, 则会输出xxx ms,使用duration的count方法会直接输出xxx,没有单位