时区,为了克服时间上的混乱,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
上一篇
下一篇