Linux时间相关函数

声明:如果涉及侵权,请联系本人删除侵权内容。
  声明:本文由本人以以往工作经验为依据,总结而得,如果错误,欢迎指正,便于后人参考,少走弯路。

Demo文件请移步github:Time Demo

开发中经常会用到时间,针对不同应用,对时间的需求有所不同:

  • 时间精度(计时等,秒级、毫秒级、微秒级、纳秒级);

  • 时间格式(RTC显示等,年、月、日、时、分、秒的常用不同排列组合);

  • 时间计时(周期报文的发送等);

  • 时间点(闹钟等);

  • 时间段(进程运行时间统计等);

目录

1. 函数一览表

2. 结构体一览表

3. 结构体介绍

3.1. time_t

3.2. timeb

3.3. tm

3.4. timeval

3.5. timezone

3.6. clockid_t

3.7. timespec

4. 函数介绍

4.1. time()

4.2. ftime()

4.3. ctime()族

4.4. gettimeofday()族

4.5. clock_gettime()族

5. 其他时间函数

6. 疑问


1. 函数一览表

函数头文件解释
time()<time.h>获取秒数时间;
基于新纪元1970。
ftime()<sys/timeb.h>获取秒数和毫秒数;
基于新纪元1970;
有些标准已废弃。
ctime()族<time.h>时间格式转换;
asctime(),ctime(),gmtime(),localtime(),mktime()...;
基于1900年;
不获取时间。
gettimeofday()族<sys/time.h>操作秒和微妙;
基于新纪元1970。
clock_gettime()族<time.h>操作秒和纳秒;
基于新纪元1970年;
多用于系统实时、相对、绝对等各类时间统计。

2. 结构体一览表

结构体头文件解释备注
time_t<time.h>长整型别名time()使用
timeb<sys/timeb.h>包含毫秒的结构体ftime()使用
tm<time.h>包含夏令时,一年中的哪天,星期几,年,月,日,时,分,秒ctime族使用,包括asctime(),asctime_r(),gmtime(),gmtime_r(),localtime(),localtime_r(),mktime()
timeval<bits/time.h>秒和微妙gettimeofday()族使用
timezone<sys/time.h>格林威治以西的时间(夏令时)gettimeofday()族使用
clockid_t<time.h>整型别名clock_gettime()族使用
timespec<time.h>秒和纳秒clock_gettime()族使用

3. 结构体介绍

3.1. time_t

    //*** /usr/include/bits/types.h
    #define __SLONGWORD_TYPE    long int

    //*** /usr/include/bits/typesizes.h
    #define __TIME_T_TYPE       __SLONGWORD_TYPE

    //*** /usr/include/bits/types.h
    __STD_TYPE __TIME_T_TYPE __time_t;/* Seconds since the Epoch. */

    //*** /usr/include/time.h
    typedef __time_t time_t;
  • 开始计时时间:1970年1月1日0时0分0秒
  • 要求该类型表达时间不晚于:2038年1月18日19时14分07秒

3.2. timeb

    //*** /usr/include/sys/timeb.h
    struct timeb {
        time_t         time;
        unsigned short millitm;
        short          timezone;
        short          dstflag;
    };
  • time:存放秒级的值;
  • millitm:存放一秒内的毫秒级的值;
  • timezone:以格林威治以西的时间分钟为单位度量的本地时区(负值表示格林威治以东的时间分钟)(UTC时间和本地时间的相差分钟数);
  • dstflag:如果非零,是夏令时时间;
  • POSIX.1-2001表示:timezone和dstflag字段的内容是未指定的,避免依赖他们。

3.3. tm

    //*** /usr/include/time.h
    struct tm {
        int tm_sec;    /* Seconds (0-60) */
        int tm_min;    /* Minutes (0-59) */
        int tm_hour;   /* Hours (0-23) */
        int tm_mday;   /* Day of the month (1-31) */
        int tm_mon;    /* Month (0-11) */
        int tm_year;   /* Year - 1900 */
        int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
        int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
        int tm_isdst;  /* Daylight saving time */
    };
  • tm_sec:0-60范围内的真实秒值,60?
  • tm_min:0-59范围内的真实分钟值;
  • tm_hour:0-23范围内的真实小时值;
  • tm_mday:1-31范围内的真实日期日值;
  • tm_mon:0-11范围内的真实日期月值;
  • tm_year:从1900年开始的年值是1900,不是1970
  • tm_wday:0-6范围内的星期值,0代表周日;
  • tm_yday:0-365范围内的一年中的第几天,0代表1月1日;
  • tm_isdst:夏令时间

