C/C++时间库使用

C语言中,time.h定义了用于日期和时间操作的结构和函数,而C++标准库中没有提供所谓的日期类型,而是继承自C语言。表示时间中有一个重要的概念:时间戳,时间戳指的是格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数
下面对C/C++中两个重要的时间库ctime和chrono进行分析学习,并说明它们之间的联系。

ctime

在C语言中,ctime头文件包含用于获取和操作日期和时间的函数定义。接下来,将从如何表示时间、不同时间之间的转换、以及时间操作函数三个方面介绍。

时间的数据结构

在ctime中提供了四种不同时间表示的数据结构:clock_t、size_t、time_t、struct tm。
image.png

  1. time_t

表示UTC时区下,自1970年1月1日0点以来经过的秒数,实际上是一个long类型,单位为秒。

  1. struct tm

struct tm是一个结构体,其中包含日期和时间信息。具体的定义如下:

struct tm
{
    
    
    int tm_sec;				/* Seconds.	[0-60] (1 leap second) */int tm_min;				/* Minutes.	[0-59] */int tm_hour;			/* Hours.	[0-23] */int tm_mday;			/* Day.		[1-31] */int tm_mon;				/* Month.	[0-11] */int tm_year;			/* Year	- 1900.  */1900年的年数
    int tm_wday;			/* Day of week.	[0-6] */				星期几
    int tm_yday;			/* Days in year.[0-365]	*/				一年中的第几天
    int tm_isdst;			/* DST.		[-1/0/1]*/					
}

在使用struct tm构建时间时,需要注意每个变量的含义以及起始数。

  1. clock_t

用于时钟滴答计数,实际是long类型。

  1. size_t

unsigned int类型的别名。

时间转换函数

ctime头文件中提供了6种时间转换函数:asctime、ctime、gmtime、localtime、strftime、mktime。

  1. asctime

将struct tm的时间数据结构转换为字符串string。

  1. ctime

将time_t时间数据结构转换为字符串string。

  1. gmtime

将time_t转换为struct tm数据结构(UTC Time)。

  1. localtime

将time_t转换为struct tm数据结构(local Time)。

  1. srftime

将struct tm数据结构生成格式化的字符串内容(常用函数)。

  1. mktime

将struct tm数据结构转换为time_t数据结构。

时间操作函数

ctime中提供了3种时间操作函数:time、clock、difftime。

  1. time

返回当前时间,返回值为time_t类型,表示距离UTC格林尼治时间1970年1月1日00:00:00的时长,单位为秒

time_t now;
time(&now);  /* get current time; same as: now = time(NULL)  */
  1. clock

获取始终的ticks,返回clock_t类型。

  1. difftime

获取两个time_t数据类型之间的时间差,单位为秒。

double difftime (time_t end, time_t beginning);

举例说明

  1. 获取当前时间,并转换为struct tm类型,然后分别转换为字符串并打印
#include <ctime>
#include <iostream>

int main()
{
    
    
    time_t now = time(NULL); // 获取当前时间
    std::cout << "The current local time is: " << ctime(&now) << std::endl;

    struct tm* timeinfo = localtime(&now);
    std::cout << "current Beijing (China) time and date: " << asctime(timeinfo) << std::endl;

    struct tm* timeinfo2 = gmtime(&now);
    std::cout << "current Reykjavik (Iceland) time and date: " << asctime(timeinfo2) << std::endl;

    return 0;
}
  1. 构建struct tm时间,并转换为time_t类型
int main()
{
    
    
    struct tm timeinfo = {
    
    0};
    timeinfo.tm_year = 100;  // 距离1900的100年, 即2000
    timeinfo.tm_mon  = 0;   // 一月
    timeinfo.tm_mday = 1;   // 第一天
    std::cout << "1/1/2000 represented by struct tm is: " << asctime(&timeinfo) << std::endl;

    time_t tt = mktime(&timeinfo);
    std::cout << "1/1/2000 represented by time_t is: " << asctime(&timeinfo) << std::endl;
    return 0;
}
  1. 格式化表示时间
int main()
{
    
    
    struct tm timeinfo = {
    
    0};
    timeinfo.tm_year = 100;  // 距离1900的100年, 即2000
    timeinfo.tm_mon  = 0;   // 一月
    timeinfo.tm_mday = 1;   // 第一天
    // format time as string
    char buf[80];
    // format
    // %Y : Year  (2023)
    // %m : Month (0-12)
    // %d : Day of the month (0-31)
    // %H : Hour in 24th format (00-23)
    // %M : Minute (00-59)
    // %S : Second (00-61)
    strftime(buf, 80, "Now it's %Y-%m-%d-%H-%M-%S.", &timeinfo);
    std::cout << "Format time and data: " << buf << std::endl;
    return 0;
}

chrono

chrono是C++ 11中的时间库,提供计时、时钟等功能。关键是要理解时间段(durations)、时间点(time points)等概念。

时间节拍

时间节拍指的是时间计数的基本单位,其定义如下:

template <intmax_t N, intmax_t D = 1> class ratio;

其中N表示分子,D表示分母,默认的时间节拍单位为秒。
常见时间节拍的定义如下:

ratio <60, 1>  minute;	// 60/1 seconds
ratio <1, 1>   second;
ratio <1, 1000> microsecond;

时间段

duration表示一段时间,其定义如下:

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

