时间处理时实际项目中经常碰到的问题,这里介绍最常用的时间处理函数。
首先介绍基本的时间概念。时间一般分为两种,一种是本地时间(Local Time),一种是协调世界时间(Coordinated Universal Time ,UTC),也就是传说中的格林威治时间。本地时间与UTC时间之间的差即为时差,比如,北京时间(东八区)比UTC时间晚8个小时。
C运行库中处理时间的函数主要是这四个:
[cpp]view plaincopy print? time_ttime(time_t*timer);time_t time(time_t *timer);
time_t类型为32位或64位整型,具体类型由编译系统决定。此函数用来获得从1970年1月1日子夜(这个时刻在不同的CRT实现中可能会不一样)到当前时刻以来所流逝的时间,以秒为单位。这个时间差叫做日历时间(Calendar Time )。
这是当然让我困惑的地方:这个特殊的时刻——1970年1月1日零时零分零秒——是指本地时间呢,还是UTC时间呢?我认为是本地时间,也就是各个时区自己的1970年1月1日零时零分零秒。可以设想这样一种情况,如果全球24时区各有一台电脑,都依次在自己所在时区的本地时间1970年1月1日零时1分零秒调用time函数,那么返回值都是60。注意,这里是依次调用(事实上是每隔1小时),而不是想象中的同时调用,这是因为相邻时区的同一本地时间,总是相差1小时。
当然,time_t型的时间方便计算机处理,但普通用户无法理解这种数字。所以我们通常需要将time_t型时间转换成我们平常所见的年月日形式。CRT中为此定义了tm结构。
[cpp]view plaincopy print? structtm{inttm_sec;/*secondsaftertheminute-[0,59]*/inttm_min;/*minutesafterthehour-[0,59]*/inttm_hour;/*hourssincemidnight-[0,23]*/inttm_mday;/*dayofthemonth-[1,31]*/inttm_mon;/*monthssinceJanuary-[0,11]*/inttm_year;/*yearssince1900*/inttm_wday;/*dayssinceSunday-[0,6]*/inttm_yday;/*dayssinceJanuary1-[0,365]*/inttm_isdst;/*daylightsavingstimeflag*/};struct tm {int tm_sec;/* seconds after the minute - [0,59] */int tm_min;/* minutes after the hour - [0,59] */int tm_hour; /* hours since midnight - [0,23] */int tm_mday; /* day of the month - [1,31] */int tm_mon;/* months since January - [0,11] */int tm_year; /* years since 1900 */int tm_wday; /* days since Sunday - [0,6] */int tm_yday; /* days since January 1 - [0,365] */int tm_isdst; /* daylight savings time flag */};
注释中已详细解释了各个字段的用法。显然这个结构中的字段对用户更有意义。我们通常用localtime_s函数将time_t时间转换为tm时间。
[cpp]view plaincopy print? errno_tlocaltime_s(structtm*_tm,consttime_t*time);errno_t localtime_s(struct tm* _tm,const time_t *time);
其中第二个参数为传入的time_t时间,第一个参数为返回的tm时间。由函数名可看出,返回的tm时间表示的是本地时间。当然,我们有时候也需要获得对应的UTC时间,这时我们需要gmtime函数。
[cpp]view plaincopy print? errno_tgmtime_s(structtm*_tm,consttime_t*time);errno_t gmtime_s(struct tm* _tm,const time_t* time);
后面我们会看到两者的区别。
我们知道了如何将time_t时间转换为tm时间。同样,我们会需要将tm表示的时间转换为time_t时间。这时我们需要mktime函数。
[cpp]view plaincopy print? time_tmktime(structtm*timeptr);time_t mktime(struct tm *timeptr);
此函数返回从"特殊时刻"到参数表示的时刻之间流逝的日历时间。另外还有个很好用的特性,就是它能修正传进来的tm结构中各字段的取值范围。比如,如果你将tm.tm_mon设为1,tm.tm_day设为33,然后以其为参数调用mktime函数,此函数会将tm.tm_mon修正为2,tm.tm_day修正为2。具体用法参照MSDN。
我们来分析下面示例代码:
[cpp]view plaincopy print? #include<stdlib.h>#include<stdio.h>#include<time.h>intmain(){structtmtmLocal,tmUTC;time_ttNow;//Getcurrentcalendartimetime(&tNow);printf("TimeNowfromtime():%llu/n",tNow);//Getcurrentlocaltimelocaltime_s(&tmLocal,&tNow);printf("LocalTime(YYYY-MM-DDHH:MM:SS):%d-%d-%d%d:%d:%d/n",tmLocal.tm_year+1900,tmLocal.tm_mon,tmLocal.tm_mday,tmLocal.tm_hour,tmLocal.tm_min,tmLocal.tm_sec);//GetUTCtimecorrespondingtocurrentlocaltime,andtmLocal.tm_hour-tmUTC.tm_hour=8gmtime_s(&tmUTC,&tNow);printf("UTCTime(YYYY-MM-DDHH:MM:SS):%d-%d-%d%d:%d:%d/n",tmUTC.tm_year+1900,tmUTC.tm_mon,tmUTC.tm_mday,tmUTC.tm_hour,tmUTC.tm_min,tmUTC.tm_sec);//converttmLocaltocalendartimetNow=mktime(&tmLocal);printf("TimeNowfrommktime():%llu/n",tNow);returnEXIT_SUCCESS;}#include <stdlib.h>#include <stdio.h>#include <time.h>int main(){struct tmtmLocal, tmUTC;time_ttNow;//Get current calendar timetime(&tNow);printf("Time Now from time(): %llu/n", tNow);//Get current local timelocaltime_s(&tmLocal, &tNow); printf("Local Time(YYYY-MM-DD HH:MM:SS): %d-%d-%d %d:%d:%d/n", tmLocal.tm_year + 1900, tmLocal.tm_mon,tmLocal.tm_mday, tmLocal.tm_hour, tmLocal.tm_min, tmLocal.tm_sec);//Get UTC time corresponding to current local time, and tmLocal.tm_hour - tmUTC.tm_hour = 8gmtime_s(&tmUTC, &tNow);printf("UTC Time (YYYY-MM-DD HH:MM:SS): %d-%d-%d %d:%d:%d/n", tmUTC.tm_year + 1900, tmUTC.tm_mon,tmUTC.tm_mday, tmUTC.tm_hour, tmUTC.tm_min, tmUTC.tm_sec);//convert tmLocal to calendar timetNow = mktime(&tmLocal);printf("Time Now from mktime(): %llu/n", tNow);return EXIT_SUCCESS;}
输出结果如下:
上面代码中,11行time函数获得从"特殊时刻"到当前时刻的日历时间,如输出结果中的第一行显示的1267192581秒。
14行localtime_s函数将日历时间转换为本地tm时间,如输出结果第二行。
18行gmtime_s函数将将日历时间转换为对应的UTC的tm时间,如输出结果第三行显示。很容易看出,第二,三行输出的时间相差8小时,因为我在东八区。如果你修改自己电脑的时区(在控制面板的Date and Time中修改),再运行此程序,比较两次的运行结果,你就可以更好的理解了。
22行mktime函数将tm时间转换为日历时间,输出结果中第四行显示的结果与第一行一样,这是必须的。。。
如果觉得《CRT中的时间(time_t和tm)》对你有帮助,请点赞、收藏,并留下你的观点哦!