当通过time函数获取系统时间的时候,time_t得到的是一个计算机系统时间是按照UTC时间计算的从1970年1月1日0时开始的秒数。因此,在当前某一时刻,无论运行的计算机在地球哪个时区,其通过time(NULL)函数获得的time_t的值都是相同的。
将time_t转换为可读的本地时间格式用localtime函数。
将time_t转换为可读的UTC时间格式用gmtime函数。
既然计算机的time_t使用统一的UTC时间基准计时。在struct tm对象到time_t时,却只提供了一个转换函数:mktime函数。但是它却是把本地时间格式的struct tm对象转到time_t(注意,time_t只有UTC格式)。为何没有UTC时间格式的转换函数?(本文无答案)。
我们通过下面的程序验证:
#include
#include
time_t tp = 0;
time_t tn = 0;
struct tm *tmp = 0;
time(&tp);
printf("time():%d\n",tp);
tmp = localtime(&tp);
tn = mktime(tmp);
printf("time()->localtime()->mktime(): %d\n", tn);
tmp = gmtime(&tp);
tn = mktime(tmp);
printf("time()->gmtime()->mktime(): %d\n", tn);
运行结果:
time(): 1659079214
time()->localtime()->mktime(): 1659079214
time()->gmtime()->mktime(): 1659050414
查阅文档得知,mktime函数是将struct tm对象作为本地时间转换为time_t。
参考:
当我们在处理涉及全球时间的程序时,分2种情况(此处仅讨论Windows和Linux):
time_t的值是从time(NULL)函数或者已知为本地系统时间而来,则需要用gmtime函数来转换为struct tm对象。time_t的值是从其他已知的UTC时间而来,则需要用localtime函数来转换为struct tm对象。如果需要将struct tm格式的时间转换为time_t,而struct tm对象如果不是本地时间,则需要在mktime执行以后,加上一个本地时间到UTC时间的偏移秒数。
如果需要处理其他时区的时间,可以使用boost的local_time。他可以获得不同时区与UTC的时间差,还可以在不同时区直接用boost::local_date_time::local_time_in (boost::local_time::time_zone_ptr)函数从一个时区的时间转换为另一个时区的时间。并且可以处理烦人的冬夏令时。
#include "boost/date_time/local_time/local_time.hpp"
boost::local_time::tz_database tz_db;
const char* filename = "date_time_zonespec.csv";
tz_db.load_from_file(filename);
const char* region = "America/New_York";
boost::local_time::time_zone_ptr tz = tz_db.time_zone_from_region(region);
boost::posix_time::ptime t(boost::posix_time::second_clock::universal_time());
boost::local_time::local_date_time dt(t, tz);
auto t1 = dt.local_time();
auto td = t1 - t; // 这是指定时区和UTC时区相差的秒数
参考:
https://www.boost.org/doc/libs/1_78_0/doc/html/date_time/examples.html