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什麼情況下應用?

筆記:...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章