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