Bootstrap

C++ time

一、三个概念:

(1)UTC/GMT:Coorainated Universal Time:它是一个标准,最主要的世界时间标准,其以原子时秒长为基础,在时刻上尽量接近于格林尼治平时,也即格林威治标准时间(Greenwich Mean Time,GMT),在大多数场合,UTC与GMT等同(只是GMT不再由科学界精确定义)。
:为描述方便,本文中将UTC与GMT等同。

(2)Local time:指相对于UTC/GMT时间的本地时间(时区转换)。比如,中国内地的时间与UTC的时差为+8,也就是UTC+8。美国是UTC-5。

(3)Calendar time:日历时间,是用“从一个标准时间点到此时的时间经过的秒数”来表示的时间。在计算机中是相对于时间点:1970年1月1日,来算的。

二、主要数据类型、结构及函数头文件:<ctime> (或者 time.h)
(1)types:

time_t:time type,通常为整型值,表示自1970年1月1日00:00到现在所经过的秒数。
typedef long time_t

struct tm:time structure,该结构体包含了日历时间和日期,其中各成员详细信息如下:

1,tm_year是指自1900年后的个数,故要得出真正的年份,还有加上1900(即tm_year + 1900)。2,tm_isdst指夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。但中国不实行夏令时,即此处应该0.
(2)functions:(以下只挑选了几个有代表性的函数为的是理清思路,更多函数可参考C++手册)

函数名:time
原型:time_t  time (time_t*  timer):
功能:获取当前的日历时间。若 timer 为NULL,则返回日历时间;若timer非NULL则将获取的日历时间存于timer中。

函数名:gmtime:
原型:struct tm*  gmtime (const time_t*  timer);
功能:将time_t类型的日历时间转换为 tm 结构的UTC(GMT)时间。

函数名:localtime
原型:struct tm*  localtime (const  time_t*  timer);
功能:将time_t类型的日历时间转换为 tm 结构的 Local time(本地时间)。

函数名:ctime
原型:char*  ctime (const  time_t*  timer);
功能:将time_t类型的日历时间转换为适合人们阅读(human-readable)的字符串格式的时间。

函数名:mktime
原型:time_t  mktime (const struct tm*  timeptr);
功能:将tm结构体类型的时间转换为 time_t类型的时间

函数名:asctime
原型:char*  asctime (const struct tm*  timeptr);
功能:将tm结构体类型的时间转换为适合人们阅读的字符串格式的时间。


综上,可以发现时间的表示形式不外乎三种:time_t、strcut tm以及string(char*).


三、例子

#include<iostream>
#include<string>
#include<ctime>
using namespace std;
int main()
{
     time_t rawtime = time(NULL);
     cout<<"rawtime:"<<rawtime<<endl;
     struct tm localtm = *localtime(&rawtime);
     struct tm UTCtm = *gmtime(&rawtime);
     cout<<"----------UTC time VS local time-----------"<<endl; 
     cout<<"tm_sec:   "<<localtm.tm_sec<<"          "<<UTCtm.tm_sec<<endl;
     cout<<"tm_min:   "<<localtm.tm_min<<"          "<<UTCtm.tm_min<<endl;
     cout<<"tm_hour:  "<<localtm.tm_hour<<"          "<<UTCtm.tm_hour<<endl;
	 cout<<"tm_mday:  "<<localtm.tm_mday<<"          "<<UTCtm.tm_mday<<endl;
     cout<<"tm_mon:   "<<localtm.tm_mon+1<<"          "<<UTCtm.tm_mon+1<<endl;
	 cout<<"tm_year:  "<<localtm.tm_year+1900<<"        "<<UTCtm.tm_year+1900<<endl;
     cout<<"tm_yday:  "<<localtm.tm_yday<<"         "<<UTCtm.tm_yday<<endl;
     cout<<"tm_isdst: "<<localtm.tm_isdst<<"           "<<UTCtm.tm_isdst<<endl;
     string cstime = asctime(&localtm);
     cout<<"string time:"<<cstime<<endl;
     time_t makeLocal = mktime(&localtm);
     cout<<"mktime (hours)local: "<<makeLocal/3600<<endl;
     time_t makeUTC = mktime(&UTCtm);
     cout<<"mktime (hours)UTC: "<<makeUTC/3600<<endl;
     return 0;
}

输出结果


注:由结果可知,local time(UTC+8)比UTC要大8个小时,而其他member均一样。

四、关于localtime的返回值的内存问题:

在执行localtime(或者是gmtime或者是mktime等)时,有一个小问题。注意到代码中的:

struct tm localtm =*localtime(&rawtime);
struct tm UTCtm = *gmtime(&rawtime);

当我们写成:
struct tm* localtmptr = localtime(&rawtime);
struct tm*UTCtmptr = gmtime(&rawtime);
则会出现问题,运行结果会发现又localtime和gmtime得出的时间值时一样的,它们之间并不相差8个小时。

为什么会这样呢?

通过man localtime命令,可以发现一些细节:


即 localtime(或者是gmtime或者是mktime)等,它们的返回值都是指向一个共享的静态存储区,该块内存可能会被后面的时间函数重写。故 若有时间函数连续出现时,应该直接返回该内存,而不是指向该内存的指针。
这样一来,每一个时间函数都会从静态存储区把自己的时间拷贝出来,存入自己的内存区。

;