Linux使用带时区转换的时间函数注意事项(负负得正)

linux时间结构体定义:


struct tm
{
     int    tm_sec; //代表目前秒数,正常范围为0-59,但允许至61秒
     int    tm_min; // 代表目前分数,范围0-59
     int    tm_hour; //从午夜算起的时数,范围为0-23
     int    tm_mday; //目前月份的日数,范围01-31
     int    tm_mon; // 代表目前月份,从一月算起,范围从0-11
     int    tm_year; //从1900年算起至今的年数
     int    tm_wday; //一星期的日数,从星期一算起,范围为0-6
     int    tm_yday; //从今年1月1日算起至今的天数,范围为0-365
     int    tm_isdst; //日光节约时间的旗标

};

1、time(获取当前UTC秒数,需要注意的该函数无时区转换)


#include<time.h>


time_t time(time_t *t);


这个函数应该算是最常用函数之一,返回UTC标准秒数,没有时区转换,在伦敦和上海同时调用这个函数返回值相同。


2、gmtime(获取当前时间结构,UTC时间,需要注意的是该函数无时区转换)



#include<time.h>
struct tm *gmtime(const time_t *timep);


struct   tm *gmtime_r(const time_t *timep, struct tm *result);


这两个函数意思一样,将timep这个秒数转换成以UTC时区为标准的年月日时分秒时间。
gmtime_r是线程安全的,推荐使用这个。gmtime返回的是一个struct  tm*,
这个指针指向一个静态的内存,这块区域是会经常被改动的。你刚调用gmtime(),
执行了其他几条命令,然后想使用刚才gmtime()得到struct  tm,会发现内容不对了,
所以很危险,使用gmtime_r后就没有问题,gmtime_r会将结果保存到你传入的内存中。


获得的struct tm结构体,注意该结构体的定义,如果要打印年份要+1900,月份+1.


3、localtime(获取当前时间结构,本地时间,但是有时区转换)


#include<time.h>


struct tm *localtime(const time_t * timep);


struct tm *localtime_r(const time_t *timep, struct tm *result);




这两个函数意思也一样,会根据时区信息得到本地时间,同样建议使用localtime_r版本。


4、mktime(将时间结构转换为UTC秒数,但是有时区转换)


#include<time.h>
time_t mktime(struct tm *tm);


将已经根据时区信息计算好的struct  tm转换成time_t的秒数。计算出的秒数是以UTC时间为标准的,跟调用time()得到的秒数是同一个概念。


回到文章的题目,为什么说负负得正呢,
比如utc时间秒数1519741060,当我用

gmtime_r

 转换为struct   tm t结构时,再用mktime函数转换为秒数时,发现时间被减了8个小时,也就是8时区,这是因为mktime认为你的结构带了时区。


因此,如果想用秒数转换为tm结构之后,再从tm结构转换秒数的正确方法应该是使用localtime_r转为有时区的tm,mktime再去掉时区得回之前的秒数。这就是负负得正。


猜你喜欢

转载自blog.csdn.net/zhouzhenhe2008/article/details/79393696