1. 程式人生 > >Linux使用帶時區轉換的時間函式注意事項(負負得正)

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再去掉時區得回之前的秒數。這就是負負得正。