【c/c++】linux时间获取与时间转换函数总结

1. 序言

程序中常需要记录时间戳或者计算模块耗时,在此对时间函数及应用场景做一个总结

2. 有哪些函数

  • 获取时间

    clock, time, gettimeofday, chrono库时间函数

  • 时间格式转换

    ctime, localtime, gmtime, asctime, mktime, strftime

  • 其他

    计算时间差:difftime
    时间转换线程安全函数:ctime_r, localtime_r, asctime_r, gmtime_r

3. 选用场景

  • 获取时间的函数
函数 功能描述 选用场景
clock 从程序启动到此函数调用消耗的处理器时间,精确到微秒 统计程序内模块处理器耗时
time 当前的UTC时间,精确到 统计过去了多少秒
gettimeofday 当前的UTC时间,精确到微秒 获取当前较精确时间戳
chrono::system_clock 当前的UTC时间,精确到微秒 获取当前较精确时间戳,与NTP时间有关
chrono::steady_clock 当前的UTC时间,精确到纳秒 获取当前稳定的高精确时间戳
chrono::high_resoluction_clock 当前的UTC时间,精确到纳秒 获取当前最高精确时间戳
  • 时间转换函数
函数 功能描述 选用场景
localtime 将UTC秒数转换为本地时间(tm格式) 可按年月日时分秒显示
gmtime 将UTC秒数转换为本地时间(tm格式) 可按年月日时分秒显示
ctime 将UTC秒数转换为本地时间(字符串格式) 星期 月 日 时分秒 年
asctime 将tm时间转换为UTC秒数(字符串形式) 星期 月 日 时分秒 年
mktime 将tm格式的时间转换为UTC秒数 统计过去了多少秒
strftime 将tm格式的时间转换为指定格式 时间转换为特定格式
  • 其他时间函数
函数 功能描述 选用场景
difftime 统计两个时间相差的秒数 计算两个UTC时间相差多少秒
ctime_r, localtime_r, asctime_r, gmtime_r 当ctime, localtime, asctime, gmtime对应的线程安全函数 线程安全的时间转换函数

ctime/asctime两者传入的参数结构不同,见4. 详细解析
 

4. 详细解析

4.1 时间获取函数

1. clock函数
头文件 #include
函数原型 clock_t clock(void)
函数说明 typedef long clock_t;获取从程序启动到此函数调用消耗的处理器时间,精确到毫秒
返回值 时间可用返回时间,否则返回-1
  • 使用实例
#include 
#include 
#include 
#include 	// 或 #include 
#include 
 
// function耗时工作
void function()
{
    double d = 0;
    for (int n = 0; n < 10000; ++n)
       for (int m = 0; m < 10000; ++m)
           d += d * n * m;
}
 
int main()
{
    std::clock_t clock_start = std::clock();

    auto utc_start = std::chrono::high_resolution_clock::now();

    std::thread t1(function);
    std::thread t2(function);
    t1.join();
    t2.join();
    
    std::clock_t clock_end = std::clock();
    
    auto utc_end = std::chrono::high_resolution_clock::now();
 
    std::cout << std::fixed << std::setprecision(2) << "CPU耗时: "
              << (clock_end - clock_start) / 1000.0 << " ms\n"
              << "UTC耗时: "
              << std::chrono::duration<double, std::milli>(utc_end - utc_start).count()
              << " ms\n";
}
# 编译
g++ -o main main.cpp -lpthread
# 运行
./main
2. time函数
头文件 #include
函数原型 time_t time(time_t* t)
函数说明 typedef long time_t; 返回UTC时间,精确到
返回值 成功返回秒数,失败返回 (time_t)-1
  • 使用实例
#include 
#include 
 
using namespace std;

int main()
{
    time_t seconds = time((time_t*)NULL);
    std::cout << seconds << std::endl;
    return 0;
}
# 编译运行
g++ -o main main.cpp
3. gettimeofday函数
头文件 #include #include
函数原型 int gettimeofday (struct timeval * tv , struct timezone * tz)
函数说明 时间放到tv结构,时区放到tz所指结构。tz一般使用nullptr
返回值 成功返回0, 失败返回-1
  • 使用实例
#include
#include
#include 

using namespace std;