3.4. timeval

    //*** /usr/include/bits/time.h
    struct timeval
    {
        __time_t tv_sec;
        __suseconds tv_usec;
    };
  • tv_sec:秒
  • tv_usec:微秒

3.5. timezone

    //*** /usr/include/sys/time.h
    struct timezone
    {
        int tz_minuteswest;
        int tz_dsttime;
    };
  • tz_minuteswest:以格林威治以西的时差,单位为分钟
  • tz_dsttime:夏令时非零时有效

3.6. clockid_t

    //*** /usr/include/bits/types.h
    #define __S32_TYPE      int

    //*** /usr/include/bits/typesizes.h
    #define __CLOCKID_T_TYPE    __S32_TYPE

    //*** /usr/include/bits/types.h
    __STD_TYPE __CLOCK_T_TYPE __clock_t;

    //*** /usr/include/time.h
    typedef __clockid_t clockid_t; 

3.7. timespec

    //*** /usr/include/time.h
    struct timespec {
        time_t   tv_sec;        /* seconds */
        long     tv_nsec;       /* nanoseconds */
    };
  • tv_sec:秒;
  • tv_nsec:纳秒;

4. 函数介绍

4.1. time()

  • MAN章节&头文件&定义:
        /* man 2 time */
    
        #include <time.h>
    
        time_t time(time_t *tloc);
  • 函数&参数&返回值描述:
    • 函数描述:

      返回从新纪元(1970-01-01 00:00:00 +0000 (UTC)开始的秒数。

    • 参数描述:

      如果tloc非NULL,则返回值也存储在tloc指向的内存中。

    • 返回值描述:
    • 成功:返回从新纪元开始的秒数值;
    • 失败:返回-1,并设置errno;
  • Demo&结果:
    • Demo:
        #include <stdio.h>
        #include <time.h>
    
        int main(void)
        {
            time_t m_tyTimeVal = 0;
    
            m_tyTimeVal = time(NULL);
            printf("%d\n",(int)m_tyTimeVal);
    
            return 0;
        }
    • 结果:
        /* 算算什么时间... */
        1587039053

4.2. ftime()

  • MAN章节&头文件&定义:

        /* man 3 ftime */  
    
        #include <sys/timeb.h>
    
        int ftime(struct timeb *tp);
  • 函数&参数&返回值描述:

    • 函数描述:

      以秒和毫秒的形式返回自新纪元(1970-01-01 00:00:00 +0000 (UTC))以来的当前时间。

    • 参数描述:

      传出参数,存放获取的时间值。

    • 返回值描述:
    • 总是返回0;
    • POSIX.1-2001指定在某些系统文档中错误返回-1。
  • Demo&结果:

    • Demo:
        /* gcc编译需要struct timeb var格式定义. */
        /* g++编译可以timeb var格式直接定义. */
        #include <stdio.h>
        #include <sys/timeb.h>
    
        int main(void)
        {
            int m_ulRet = 0;
            struct timeb m_stTimeVal;
    
            m_ulRet = ftime(&m_stTimeVal);
            printf("     ret : %d\n",m_ulRet);
            printf("    time : %d\n"
                   " millitm : %d\n"
                   "timezone : %d\n"
                   " dstflag : %d\n",
                (int)m_stTimeVal.time,
                m_stTimeVal.millitm,
                m_stTimeVal.timezone,
                m_stTimeVal.dstflag);
    
            return 0;
        }
    • 结果:
             ret : 0
            time : 1587031235
         millitm : 84
        timezone : 0
         dstflag : 0
  • POSIX.1-2008删除了ftime()的规范,废弃不用了。

4.3. ctime()族

  • MAN章节&头文件&定义:
        /* man 3 ctime/asctime/gmtime/localtime/mktime... */ 
    
       #include <time.h>
    
       char *asctime(const struct tm *tm);
       char *asctime_r(const struct tm *tm, char *buf);
    
       char *ctime(const time_t *timep);
       char *ctime_r(const time_t *timep, char *buf);
    
       struct tm *gmtime(const time_t *timep);
       struct tm *gmtime_r(const time_t *timep, struct tm *result);
    
       struct tm *localtime(const time_t *timep);
       struct tm *localtime_r(const time_t *timep, struct tm *result);
    
       time_t mktime(struct tm *tm);   
  • 函数&参数&返回值描述:
    • 函数描述:
    • 这个族不会获取时间,而是对已经获取到的时间做格式转换;
    • localtime:将time_t类型的时间转换为tm类型本地时间;
    • gmtime:将time_t类型的时间转换为tm类型的格林威治(GMT)时间,
    • asctime:将tm类型时间转换为字符串型输出;
    • ctime:将time_t时间在内部转换成tm时间,并转成字符串输出;
    • mktime:将tm类型时间转换成time_t类型;
    • 在线程中应该使用对应函数的"_r"模式来处理,来避免线程安全问题;
    • 参数描述:
    • const tm*:传入
    • char *buf:传出
    • const time_t*传入
    • 返回值描述:

    根据不同函数功能返回。

  • Demo&结果:
    • Demo:
        #include <stdio.h>
        #include <time.h>
        #include <string.h> 
        #include <stdlib.h>
    
        void printTm(const struct tm* tm)
        {
            printf("**%d-%d-%d:%d-%d-%d\n",tm->tm_year+1900,tm->tm_mon+1,\
                    tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
            printf("**week:%d\n",tm->tm_wday);
            printf("**yday:%d\n",tm->tm_yday);
            printf("**dst:%d\n",tm->tm_isdst);
        }
    
        int main(void)
        {
            time_t m_tyTimeVal = 0;
            time_t m_tyTimeTempVal = 0;
            struct tm* m_pstTmVal;
            char *m_pucTimeStr;
            
            m_pstTmVal = malloc(sizeof(struct tm));
            m_pucTimeStr = malloc(200);
    
            printf("******************************** time() ***\n");
            m_tyTimeTempVal = time(NULL);
            printf("**%d\n",(int)m_tyTimeTempVal);
            
            printf("****************************** gmtime() ***\n");
            m_pstTmVal = gmtime(&m_tyTimeTempVal);
            printTm(m_pstTmVal);
    
            printf("*************************** localtime() ***\n");
            m_pstTmVal = localtime(&m_tyTimeTempVal);
            printTm(m_pstTmVal);
            
            printf("***************************** asctime() ***\n");
            m_pucTimeStr = asctime(m_pstTmVal); 
            printf("**%s",m_pucTimeStr);
    
            printf("******************************* ctime() ***\n");
            m_pucTimeStr = ctime(&m_tyTimeTempVal);
            printf("**%s",m_pucTimeStr);
    
            printf("****************************** mktime() ***\n");
            m_tyTimeVal = mktime(m_pstTmVal);
            printf("**%d\n",(int)m_tyTimeVal);
        #if 0
            if(m_pstTmVal)
                free(m_pstTmVal);//Bk?:这里不能free,函数是怎么返回结构体指针的?
            if(m_pucTimeStr)
                free(m_pucTimeStr);
        #endif
    
            return 0;
        }
    • 结果:
        # ./App 
        ******************************** time() ***
        **206
        ****************************** gmtime() ***
        **1970-1-1:0-3-26
        **week:4
        **yday:0
        **dst:0
        *************************** localtime() ***
        **1970-1-1:8-3-26
        **week:4
        **yday:0
        **dst:0
        ***************************** asctime() ***
        **Thu Jan  1 08:03:26 1970
        ******************************* ctime() ***
        **Thu Jan  1 08:03:26 1970
        ****************************** mktime() ***
        **206

4.4. gettimeofday()族

  • MAN章节&头文件&定义:
        /* man 2 gettimeofday/settimeofday */
    
        #include <sys/time.h>
    
        int gettimeofday(struct timeval *tv, struct timezone *tz);
    
        int settimeofday(const struct timeval *tv, const struct timezone *tz);
        // settimeofday(): _BSD_SOURCEs //Bk?:未确定用途  
  • 函数&参数&返回值描述:
    • 函数描述:
    • gettimeofday:获取时间和时区信息;
    • settimeofday:设置时间和时区;
    • 参数描述:
    • tv:包含秒和微秒信息,不使用时传NULL,该变量为NULL编译时报警告;
    • tz:包含时区和夏令时信息,该参数基本过时(有些系统获取不到值),常传NULL;
    • 返回值描述:
    • 0:成功;
    • -1:失败,并设置errno;
  • Demo&结果:
    • Demo:
        #include <stdio.h>
        #include <sys/time.h>
        #include <time.h>
        #include <stdlib.h>
    
        int main(void)
        {
            struct timeval tv;
            system("date");
            gettimeofday(&tv,NULL);
            printf("timeval:%ld.%ld\n\n",tv.tv_sec,tv.tv_usec);
            
            tv.tv_sec = 1587039053;
            tv.tv_usec = 0;
            printf("timeval:%ld.%ld\n\n",tv.tv_sec,tv.tv_usec);
            
            if(settimeofday(&tv,NULL) != 0)
            {
                perror("settimeofday");	
            }
            system("date");
            gettimeofday(&tv,NULL);
            printf("timeval:%ld.%ld\n",tv.tv_sec,tv.tv_usec);
            
            return 0;
        }
    • 结果:
        # ./App 
        Thu Jan  1 08:02:41 CST 1970
        timeval:161.657774
    
        timeval:1587039053.0
    
        Thu Apr 16 20:10:53 CST 2020
        timeval:1587039053.2744
  • settimeofday在设置时间的时候,参数很容易出错,导致设置失败;

4.5. clock_gettime()族

  • MAN章节&头文件&定义:
        /* man 3 clock_getres/clock_gettime/clock_settime */
    
        #include <time.h>
    
       int clock_getres(clockid_t clk_id, struct timespec *res);
    
       int clock_gettime(clockid_t clk_id, struct timespec *tp);
    
       int clock_settime(clockid_t clk_id, const struct timespec *tp); 
  • 函数&参数&返回值描述:
    • 函数描述:
    • clock_getres:检索指定clk_id类型的分辨率;
    • clock_gettime:得到指定clk_id类型的时间;
    • clock_settime:设置指定clk_id类型的时间;
    • 参数描述:
    • clk_id:某种时钟类型
      • CLOCK_REALTIME:系统实时时间,随系统实时时间改变而改变;
      • CLOCK_MONOTONIC:从系统启动开始计时,不受系统时间被用户改变的影响;
      • CLOCK_PROCESS_CPUTIME_ID:本进程在系统CPU中运行的时间;
      • CLOCK_THREAD_CPUTIME_ID:本进程在系统CPU中运行的时间。
    • tp:时间值
    • res:分辨率
    • 返回值描述:
    • 0:成功;
    • -1:失败,并设置errno。
  • Demo&结果:
    • Demo:
        #include <stdio.h>
        #include <time.h>
    
        void printTm(const struct tm* tm)
        {
            printf("**%d-%d-%d:%d-%d-%d\n",tm->tm_year+1900,tm->tm_mon+1,\
                    tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
            printf("**week:%d\n",tm->tm_wday);
            printf("**yday:%d\n",tm->tm_yday);
            printf("**dst:%d\n",tm->tm_isdst);
        }
    
        int main(void)
        {
            struct timespec timeVal;
    
            clock_gettime(CLOCK_REALTIME,&timeVal);
            printf("time:%s\n",ctime(&timeVal.tv_sec));
            printf("time: %ld.%ld\n",timeVal.tv_sec,timeVal.tv_nsec);
    
            return 0;
        }
    • 结果:
        # ./App 
        time:Thu Jan  1 08:00:23 1970
    
        time: 23.927505916

 

5. 其他时间函数

函数解释
clock()返回程序使用的处理器时间的近似值
adjtime()调整系统时钟
adjtimex()设置David L. Mills的时钟调整算法的调整参数
clock_getcpuclockid()TBD...
pthread_getcpuclockid()TBD...
timeradd()族操作timeval类型的两个结构体变量;
timeradd()
timersub()
timerclear()
timerisset()
timercmp()
setitimer()族为进程提供三种间隔计时器,计时到达给进程发送信号;
ITIMER_REAL
ITIMER_VIRTUAL
ITIMER_PROF
timer_create()系列创建一个间隔计时器
相关函数还有:
timer_delete()
timer_getoverrun()
timer_settime
timer_gettime
timerfd_create()族创建一个通过文件描述符传递计时器溢出通知的计时器

6. 疑问

  • linuxOS能应用的最小时间精度,应用层可以保证的时间精度?

笔记:...

  • 验证:printf("%" PRId64"\n",m_tyTimeVal)?

笔记:...

  • 格林威治&夏令时&时区?

笔记:...

  • POSIX?

笔记:...

  • 线程安全?

笔记:...

  • 哪些结构体在将来某个时间点就不能使用了(time_t?)?

笔记:...

  • ctime族多个函数返回结构体指针,返回的是那个区域(常量?堆区?栈?)?谁释放?(突然感觉C语言不过关呀!)

笔记:...

  • tm结构体tm_sec成员的值60什么情况下应用?

笔记:...

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值