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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章