【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. 选用场景

  • 获取时间的函数
  • 时间转换函数
  • 其他时间函数

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

4. 详细解析

4.1 时间获取函数

使用实例

#include <iostream>
#include <iomanip>
#include <chrono>
#include <time.h>	// 或 #include <ctime>
#include <thread>
// 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

使用实列

#include <time.h>
#include <iostream>
using namespace std;
int main()
    time_t seconds = time((time_t*)NULL);
    std::cout << seconds << std::endl;
    return 0;
# 编译运行
g++ -o main main.cpp
# 编译运行
g++ -o main main.cpp

使用实例

#include<sys/time.h>
#include<unistd.h>
#include <iostream>
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;
}
  • 三个函数均是c11才引入的
  • system_clock还有两个成员函数 to_time_t和from_time_t
  • system_clock和gettimeofday精度有微秒级差异,不能混用!会造成时间错乱
  • 使用实例
#include <iostream>
#include <chrono>
#include <time.h>
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)
  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 时间转换函数

使用实例

#include<time.h>
#include<iostream>
using namespace std;
int main()
    time_t timep;
    time(&timep);
    std::cout << ctime(&timep) << std::endl;
    return 0;
}

使用实例

#include <time.h>
#include <iostream>
#include <string>
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;
}

使用实例

#include <time.h>
#include <iostream>
#include <string>
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)

使用实例

#include <time.h>
#include <iostream>
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;
}

使用实例

#include <time.h>
#include <iostream>
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

使用实例

#include <iostream>
#include <time.h>
#include <locale.h>
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 时间差计算函数

使用实例

#include <iostream>
#include <time.h>
#include <unistd.h>
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);