其中Rep表示Period的数量,可以是int, float,double等类型。Period是ratio类型,用来表示时间节拍(精度)。
Rep的值乘以Period精度等于一段时间的大小。
chrono中宏定义了许多特例化的duration:hours,miniutes,seconds,milliseconds等等。

/// nanoseconds
typedef duration<int64_t, nano>       nanoseconds;
/// microseconds
typedef duration<int64_t, micro>      microseconds;
/// milliseconds
typedef duration<int64_t, milli>      milliseconds;
/// seconds
typedef duration<int64_t>         seconds;
/// minutes
typedef duration<int64_t, ratio< 60>>   minutes;
/// hours
typedef duration<int64_t, ratio<3600>>  hours;

常见时间单位转换知识:
秒(second),时间单位 : s,
毫秒(millisecond),时间单位:ms
微秒(microsecond),时间单位:μs
时间换算:
1s【秒】 = 1000ms【毫秒】
1ms【毫秒】 = 1000μs【微秒】
1μs【微秒】 = 1000ns【纳秒】
1ns 【纳秒】= 1000ps【皮秒】
其中成员函数count返回单位精度下的数量,即Rep值。duration_cast函数用来转换duration中Period的精度,从而得到不同的Rep值。

#include <iostream>
#include <chrono>

int main()
{
    
    
    // 使用chrono库中自定义的duration
    typedef std::chrono::seconds seconds_type;
    typedef std::chrono::minutes minutes_type;
    typedef std::chrono::hours   hours_type;
    // template<class Rep2>
    // constexpr explicit duration (const Rep2& n);
    hours_type h_oneday(24);            // 24h
    std::cout << h_oneday.count() << "hours." << std::endl;
    // 赋值构造函数
    minutes_type ms_oneday = std::chrono::duration_cast<minutes_type>(h_oneday) ;
    std::cout << ms_oneday.count() << "minutes." << std::endl;
    // 赋值构造函数
    seconds_type s_oneday  = std::chrono::duration_cast<minutes_type>(h_oneday);
    std::cout << s_oneday.count() << "seconds." << std::endl;

    return 0;
}

时间点

time_point表示一个具体时间,其中Clock用来指定需要使用的时钟(system_clock, steady_clock和high_resolution_clock),第二个参数duration type表示以何种精度表示时间点。

template< class Clock, class Duration = typename Clock::duration > class time_point;

Clock时钟

chrono中提供了三种时钟:system_clock、steady_clock和high_resolution_clock。每一个clock类中都有确定的time_point, duration,Rep, Period类型。
这三个时钟类都提供了一个静态成员函数 **now() **用于获取当前时间,该函数的返回值是一个 time_point 类型。

  • system_clock:系统时间,可以人为的调整。system_clock除了now()函数外,还提供了to_time_t()静态成员函数,用于将系统时间转换成熟悉的std::time_t类型,from_time_t()静态成员函数,用来将time_t时间类型转换为time_point;
  • steady_clock:是单调的时钟,类似教练手中的秒表,适合用于记录程序耗时;
  • high_resolution_clock:是当前系统能够提供的最高精度的时钟,同样不可以修改,相当于steady_clock的高精度版本;

举例说明

  1. 记录程序的耗时
int main()
{
    
    
    using std::chrono::steady_clock;
    typedef std::chrono::seconds seconds_type;
    typedef std::chrono::milliseconds milliseconds_type;
    typedef std::chrono::microseconds microseconds_type;

    steady_clock::time_point start = 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 end = steady_clock::now();

    seconds_type s_span = std::chrono::duration_cast<seconds_type>(end - start);
    std::cout << "It took me " << s_span.count() << " seconds." << std::endl;

    milliseconds_type mill_span = std::chrono::duration_cast<milliseconds_type>(end - start);
    std::cout << "It took me " << mill_span.count() << " milliseconds." << std::endl;

    microseconds_type micro_span = std::chrono::duration_cast<microseconds_type>(end - start);
    std::cout << "It took me " << micro_span.count() << " microseconds." << std::endl;
    return 0;
}
  1. system_clock与time_t时间类型互换
int main()
{
    
    
    using std::chrono::system_clock;
    system_clock::time_point now_t = system_clock::now();
    time_t tt;
    tt = system_clock::to_time_t(now_t);
    std::cout << "now is: " << ctime(&tt) << std::endl;

    // 构建 struct tm转换为 time_t,然后将time_t转换为time_point
    struct tm timeinfo = {
    
    0};
    timeinfo.tm_year = 100;  // 距离1900的100年, 即2000
    timeinfo.tm_mon  = 0;   // 一月
    timeinfo.tm_mday = 1;   // 第一天
    time_t tt_2000 = mktime(&timeinfo);
    std::cout << "1/1/2000 is: " << ctime(&tt) << std::endl;
    system_clock::time_point tp = system_clock::from_time_t(tt_2000);
    system_clock::duration d    = system_clock::now() - tp;

    // convert to number of days
    typedef std::chrono::duration<int64_t, std::ratio<60*60*24>> days_type;
    days_type ndays = std::chrono::duration_cast<days_type> (d);
    // display result
    std::cout << ndays.count() << "days have passed since 1/1/2000" << std::endl;
    return 0;
}

参考链接

猜你喜欢

转载自blog.csdn.net/hello_dear_you/article/details/129057574
今日推荐