int main()
{
    struct timeval tv;
    struct timezone tz;
    
    gettimeofday (&tv , &tz);
    //gettimeofday (&tv , nullptr);
    
    std::cout << "\n tv.sec = " << tv.tv_sec << ", tv.usec = " << tv.tv_usec << std::endl;
    
    std::cout << "\n tz.minuteswest = " << tz.tz_minuteswest << ", tz.tz_dsttime = " << tz.tz_dsttime << std::endl;
    return 0;
}
4. chrono库时间函数
头文件 #include
函数原型 std::chrono::system_clock()::成员函数
函数说明 常用::now()获取当前UTC时间,用::is_steady判断是否为稳定时钟
chrono三个时间函数的区别
system_clock() 系统时钟,精确到微秒。不稳定,NTP时间变化会跟着变。
steady_clock() 稳定时钟,精确到纳秒。适合于记录程序耗时
high_resolution_clock() 高精度时钟,精确到纳秒。相当于steady_clock的高精度版本
  • 三个函数均是c11才引入的
  • system_clock还有两个成员函数 to_time_t和from_time_t
  • system_clock和gettimeofday精度有微秒级差异,不能混用!会造成时间错乱
  • 使用实例
#include 
#include 
#include 

using namespace std;
using namespace chrono;

int main()
{
  // 是否为稳定时钟
  std::cout << "system_clock::is_steady: " << std::boolalpha << system_clock::is_steady << std::endl;
  std::cout << "steady_clock::is_steady: " << std::boolalpha << steady_clock::is_steady << std::endl;
  std::cout << "high_resolution_clock::is_steady: " << std::boolalpha << high_resolution_clock::is_steady << std::endl;
  
  auto start = system_clock::now();

  int i = 0;
  while (i < 10000)
    i++;

  duration<double> timeGap = system_clock::now() - start;
  std::cout << "timeGap: " << duration_cast<microseconds>(timeGap).count() << endl;
  
  std::time_t timeT = system_clock::to_time_t(system_clock::now()); 
  std::cout << asctime(gmtime(&timeT)) << std::endl;
  std::cout << asctime(localtime(&timeT)) << std::endl;

  duration<double> timeGap1 = system_clock::now() - system_clock::from_time_t(timeT); 
  std::cout << "timeGap: " << duration_cast<microseconds>(timeGap1).count() << std::endl;

  return 0;
}

// to_time_t: static std::time_t to_time_t( const time_point& t ) noexcept;
// from_time_t: static std::chrono::system_clock::time_point from_time_t( std::time_t t ) noexcept;

4.2 时间转换函数

1. ctime函数
头文件 #include
函数原型 char* ctime(const time_t *time);
函数说明 将time_t格式时间以字符串形式返回
返回值 成功返回0, 失败返回-1
  • 使用实例
#include
#include
using namespace std;

int main()
{
    time_t timep;
    time(&timep);
    std::cout << ctime(&timep) << std::endl;
    return 0;
}
2. localtime函数
头文件 #include
函数原型 struct tm* localtime(const time_t * timep);
函数说明 将time_t格式时间以tm格式返回,转换为为当地时区
返回值 返回tm结构代表当地时间
  • 使用实例
#include 
#include 
#include 
using namespace std;

