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