(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设置时区
// 设置程序使用时区0
_putenv_s("TZ", "GMT-0");
_tzset();
// gmtime与localtime就会一致了, ctime展示出的也是设定timezone=0的时间了
struct tm* gm = gmtime(&now);
struct tm* local = localtime(&now);
printf("current: %s", ctime(&now));
叙述理解
研究时间这块,跟我之前理解偏差最大的一个点是:
- 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 1970
now=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 2022
local-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)