int main()
{
	string wday[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	
	time_t timep;
	time(&timep);

	struct tm *localTime = localtime(&timep); /*取得当地时间*/

	std::cout << 1900 + localTime->tm_year << 1 + localTime->tm_mon << localTime->tm_mday;

	std::cout << " " << wday[localTime->tm_wday] << " " << localTime->tm_hour << " " << localTime->tm_min << " " << localTime->tm_sec << std::endl;

	return 0;
}

3. gmtime函数
头文件 #include
函数原型 struct tm* gmtime(const time_t*timep);
函数说明 将tm格式时间转换为真实世界时间,中间转换使用
返回值 返回tm格式时间为UTC时间
  • 使用实例
#include 
#include 
#include 
using namespace std;

int main()
{
	string wday[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
	
	time_t timep;
	time(&timep);

	struct tm *gmTime = gmtime(&timep); /*取得当地时间*/

	std::cout << 1900 + gmTime->tm_year << 1 + gmTime->tm_mon << gmTime->tm_mday;

	std::cout << " " << wday[gmTime->tm_wday] << " " << gmTime->tm_hour << " " << gmTime->tm_min << " " << gmTime->tm_sec << std::endl;

	return 0;
}
  • localtime和gmtime区别:时区。比如gmtime是10:00, 中国时间localtime就是18:00 (GMT+8)
4. asctime函数
头文件 #include
函数原型 char* asctime(const struct tm * timeptr);
函数说明 将tm格式时间转换为当地时间,以字符串形式返回
返回值 返回字符串表示当地时间
  • 使用实例
#include 
#include 
using namespace std;

int main()
{
	time_t timep;
	time(&timep);

	// gmtime将time_t格式时间转换为tm格式
	// asctime将tm格式时间转换为字符串形式
	std::cout << asctime(gmtime(&timep)) << std::endl;

	return 0;
}
5. mktime函数
头文件 #include
函数原型 time_t mktime(strcut tm* timeptr);/
函数说明 将tm格式时间转换为time_t时间(UTC秒数)
返回值 UTC时间秒数
  • 使用实例
#include 
#include 
using namespace std;

int main()
{
	time_t timep;
	time(&timep);
	std::cout << "time(): " << timep << std::endl;

	struct tm *localTime = localtime(&timep);
	timep = mktime(localTime);

	std::cout << "time() -> localTime() -> mktime(): " << timep << std::endl;
	return 0;
}
  • 执行结果
time(): 1651132717
time() -> localTime() -> mktime(): 1651132717
6. strftime函数
头文件 #include
函数原型 size_t strftime(char *strDest, size_t maxSize, const char *format, const struct tm *timeptr);
函数说明 将tm格式时间转换为自定义时间格式。
参数 strDest: 存放格式化后的字符串; maxSize: 最多可以输出的字符数; format: 格式化; timeptr: 要转换的tm格式时间
返回值 UTC时间秒数
  • 使用实例
#include 
#include 
#include 
 
int main(void)
{
    char buff[70];
    struct tm tmTime;
    tmTime.tm_year = 122;
    tmTime.tm_mon = 3;
    tmTime.tm_mday = 28;
    tmTime.tm_hour = 16;
    tmTime.tm_min = 12;
    tmTime.tm_sec = 21;

    if (strftime(buff, sizeof buff, "%A %c", &tmTime)) {
		std::cout << buff << std::endl;
    } else {
		std::cout << "strftime failed" << std::endl;
    }
 
    setlocale(LC_TIME, "ja_JP");
 
    if (strftime(buff, sizeof buff, "%A %c", &tmTime)) {
		std::cout << buff << std::endl;
    } else {
		std::cout << "strftime failed" << std::endl;    
    }
    return 0;
}

4.3 时间差计算函数

difftime函数
头文件 #include
函数原型 double difftime(time_t, time_t)
函数说明 计算两个UTC时间的差值
返回值 时间差,精确到秒
  • 使用实例
#include 
#include 
#include 
using namespace std;

int main(void)
{
	time_t start, ends;
	clock_t cstart, cends;
	
	start = time(NULL);
	
	cstart = clock();
	
	sleep(3);

	ends = time(NULL);

	cends = clock();
	
	cout << "时间差:" << difftime(ends, start) << endl;
	cout << "Clock时间差:" << cends - cstart << endl;
	
	return 0;
}

4.4 线程安全的时间转换函数

  • 以下时间转换函数是线程安全的,多线程中应用对应的xxx_r函数代替xxx函数
// ctime_r: 将time_t时间转换为字符串形式
char *ctime_r(const time_t *timep, char *buf);

// localtime_r: 将time_t时间转换为当地时间,tm格式
struct tm *localtime_r(const time_t *timep, struct tm *result);

// asctime_r: 将tm使劲按转换为当地时间,字符串形式
char *asctime_r(const struct tm *tm, char *buf);

// gmtime_r: 将time_t时间转换为tm格式时间
struct tm *gmtime_r(const time_t *timep, struct tm *result);

 


参考文章:

C++时间获取函数
C++时间函数总结
线程安全的时间函数
C++时间函数实例
C++时间函数详细说明
chrono三个时间函数的区别

created by shuaixio, 2022.04.28

你可能感兴趣的:(C/C++,linux,c++,c,时间获取,时间转换)