时区,为了克服时间上的混乱,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 = %ld\n", 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 = %ld\n", mktime(&result_localtime));
//错误值示范,本身是UTC,再减时区结果是错误的
printf("mktime localtime to utc = %ld\n", 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

可见最后一行时间打印是个错误值。
---------------------
作者:YangXX_HZ
来源:CSDN
原文:https://blog.csdn.net/u010507799/article/details/52288190
版权声明:本文为博主原创文章,转载请附上博文链接!

测试环境:vmware 7 + Redhat5.5,系统 时间 使用UTC, 时区 为上海。 1、 函数 功能介绍 使用man gm time 或man local time 都可以的得到这几个 函数 的介绍。原型如下: struct tm *gm time (const time _t * time p); struct tm *gm time _r(const time _t * time p, struct tm *resul linux 时间 类型local time _r,struct tm *phttp://blog.sina.com.cn/s/blog_9b0604b4010130tr.html头文件#include 函数 功能介绍 使用man gm time 或man local time 都可以的得到这几个 函数 的介绍。原型如下: struct tm *gm time (const time _t * time p); struct tm *gm time _r(const time _t * time p, struct tm *result); struct tm *local time (const time _t * time p); struct tm *local time _r(const time _t * time p, struct tm *res 造成这个现象的原因: local time _r不会使用系统 time zone设定全局变量 tzname, time zone 和daylight的值,这三个变量被用来校正格林威治(UTC) 时间 为本地 时间 。当系统 time zone在进程周... 在linux下用local time _r()获取的 时间 比实际 时间 差八个小时,这个一般是因为 时区 设置导致的,我们可以在 /etc/profile 中设置 时区 设置为CST 时区 ,然后source /etc/profile export TZ='CST-8' 关于 时区 的详解可以参考:https://www.douban.com/note/147740972/ 2、 time _t: time _t表示的 时间 (日历 时间 )是从一个 时间 点(例如:1970年1月1日0时0分0秒)到此时的秒数。 3、tm:在标准C/C++中,我们可通过tm(实际上是一种数据结构)结构来获得日期和 时间 ,tm结构在 time .h中的定义如下: struct tm {   int tm_sec; /* 秒,取值区间为[0,59] */   int tm_min; /* 分,取值区间为[0,59] */