时区与time/gmtime/localtime/mktime/ctime函数联系
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
參考:https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/mktime-mktime32-mktime64?view=msvc-170
參考:https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64?view=msvc-170
參考:https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/gmtime-gmtime32-gmtime64?view=msvc-170
參考:https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/ctime-ctime32-ctime64-wctime-wctime32-wctime64?view=msvc-170
參考:https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/time-time32-time64?view=msvc-170
經常用time函數的時候,獲取了從一個1970年1月1日0時0分0秒開始的秒數計數,但是這個計數是基于當地時區時間計數,還是格林威治時間計數,自己心里還是有問號在的。
驗證測試
確認也不難,查文檔,自己測試試試看,就有了下面這些記錄了:
// 時間0值,代表的時間是什么時間呢?是1970.1.1,格林威治0:0:0,東8區是8:00:00 // 參考輸出 time0=0 Thu Jan 1 08:00:00 1970 time_t n0 = 0; printf("time0=%d %s\n", n0, ctime(&n0));// 獲取當前時間: 格林威治時間 // 參考 now=time(NULL)=1648340045 %86400=845 Sun Mar 27 08:14:05 2022 // 參考中可以看出,845是0:14:05時刻,這個時間值是格林威治的時刻,東8區需要+8小時 time_t now = time(NULL); printf("now=time(NULL)=%d %86400=%d %s", n, n%86400, ctime(&n));// gm為格林威治時間,直接使用time_t轉換即可得到tm結構 // 參考 使用now轉換格力威支時刻,顯示的是 gm.hour=0, min=14, sec=5 struct tm* gm = gmtime(&now); printf("gm.hour=%d, min=%d, sec=%d\n", gm->tm_hour, gm->tm_min, gm->tm_sec);// local為當地時間,使用time_t格林威治時間+時區偏差,生成tm結構 // 參考 使用now轉換當地時刻,顯示的是 local.hour=8, min=14, sec=5 struct tm* local = localtime(&now); printf("local.hour=%d, min=%d, sec=%d\n", local->tm_hour, local->tm_min, local->tm_sec);// mktime輸入的是localtime-tm結構,得到格林威治時間time_t // ctime展示的當地時間localtime串信息 // 參考 使用local轉換,顯示的是 mktime=1648340045, %86400=845, Sun Mar 27 08:14:05 2022 time_t l = mktime(local); printf("mktime=%d, %86400=%d, %s", l, l%86400, ctime(&l));// localtime與gmtime兩者關系: 例如 localtime北京時間 = gmtime格林威治時間 +8小時如果想做時區自動轉換也是可以的:
例如當前計算機采用的東八區時間,想使用timezone-0作為程序的時區設置
通過:linux版本使用tzset、windows版本使用_tzset設置時區
敘述理解
研究時間這塊,跟我之前理解偏差最大的一個點是:
- time(NULL)總是返回的是當前格林威治時間,不論系統/程序采用的哪個時區;
- 正常使用的情況下:time_t上的存儲值總是描述格林威治時間;
- tm結構存儲值有時用來描述格林威治時間gmtime,有時用來描述當地時間localtime-當前時區時間;
- ctime考慮了時區,輸入值要求time_t是格林威治時間,輸出來的值總是用來描述當地時間-當前時區時間;
- mktime考慮了時區,輸入的值總是要求localtime-tm結構-當前時區時間,輸出值格林威治時間;
注意:
- ctime返回的是靜態變量地址;更要注意gmtime與localtime返回的靜態變量地址是同一個,后調用的會覆蓋上次調用的值;
- tm結構上tm_year不同于time_t-從1970年1月1日開始,tm_year而是從1900年開始計數,輸出時要+1900;
- tm結構上tm_month從0開始,輸出時需要+1; tm_mday是從1開始; tm_hour, tm_min, tm_sec的范圍皆是[0, 59].
- mktime時,不需要輸入tm_wday and tm_yday。
- Windows下:_mktime64/time handles dates from midnight, January 1, 1970 to 23:59:59, December 31, 3000. if the calendar time can’t be represented, returns -1.
- Windows下:localtime/gmtime/ctime return NULL if the date passed to the function is Before midnight, January 1, 1970.
測試程序與輸出
測試程序
#include <stdio.h> #include <time.h>int main(){time_t n0 = 0;printf("time0=%d %s\n", n0, ctime(&n0));time_t n = time(NULL);printf("now=time(NULL)=%d %86400=%d %s", n, n%86400, ctime(&n));struct tm* gm = gmtime(&n);printf("gm.hour=%d, min=%d, sec=%d\n", gm->tm_hour, gm->tm_min, gm->tm_sec);struct tm* local = localtime(&n);printf("local.hour=%d, min=%d, sec=%d\n", local->tm_hour, local->tm_min, local->tm_sec);time_t l = mktime(local);printf("mktime=%d, %86400=%d, %s\n", l, l%86400, ctime(&l));struct tm t;t.tm_year = 70;t.tm_mon = 1;t.tm_mday = 1; // 注: windows下mktime不支持東8區取1970.1.1號8點前時間;linux是可以的;windows下可以取往后延一天的0點時間值。t.tm_hour = 0;t.tm_min = 0;t.tm_sec = 0;time_t curr = mktime(&t);printf("local-1970.1.1=%d %86400=%d %s\n", curr, curr % 86400, ctime(&curr));printf("(now-local@1970.1.1)%86400 = %d\n", (n - curr) % 86400);return 0; }輸出
time0=0 Thu Jan 1 08:00:00 1970now=time(NULL)=1648340045 %86400=845 Sun Mar 27 08:14:05 2022 gm.hour=0, min=14, sec=5 local.hour=8, min=14, sec=5 mktime=1648340045, %86400=845, Sun Mar 27 08:14:05 2022local-1970.1.1=-28800 %86400=-28800 Thu Jan 1 00:00:00 1970(now-local@1970.1.1)%86400 = 29645(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
總結
以上是生活随笔為你收集整理的时区与time/gmtime/localtime/mktime/ctime函数联系的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 典型数据库架构设计
- 下一篇: java多线程实现的几种方式