时间时区概念及常用时间函数

时区,为了克服时间上的混乱,1884年在华盛顿召开的一次国际经度会议(又称国际子午线会议 )上,规定将全球划分为24个时区(东、西各12个时区)。规定英国(格林尼治天文台旧址)为中时区(零时区)、东1-12区,西1-12区,每个时区横跨经度15度,时间正好是1小时。最后的东、西第12区各跨经度7.5度,以东、西经180度为界。每个时区的中央经线上的时间就是这个时区内统一采用的时间,称为区时,相邻两个时区的时间相差1小时。

硬件时钟(又称实时时钟,也就是RTC),实时时钟为操作系统提供了一个可靠的时间,并且在断电的情况下,RTC实时时钟也可以通过电池供电,一直运行下去,用来保存和同步计算机操作系统时间。RTC通过STRB/LDRB这两个ARM指令向CPU传送8位数据(BCD码)。数据包括秒,分,小时,星期,天,月和年。RTC实时时钟依靠一个外部的石英晶体,产生周期性的脉冲信号,每一个信号到来时,计数器就加1,通过这种方式,完成计时功能。

系统时钟,操作系统认知的时间,包括时区信息和UTC时间(unix时戳均使用1970年1月1日0时0分0秒到目前的UTC秒数)两部分,时区信息保存在/etc/localtime文件中,一般由/usr/share/zoneinfo/目录下的时区文件拷贝或链接而来(该目录包含所有支持的时区文件,修改时区其实是替换/etc/localtime文件,而不是直接修改该文件内容)。UTC时间是UNIX系统所使用的标准时间,不同地区的人使用时显示的本地时间由UTC+时区而来(也可以说所有Unix/linux操作系统的系统时间都相同,1970年1月1日0时0分0秒到目前的UTC秒数)。

了解以上概念我们知道,计算机系统一般包括三个重要的时间(也是容易搞混的时间,通常我们所说的计算机时间应该指的是本地时间,用户在第一次使用设备时需要选择时所在区),分别为硬件rtc时间,系统utc时间和本地local时间。三者有以下关系:

硬件rtc时间是在关机或掉电状态能够继续保存的,所以为主导地位,其他时间都可以由该时间计算得来(系统时间在操作系统运行起来后被rtc同步),rtc保存的时间可以有两种,一是utc时间,二是local时间,以东八区为例:

当rtc时间为utc时间:系统utc时间 = rtc时间, 本地local时间 = rtc时间 + 8小时;

当rtc时间为local时间:系统utc时间 = rtc时间 – 8小时, 本地local时间 = rtc时间 ;

两种设置都可以,没有明确规定,不过一般Windows和Linux都默认rtc保存local本地时间。

linux时间结构体定义:

struct tm

{

int tm_sec;

int tm_min;

int tm_hour;

int tm_mday;

int tm_mon;

int tm_year;

int tm_wday;

int tm_yday;

int tm_isdst;

};

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 日光节约时间的旗标

timeval结构定义为:

struct timeval

{

long tv_sec; /*秒*/

long tv_usec; /*微秒*/

};

timezone结构定义为:

struct timezone

{

int tz_minuteswest; /*和Greenwich 时间差了多少分钟*/

int tz_dsttime; /*日光节约时间的状态*/

};

linux常用时间函数介绍:

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返回的是一个structtm*,这个指针指向一个静态的内存,这块区域是会经常被改动的。你刚调用gmtime(),执行了其他几条命令,然后想使用刚才gmtime()得到struct tm,会发现内容不对了,所以很危险,使用gmtime_r后就没有问题,gmtime_r会将结果保存到你传入的内存中。

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);

将已经根据时区信息计算好的structtm转换成time_t的秒数。计算出的秒数是以UTC时间为标准的,跟调用time()得到的秒数是同一个概念。

5、gettimeofday(获取当前时间,UTC时间,精度微妙,无时区转换)

#include <sys/time.h>

#include <unistd.h>

int gettimeofday(struct timeval *tv, struct timezone *tz);

这个timeval是相对time_t更精确的时间,包含了微妙数。tv_usec最大为999999,再加1则为1秒,超过1秒就进位到tv_sec。timezone一般传入NULL,linux没有处理timezone中的tz_dsttime信息,所以在编程时不要从这里获取时区信息。

6、ctime(将时间转换为本地时间字符串, 有时区转换)

#include<time.h>

char *ctime(const time_t *timep);

7、asctime(将时间转换为字符串, 无时区转换)

#include<time.h>

char *ctime(const time_t *timep);

char * asctime(const struct tm * timeptr);

代码示例:

#include <stdio.h>

#include <time.h>

#include <sys/time.h>

int main(int argc, char* argv[])

{

time_t timep;

time(&timep);//获取UTC秒数

//ctime转换为本地时间字符串形式,有时区转换

printf("timep = %ld, local time = %s", timep, ctime(&timep));

struct timeval tv;

gettimeofday(&tv, NULL);//获取微秒精度时间结构,UTC无时区转换

printf("tv.sec = %ld, tv.usec = %ldn", tv.tv_sec, tv.tv_usec);

struct tm result_gmtime, result_localtime;

gmtime_r(&timep, &result_gmtime);//获取UTC时间结构,无时区转换

localtime_r(&timep, &result_localtime);//获取本地时间结构,有时区转换

//时间结构转换为字符串显示,无时区转换

printf("gmtime_r = %s", asctime(&result_gmtime));

printf("localtime_r = %s", asctime(&result_localtime));

//mktime将本地时间转换为UTC秒数,有时区转换

printf("mktime localtime to utc = %ldn", mktime(&result_localtime));

//错误值示范,本身是UTC,再减时区结果是错误的

printf("mktime localtime to utc = %ldn", mktime(&result_gmtime));

return 0;

}

执行结果:

timep = 1471929196, local time = Tue Aug 23 13:13:16 2016

tv.sec = 1471929196, tv.usec = 146952

gmtime_r = Tue Aug 23 05:13:16 2016

localtime_r = Tue Aug 23 13:13:16 2016

mktime localtime to utc = 1471929196

mktime localtime to utc = 1471900396

可见最后一行时间打印是个错误值。

————————————————

版权声明:本文为CSDN博主「Study杨」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:时间时区概念及常用时间函数_Study杨的博客-CSDN博客_gmtime_r

发表回复

相关推荐

被这么多人误解的SOE咖啡竟然是这样!

开门见山 SOE:通常是三个英文单词的首字母缩写。 在百度百科中搜索“SOE",分别有如下解释: “Spirit Of Enterprise” ...

· 22秒前

独龙纹面女——亲眼见证即将消逝的纹面遗迹

她走过的小道鲜花盛开 她织出的彩虹连到天边 她微笑的地方没有悲伤 她劳作的土地没有贫瘠 你是那太阳温暖人间 你是那月亮点 ...

· 26秒前

从年薪4万到21万,积云教育是如何拯救初中辍学农村娃的?

如今这个社会,找工作时学历就是块敲门砖,如果你连这块敲门砖都没有,想混进某个圈子,基本没戏!等待你的不是餐厅服务员就 ...

· 1分钟前

逆天配角王晙:指挥两千唐军,打败十万吐蕃

本文系时拾史事独家原创稿件,未经授权严禁转载

· 1分钟前

巴黎水那么难喝,凭什么卖那么贵???

哈喽大家好,我是小韦! 今天我们来讲一讲——水。 如果问你一个问题“什么水和荔枝一起喝会有香槟得感觉?” 如果看过亦舒小说 ...

· 2分钟前