•  在Linux内核中,常见的时间类型有以下两种:系统时间(system time)和实时时间(real time),其实,方便理解,可以将二者分别认为是相对时间和绝对时间,同时它们分别对应于内核中的两个全局变量值:jiffies和xtime...

    1. 内核中时间的基本类型:

               在Linux内核中,常见的时间类型有以下两种:系统时间(system time)和实时时间(real time),其实,方便理解,可以将二者分别认为是相对时间和绝对时间,同时它们分别对应于内核中的两个全局变量值:jiffies和xtime。

               xtime: xtime值是cmos电路中取得的时间,一般是从某个历史时刻(1970年1月1日0时0分)开始到现在的时间,其实也就是我们操作系统上面所显示的时间,它的精度是微秒。

               jiffies:jiffies是记录从电脑开机到现在总共的时钟中断次数(拍数),它的值取决于系统的频率,单位是HZ,其倒数即表示一秒钟中断所产生的次数,在Linux 2.5内核版本之后将HZ从100提高到1000MHZ,它的精度也就是10毫秒。

               根据对上面两个全局变量值的介绍,大提升应该了解到Linux系统中系统时间与实时时间之间的区别,前者表示的是从电脑开机到现在的时间,可以通过全局变量jiffies值换算而来;而实时时间则是指我们日常生活中的日期时间,它跟UTC有着密切关系,这些将在后面章节做介绍。

     

    2. Linux time API中常见的时间结构:

    (1)time_t:它是一个长整型数据,用来表示从1970年之后到现在的秒数。一般通过time函数获取。

    (2)timeval结构:通过gettimeofday函数获取。

                struct timeval

                {

                  long tv_sec; /* seconds */

                   long tv_usec; /* microseconds */

                 };

    (3)timezone结构:通过gettimeofday函数获取。

                struct timezone

                {

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

                          int tz_dsttime; /*DST types*/

                };

               【引申】常见的DST类型如下:

                #define   DST_NONE      0    /* not on dst */

                #define   DST_USA        1    /* USA style dst */

                #define   DST_AUST       2   /* Australian style dst */

                #define   DST_WET        3    /* Western European dst */

                #define   DST_MET        4    /* Middle European dst */

                #define   DST_EET         5    /* Eastern European dst */

                #define   DST_CAN        6    /* Canada */

    (4)timespec结构:通过clock_gettime函数获取。

                struct timespec {

                time_t tv_sec;         /* seconds */

                 long   tv_nsec;        /* nanoseconds */

                };

    (5)tm结构:通常由gmtime, localtime, mktime等函数返回。

               struct tm {

                      /*

                   * the number of seconds after the minute,normally in the range

                   * 0 to 59, but can be up to 60 to allow forleap seconds

                   */

                    int tm_sec;

                    /* the number of minutes after the hour, in the range 0 to 59*/

                    int tm_min;

                     /* the number of hours past midnight, in the range 0 to 23 */

                     int tm_hour;

                     /* the day of the month, in the range 1 to 31*/

                     int tm_mday;

                     /* the number of months since January, in the range 0 to 11 */

                     int tm_mon;

                     /* thenumber of years since 1900 */

                    long tm_year;

                    /* the number of days since Sunday, in the range 0 to 6 */

                   int tm_wday;

                   /* the number of days since January 1, in the range 0 to 365 */

                  int tm_yday;

               };

     

    3. 常见的时间系统函数:

    (1) time:   #include <time.h>

          time_t time(time_t *t)

          若函数的参数为NULL,则返回从1970年1月1日0时0分0秒到现在(系统时间)所经过的秒;若参数非空,则将返回的值存在由指针t所指代的内存中。

    (2) gettimeofday: #include <sys/time.h>

          int gettimeofday(structtimeval *tv ,struct timezone *tz )

          此函数可以获取两方面的时间信息,一个是可以获取到从1970年1月1日0时0分0秒到现在(系统时间)所经过的微秒,精度相比time函数精度有所提升;另外还可以获取到系统的时区信息。

    【说明】

    ◆     gettimeofday函数成功返回0;否则返回-1,错误存储在errno中。

    ◆     tz_minuteswest值的确定问题:它表示的是与GTM之间相差的分钟数,其值应该为GMT(GMT +0)减去本地

             时区对应的时间所得到的值,以EDT(GMT -4)为例,其值为240分钟。

    ◆     在实际开发中,gettimeofday中的tz参数实际很少使用,因为各种原因,一直未能实现(所获取出来的值恒为

             0),因此,通常将此处直接写成NULL。

    ◆     对于gettimeofday函数的效率以及内部实现(系统调用实现),可参考

               http://blog.csdn.net/russell_tao/article/details/7185588中的阐述。

    ◆     与gettimeofday函数相对应的是settimeofday,它可以设置实时时间RTC。但之前必须要具有root权限。

    (3) gmtime,localtime and mktime:

               struct tm*gmtime(const time_t *timep)

               struct tm *localtime(const time_t *timep)

               time_tmktime(struct tm*tm)

               以上三个函数实现了time_t与tm结构的互换。前两者将time_t结构转换成tm结构,mktime则正好相反。

    【说明】gmtime与localtime之间的区别:

               二者均可以将time_t结构的时间值转化成真实世界所使用的日期时间表示方法(tm结构),但是,前者返回的时间值未作时区的转换,即返回的是UTC时间;而localtime函数则返回的经过了时区转换的时间值,所获取到的值才是本地的真实时间。例如,在Linux系统中运行date命令,它显示的是经过时区转换之后的时间值(通过localtime获取),而若运行“date-u”则能显示未经过时区转换的UTC时间(通过gmtime获取)。

     

    (3) strftime:  #include <time.h>

         size_tstrftime (char *s,sizetsize, const char *format,const struct tm *brokentime)

         此函数的功能是将由brokentime指针所指的时间按照format指针所指的格式输出到由s指针所指向的存储空间中,其中size是指存储空间的最大值。若返回0,则表明出现错误,所写进存储空间的结果是未定义的,若为真,则返回的是写进存储空间的字符数。

     

    (4) clock_gettime: #include <time.h>

          intclock_gettime(clockid_tclk_id,struct timespec *tp);

          此函数的功能是用来获取不同类型计时时钟的时间,其类型由clockid_t指定,常见的有:

           CLOCK_REALTIME(与实时时间对应)

           CLOCK_MONOTONIC(与系统时间对应)

    【说明】

    ◆     clock_gettime函数能将所获得的时间值精确到纳秒级别;

    ◆     函数运行成功则返回0,否则返回-1,并将错误存在errno中;

    ◆     除上面的两个时钟类型之外,还有以下两种类型:

            CLOCK_PROCESS_CPUTIME_ID和CLOCK_THREAD_CPUTIME_ID

            但是这两种时钟类型一般出现在多处理机系统(SMP)中,值得注意的是,在老版本的Linux系统中可能会出现CPU时间之间不一致的现象,这是因为不同的CPU之间没有保证时间一致性措施,导致CPU时间之间出现偏移量,在2.6.18版本之后解决了这方面的问题,使得系统启动后不同的CPU之间具有相同的时间基准点。

    ◆CLOCK_REALTIME时间可以通过settime或者settimeofday函数进行修改,或者通过NTP周期性 地纠正,此时需要用到adjtimex函数;CLOCK_MONOTONIC时间则不能通过settime或者settimeofday函数进行修改,但是同样可以通过NTP进行调整,此时同样需要用到adjtimex函数。

    对比两种时钟类型,若要在实际开发中要统计某个事件的时间,则最好是使用CLOCK_MONOTONIC,因为CLOCK_REALTIME被影响的因素太多,如手动修改,时区变化等等。

     

    4. DST以及相关的系统函数:

    (1)UTC、GMT与DST

               目前世界上常见的计时方式主要有:太阳时(MT)和原子时。GMT(格林尼治时间)的正午是指当太阳横穿格林尼治子午线时的时间,由于地球的自转呈现不规则性,并且正在缓慢减速,因此格林威治时间目前已经不再作为标准时间使用,取而代之的是协调时间时(UTC),它是由原子钟提供,它是基于标准的GMT提供的准确时间,若在不需要精确到秒的前提下,通常也将GMTUTC视作等同

               DST(daylight saving time)也称为夏令时,它是以节约能源为目的而人为规定的一种制度,它规定某段时间作为夏令时间,并在标准时间的基础上提前多长时间(通常是一个小时),同时DST还规定了规定生效的起始时间和末尾时间,详细规则会在tzset函数中介绍,值得注意的是目前只是部分国家实施了夏令时制度。

               标准时间是相对于UTC/GMT时间而言的,它在UTC/GMT之上增加了时区信息,比如中国标准时间是GMT+8,即在UTC时间上增加8个小时。   

    (2) 系统时间、标准时间以及UTC时间之间的关系:

               这节主要探讨在具体项目实现过程中,如何处理系统时间、标准时间以及UTC时间之间的关系,其中系统时间可以通过前面的系统函数获取到,它可能正处于夏令时间区域,下面这个图可以清晰地阐述三者之间的关系:

                 我们以localtime函数获取到本地系统时间为例,演示如何将其转换成UTC时间,前面已经说过,localtime所获取到的时间已经包含了时区信息,但是之前我们必须要确认目前的这个时间是否处于夏令时区域之内,若是,则还需要经过A阶段(去掉DST偏移量,通常是一个小时),若不是,只需要经历第二个阶段B,即去时区,最后转化成UTC,当然这两个阶段并没有严格的先后顺序。反过来,在具体实现中,还经常出现将UTC时间转化成本地时间的情况,比如NTP就是基于这样的原理,它从NTP server端获取统一的UTC时间,然后需要经过C(加时区)和D(加DST,如果存在或正好处于夏令时区域范围之内的话)两个阶段将其转化成本地系统时间。

               下面主要阐述第一种情况(本地系统时间——>UTC)是如何具体实现的。当然前提是我们要知道目前所在的时区,这是一切的根本。在此之前,值得说明的是,一般来讲,时区是一个固定的信息,难以想象一个国家或地区去改变时区所带来的后果,但是DST因为是人为规定的,因此可能存在着修改的情况,基于这个事实,在具体实现中,时区信息可以存储在本地,而DST信息既可以静态存储在本地,也可以通过相关的server动态获取到。我们以静态存储的方式为例来讲解具体是如何实现去时区,去DST。

               下面这个结构体存储了跟时区相关的位移量(offset)以及是否存在DST等信息,根据所在的时区信息,很容易找到系统时间与UTC时间之间的时区偏移,另外根据rule是否为-1来确定此时区是否实施了夏令时,若为-1,表明这个时区地已经实现了夏令时,则还需要经过去DST阶段,否则只需要经过去时区就可以得到UTC时间。

            struct zone zones[N_ZONES] = {

            /* offset rules */

            { -43200, -1 }, /* (GMT-12:00)International Date Line West */

            { -39600, -1 }, /* (GMT-11:00) Midway Island,Samoa */

            { -36000, -1 }, /* (GMT-10:00) Hawaii */

            { -32400,  0 }, /* (GMT-09:00) Alaska */

            { -28800,  0 }, /* (GMT-08:00) Pacific Time, Tijuana */

            { -25200, -1 }, /* (GMT-07:00) Arizona, Mazatlan*/

            { -25200, 13 }, /* (GMT-07:00) Chihuahua, La Paz*/

            { -25200,  0 }, /* (GMT-07:00) Mountain Time */

            { -21600,  0 }, /* (GMT-06:00) Central America */

            { -21600,  0 }, /* (GMT-06:00) Central Time */

            { -21600, 13 }, /* (GMT-06:00) Guadalajara, MexicoCity, Monterrey*/

            { -21600, -1 }, /* (GMT-06:00) Saskatchewan */

            { -18000, -1 }, /* (GMT-05:00) Bogota, Lima, Quito */

            { -18000,  0 }, /* (GMT-05:00) Eastern Time */

            { -18000, -1 }, /* (GMT-05:00) Indiana */

            { -14400,  0 }, /* (GMT-04:00) Atlantic Time */

            {-14400, -1 }, /* (GMT-04:00) Caracas, La Paz */

            { -14400,  2 }, /* (GMT-04:00) Santiago */

            { -12600,  0 }, /* (GMT-03:30) Newfoundland */

            { -10800, 14 }, /* (GMT-03:00) Brasilia */

            { -10800, -1 }, /* (GMT-03:00) Buenos Aires, Georgetown*/

            { -10800, -1 }, /* (GMT-03:00) Greenland */

            { -7200, -1 }, /* (GMT-02:00) Mid-Atlantic */

            { -3600,  1 }, /* (GMT-01:00) Azores */

            { -3600, -1 }, /* (GMT-01:00) Cape Verde Is. */

            {     0, -1 }, /* (GMT) Casablanca, Monrovia */

            {     0,  1 }, /* (GMT) Greenwich MeanTime: Dublin, Edinburgh,Lisbon, London*/

            {  3600,  1 }, /* (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna

            {  3600,  1 }, /* (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague */

            {  3600,  1 }, /* (GMT+01:00) Brussels, Copenhagen, Madrid, Paris*/

            {  3600,  1 }, /* (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb*/

            {  3600, -1 }, /* (GMT+01:00) West Central Africa*/

            {  7200,  1 }, /* (GMT+02:00) Athens, Istanbul, Minsk */

            {  7200,  1 }, /* (GMT+02:00) Bucharest */

            {  7200,  4 }, /* (GMT+02:00) Cairo */

            {  7200, -1 }, /* (GMT+02:00) Harare, Pretoria */

            {  7200,  1 }, /* (GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius */

            {  7200,  5 }, /* (GMT+02:00) Jerusalem */

            { 10800,  6 }, /* (GMT+03:00) Baghdad */

            { 10800, -1 }, /* (GMT+03:00) Kuwait,Riyadh */

            { 10800,  7 }, /* (GMT+03:00) Moscow, St. Petersburg, Volgograd */

            { 10800, -1 }, /* (GMT+03:00) Nairobi*/

            { 12600,  8 }, /* (GMT+03:30) Tehran */

            { 14400, -1 }, /* (GMT+04:00) Abu Dhabi, Muscat */

            { 14400,  9 }, /* (GMT+04:00) Baku, Tbilisi, Yerevan */

            { 16200, -1 }, /* (GMT+04:30) Kabul*/

            { 18000,  7 }, /* (GMT+05:00)Ekaterinburg */

            { 18000, -1 }, /* (GMT+05:00) Islamabad, Karachi, Tashkent*/

            { 19800, -1 }, /* (GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi */

            { 20700, -1 }, /* (GMT+05:45) Kathmandu*/

            { 21600, 12 }, /* (GMT+06:00) Almaty, Novosibirsk */

            { 21600, -1 }, /* (GMT+06:00) Astana, Dhaka*/

            { 21600, -1 }, /* (GMT+06:00) Sri Jayawardenepura */

            {  23400, -1 }, /* (GMT+06:30) Rangoon */

            { 25200, -1 }, /* (GMT+07:00) Bangkok, Hanoi, Jakarta*/

            { 25200,  7 }, /* (GMT+07:00) Krasnoyarsk */

            { 28800, -1 }, /* (GMT+08:00) Beijing,Chongquing, Hong Kong, Urumqi*/

            { 28800, -1 }, /* (GMT+08:00) Irkutsk,Ulaan Bataar */

            { 28800, -1 }, /* (GMT+08:00) Kuala Lumpur, Singapore*/

            { 28800, -1 }, /* (GMT+08:00) Perth*/

            { 28800, -1 }, /* (GMT+08:00) Taipei*/

            { 32400, -1 }, /* (GMT+09:00) Osaka, Sapporo, Tokyo*/

            { 32400, -1 }, /* (GMT+09:00) Seoul*/

            { 32400,  7 }, /* (GMT+09:00) Yakutsk */

            { 34200,  3 }, /* (GMT+09:30) Adelaide */

            { 34200, -1 }, /* (GMT+09:30) Darwin*/

            { 36000, -1 }, /* (GMT+10:00) Brisbane*/

            { 36000,  3 }, /* (GMT+10:00) Canberra, Melbourne, Sydney*/

            { 36000, -1 }, /* (GMT+10:00) Guam, Port Moresby */

            { 36000, 10 }, /* (GMT+10:00) Hobart*/

            { 36000,  7 }, /* (GMT+10:00) Vladivostok */

            { 39600, -1 }, /* (GMT+11:00) Magadan */

            { 39600,  7 }, /* (GMT+11:00)Solomon Is., New Caledonia*/

            { 43200, 11 }, /* (GMT+12:00) Auckland, Wellington */

            { 43200, -1 }, /* (GMT+12:00) Fiji,Kamchatka, Marshall Is. */

            { 43200, -1 }, /* (GMT+12:00) NZ */

    };        

               那么又如何去掉DST,即找到系统时间与标准时间之间的DST偏移量呢?在此之前需要了解到DST的规则问题,如规则格式、规则数据等等。

               DST规则规定了实施夏令时的起始时间以及结束时间,如澳大利亚的是:从4月的第一个星期天的凌晨3点到10月的第一个星期天的凌晨2点,全世界DST可参考www.worldtimezone.com/daylight.html。下面主要阐述如何判断目前的时间是否包含有夏令时。

    rpytime(rule1, year) < (gm_time + zone->z_gmtoff))< rpytime(rule2, year)

          上面的式子中gm_time是本地系统时间(注意是通过localtime获取,没有加入时区,单位为秒),z_gmtoff是指制定时区的偏移量,这样式子中间代表就是标准时间;式子中rule1,rule2分别对应于DST规则中的两个界点,并利用rpytime函数计算出从1970年以来的时间总长(以秒为单位),若上面的式子成立,表明存在DST,那是因为DST使得在标准时间之上提前了1小时。



    展开全文
  • Linux系统时间函数 2018-07-27 18:20:44
     其中localtime会受时区和夏令时影响,也就是说系统会把函数输入的time_t格式的值作为UTC时间,然后根据本地的TZ环境变量,进行小时的偏移得到一个tm格式的时间;  gmtime则不做环境变量相关的处理,直接获得tm...
  • linux系统调用之时间函数 2018-09-02 23:11:04
    1.常用的时间函数 man 2 中  time_t time(time_t *t); 一个man 3 中  #include &lt;time.h&gt;  char *asctime(const struct tm *tm);  char *asctime_r(const struct tm *tm, char *buf);  ...
  • Linux获取系统当前时间函数: 实现方法一: void debug_print_time(void) { struct timespec time; struct tm nowTime; clock_gettime(CLOCK_REALTIME, &time); //获取相对于1970到现在的秒数 localtime_r(&...
  • Linux 获取时间函数 2018-09-14 20:18:39
    一、time 头文件: #include &lt;time.h&gt; 原型: time_t time(time_t *t) time_t的定义: typedef __darwin_time_t time_...返回值:UTC(coordinated universal time)时间1970年1月1日00时00分...
  • Linux获取当前时间函数 2019-07-22 10:15:22
    Linux获取当前时间函数
  • Linux时间函数 2014-03-14 16:05:19
    Linux时间函数  一、时间相关说明 格林威治时间表示0时区的标准时间。其他时区的时间和此标准时间均有时间差。UTC(Universal Time Coordinated)是世界协调时间,是格林威治时间在互联网中的表示方法 二、...
  • linux 下的时间函数 2018-09-12 20:34:04
    介绍下linux下的时间函数: 首先介绍下clock_gettime()函数,对应头文件 //时间操作方面的基础 #include &amp;amp;lt;stdint.h&amp;amp;gt; #include &amp;amp;lt;time.h&amp;amp;gt; #include &...
  • 我们都熟悉用date来设置系统时间,下面我来介绍下通过系统函数设置系统时间 #include <stdio.h> #include<sys/time.h> #include<unistd.h> #include <time.h> int SetSystemTime(char...
  • Linux时间函数及格式转换 2018-10-31 10:36:02
    本文转自Linux时间函数,感谢分享。简介 本文旨在为了解Linux各种时间类型与时间函数提供技术文档。 1、Linux下常用时间类型 Linux下常用时间类型有四种:time_t、struct tm、struct timeval、struct timespec ...
  • 参考: ... 第一章 获取时间函数 1. char * asctime(const struct tm * timeptr);  函数说明  asctime()将参数timeptr所指的tm结构中的信息转换成真实世界所使用的时间日期表示方法,然
  • Linux系统调用函数列表 2017-08-30 10:24:19
    以下是Linux系统调用的一个列表,包含了大部分常用系统调用和由系统调用派生出的的函数。这可能是你在互联网上所能看到的唯一一篇中文注释的Linux系统调用列表,即使是简单的字母序英文列表,能做到这么完全也是很...
  • c/c++ 时间函数总结 linux 2013-10-06 23:01:02
    Linux c/c++关于时间函数的总结     很想花点时间整理下Linux c/c++关于时间函数,今天…   关于时间的存储 linux下存储时间常见的有两种存储方式,一个是从1970年到现在经过了多少秒,一个是用一个结构来分别...
  • 我们在编程中可能会经常用到时间,比如取得系统的时间(获取系统的年、月、日、时、分、秒,星期等),或者是隔一段时间去做某事,那么我们就用到一些时间函数linux下存储时间常见的有两种存储方式,一个是从...
  • 以下是Linux系统调用的一个列表,包含了大部分常用系统调用和由系统调用派生出的的函数。这可能是你在互联网上所能看到的唯一一篇中文注释的Linux系统调用列表,即使是简单的字母序英文列表,能做到这么完全也是很...
  • GMT时间是以前使用的,近些年来越来越多的使用UTC时间。 ... ...linux系统中的时间函数 ---jiffies的引入 jiffies是linux内核中的一个全局变量,这个变量用来记录以内核的节拍时间为单位时间长度的
  • #include&lt;time.h&gt; #include &lt;sys/time.h&gt;#include&lt;stdio.h&gt;//gcc -o systime systime.cint getSystemTime() { time_t timer; struct tm t_tm;... local...
  • 标准C库中只有获取系统时间的API,好像还没有设置系统时间的API,本文将谈谈如何在linux平台设置系统时间,最后给出一个与平台无关的设置系统时间的封闭函数linux是如何管理时间的? 在系统启动时,Linux操作...
  • 4.linux下的系统函数的使用 c语言 4.1数学函数的使用 1pow函数 2.exp函数 3.log函数 4.rand()随机数函数 4.2字符函数的使用 4.3系统时间与日期函数的使用 系统时间 时间间隔 4.4环境控制函数   4.linux...
  • linux下获取时间函数 2018-01-28 12:29:54
    相关函数 time,ctime,gmtime,localtime asctime asctime(将时间和日期以字符串格式表示) #include 定义函数 char * asctime(const struct tm * timeptr); 函数说明 asctime()将参数timeptr所指的tm结构...
1 2 3 4 5 ... 20
收藏数 333,967
精华内容 133,586