Linux時間函數札記

關於gmtimegmtime_rlocaltimelocaltime_r


測試環境:vmware 7 + Redhat5.5,系統時間使用UTC,時區爲上海。

 1、函數功能介紹

        使用man gmtimeman localtime都可以的得到這幾個函數的介紹。原型如下:

        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);

man手冊中對它們的解釋如下:

        The gmtime() function converts the calendar time timep to broken-down time representation, expressed in Coordinated Universal Time (UTC). It may return NULL when the year does not fit into an integer. The return value points to a statically allocated struct which might be overwritten  by subsequent calls to any of the date and time functions. The gmtime_r() function does the same, but stores the data in a user-supplied struct.

        The localtime() function converts the calendar time timep to broken-time representation, expressed relative to the user's specified time zone. The function acts as if it called tzset(3) and sets the external variables tzname with information about the current time zone, timezone with  the difference between Coordinated Universal Time (UTC) and local standard time in seconds, and daylight to a non-zero value if daylight savings time rules apply during some part of the year.  The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions. The localtime_r() function does the same, but stores  the data in a user-supplied struct. It need not set tzname

翻譯如下:

        gmtime() 函數將日曆時間timep轉換爲用UTC時間表示的時間。它可能返回NULL,比如年份不能放到一個整數中。返回值指向一個靜態分配的結構,該結構可能會被接下來的任何日期和時間函數調用覆蓋。gmtime_r()函數功能與此相同,但是它可以將數據存儲到用戶提供的結構體中。

        localtime() 函數將日曆時間timep轉換爲用戶指定的時區的時間。這個函數的行爲好像是它調用了tzset(3) 並且將外部變量tzname設置爲當前時區的信息,將timezone設爲UTC和本地標準時間的差值,並且,如果在一年的部分時間使用日光節約規則時將daylight設置爲非空值。返回值指向一個靜態分配的結構,該結構可能會被接下來的任何日期和時間函數調用覆蓋。localtime_r()函數功能與此相同,但是它可以將數據存儲到用戶提供的結構體中。它不需要設置tzname

 

2、功能測試

程序一:

#include <stdio.h>

#include <time.h>

int main()

{

time_t cur_time=time(NULL);

if( cur_time < 0 )

{

perror("time");

return -1;

}

 

struct tm utc_tm;;

if( NULL == gmtime_r( &cur_time, &utc_tm ) )

{

perror("gmtime" );

return -1;

}

 

struct tm local_tm;

if( NULL == localtime_r( &cur_time, &local_tm ) )

{

perror("localtime" );

return -1;

}

 

printf("UTC = %s", asctime(&utc_tm) );

printf("LOC = %s", asctime(&local_tm) );

printf("LOC = %s", ctime(&cur_time) );

return 0;

}

程序輸出:

UTC = Thu Oct 27 09:16:10 2011

LOC = Thu Oct 27 17:16:10 2011

LOC = Thu Oct 27 17:16:10 2011

由於系統時間使用了UTC,可以看到本地時間= UTC時間 + 8”,輸出正確。

 

程序二:

#include <stdio.h>

#include <time.h>

int main()

{

time_t cur_time=time(NULL);

if( cur_time < 0 )

{

perror("time");

return -1;

}

 

struct tm *utc_tm = gmtime( &cur_time );

if( NULL == utc_tm )

{

perror("gmtime" );

return -1;

}

 

printf("UTC = %s", asctime(utc_tm) );

 

struct tm *local_tm = localtime( &cur_time );

if( NULL == local_tm )

{

perror("localtime" );

return -1;

}

 

printf("LOC = %s", asctime(local_tm) );

printf("LOC = %s", ctime(&cur_time) );

return 0;

}

程序輸出:

UTC = Thu Oct 27 09:20:45 2011

LOC = Thu Oct 27 17:20:45 2011

LOC = Thu Oct 27 17:20:45 2011

同樣是正確的。

 

程序三:

#include <stdio.h>

#include <time.h>

int main()

{

time_t cur_time=time(NULL);

if( cur_time < 0 )

{

perror("time");

return -1;

}

 

struct tm *utc_tm = gmtime( &cur_time );

if( NULL == utc_tm )

{

perror("gmtime" );

return -1;

}

 

struct tm *local_tm = localtime( &cur_time );

if( NULL == local_tm )

{

perror("localtime" );

return -1;

}

 

printf("UTC = %s", asctime(utc_tm) );

printf("LOC = %s", asctime(local_tm) );

printf("LOC = %s", ctime(&cur_time) );

return 0;

}

程序輸出:

UTC = Thu Oct 27 17:21:59 2011

LOC = Thu Oct 27 17:21:59 2011

LOC = Thu Oct 27 17:21:59 2011

這程序輸出有錯,UTC時間和本地時間相同了,這應該就是由於man文檔中描述的可能會被接下來的任何日期和時間函數調用覆蓋造成的。爲驗證這個設想,使用程序四:

 

程序四:

#include <stdio.h>

#include <time.h>

int main()

{

time_t cur_time=time(NULL);

if( cur_time < 0 )

{

perror("time");

return -1;

}

 

struct tm *local_tm = localtime( &cur_time );

if( NULL == local_tm )

{

perror("localtime" );

return -1;

}

 

struct tm *utc_tm = gmtime( &cur_time );

if( NULL == utc_tm )

{

perror("gmtime" );

return -1;

}

 

printf("UTC = %s", asctime(utc_tm) );

printf("LOC = %s", asctime(local_tm) );

printf("LOC = %s", ctime(&cur_time) );

return 0;

}

程序輸出:

UTC = Thu Oct 27 09:24:23 2011

LOC = Thu Oct 27 09:24:23 2011

LOC = Thu Oct 27 17:24:23 2011

驗證了該設想。

 

3、總結

        使用gmtimelocaltime後要立即處理結果,否則返回的指針指向的內容可能會被覆蓋,一個好的方法是使用gmtime_rlocaltime_r,由於使用了用戶分配的內存,這兩個函數是不會出錯的。





Linux時間函數

分類: Linux C編程2012-04-28 22:48 22366人閱讀 評論(6) 收藏 舉報

linuxstructnulltimezonetimer

系統環境:ubuntu10.04


簡介

本文旨在爲了解Linux各種時間類型與時間函數提供技術文檔。


1Linux下常用時間類型

Linux下常用時間類型有四種:time_tstruct tmstruct timevalstruct timespec


1.1 time_t時間類型

time_t類型在time.h中定義:

  1. #ifndef __TIME_T  
  2. #define __TIME_T  
  3. typedef  long  time_t;  
  4. #endif  

可見,time_t實際是一個長整型。其值表示爲從UTC(coordinated universal time)時間197011000000(也稱爲Linux系統的Epoch時間)到當前時刻的秒數。由於time_t類型長度的限制,它所表示的時間不能晚於2038119031407(UTC)。爲了能夠表示更久遠的時間,可用64位或更長的整形數來保存日曆時間,這裏不作詳述。

使用time()函數獲取當前時間的time_t值,使用ctime()函數將time_t轉爲當地時間字符串。

備註UTC時間有時也稱爲GMT時間,其實UTCGMT兩者幾乎是同一概念。它們都是指格林尼治標準時間,只不過UTC的稱呼更爲正式一點。兩者區別在於前者是天文上的概念,而後者是基於一個原子鐘。


1.2 struct tm時間類型

tm結構在time.h中定義:

  1. #ifndef _TM_DEFINED  
  2. struct tm{  
  3.     int tm_sec; /* - 取值區間爲[0, 59]*/  
  4.     int tm_min; /* - 取值區間爲[0, 59]*/  
  5.     int tm_hour; /* - 取值區間爲[0, 23]*/  
  6.     int tm_mday; /* - 取值區間爲[1, 31]*/  
  7.     int tm_mon; /*月份 - 取值區間爲[0, 11]*/  
  8.     int tm_year; /*年份 - 其值爲1900年至今年數*/  
  9.     int tm_wday; /*星期 - 取值區間[0, 6]0代表星期天,1代表星期1,以此類推*/  
  10.     int tm_yday; /*從每年的11日開始的天數-取值區間爲[0, 365]0代表11*/  
  11.     int tm_isdst; /*夏令時標識符,使用夏令時,tm_isdst爲正,不使用夏令時,tm_isdst0,不瞭解情況時,tm_isdst爲負*/  
  12. };  
  13. #define _TM_DEFINED  
  14. #endif  

ANSI C標準稱使用tm結構的這種時間表示爲分解時間(broken-down time)

使用gmtime( )localtime( )可將time_t時間類型轉換爲tm結構體;

使用mktime( )tm結構體轉換爲time_t時間類型;

使用asctime( )struct tm轉換爲字符串形式。

 

1.3 struct timeval時間類型

timeval結構體在time.h中定義:

  1. Struct tmieval{  
  2.     time_t tv_sec; /*s*/  
  3.     suseconds_t tv_usec; /*微秒us*/  
  4. };  

設置時間函數settimeofday( )與獲取時間函數gettimeofday( )均使用該事件類型作爲傳參。

 

1.4 struct timespec時間類型

timespec結構體在time.h定義:


  1. struct timespec{  
  2.     time_t tv_sec; /*s*/  
  3.     long tv_nsec; /*納秒ns*/  
  4. };  

 

2Linux下常用時間函數

Linux下常用時間函數有:time( )ctime( )gmtime( )localtime( )mktime( )asctime( )difftime( )gettimeofday( )settimeofday( )


2.1 time( )函數

頭文件:#include <time.h>

函數定義:time_t time(time_t *timer)

功能描述:該函數返回從197011000000秒至今所經過的秒數。如果time_t *timer非空指針,函數也會將返回值存到timer指針指向的內存。

返回值:成功則返回秒數,失敗則返回((time_t)-1)值,錯誤原因存於errno中。

例:


  1. time_t seconds;  
  2. seconds = time((time_t *)NULL);  


2.2 ctime( )函數

頭文件:#include <time.h>

函數定義:char *ctime(const time_t *timep);

功能描述:ctime( )將參數timep指向的time_t時間信息轉換成實際所使用的時間日期表示方法,並以字符串形式返回。字符串格式爲:"Wed Jun 20 21:00:00 2012\n"

例:

  1. time_t timep;  
  2. tmep = time(NULL);  
  3. printf("%s\n", ctime(&timep));  


2.3 gmtime( )函數

頭文件:#include <time.h>

函數定義:struct tm *gmtime(const time_t *timep)

功能描述:gmtime( )將參數timep指向的time_t時間信息轉換成以tm結構體表示的GMT時間信息,並以struct tm*指針返回。

GMTGMT是中央時區,北京在東8,相差8個小時,所以北京時間=GMT時間+8小時。

例:

  1. int main(void)  
  2. {  
  3.     char *wday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};  
  4.     time_t timep;  
  5.     struct tm *p_tm;  
  6.     timep = time(NULL);  
  7.     p_tm = gmtime(&timep); /*獲取GMT時間*/  
  8.     printf("%d-%d-%d ", (p_tm->tm_year+1900), (p_tm->mon+1), p_tm->tm_mday);  
  9.     printf("%s %d:%d:%d\n", wday[p_tm->tm_wday], p_tm->tm_hour, p_tm->tm_min, p_tm->tm_sec);  
  10. }  


2.4 localtime( )函數

頭文件:#include <time.h>

函數定義:struct tm *localtime(const time_t *timep);

功能描述:localtime( )將參數timep指向的time_t時間信息轉換成以tm結構體表示的本地時區時間(如北京時間= GMT+小時)

例:

  1. int main(void)  
  2. {  
  3.     char *wday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};  
  4.     time_t timep;  
  5.     struct tm *p_tm;  
  6.     timep = time(NULL);  
  7.     p_tm = localtime(&timep); /*獲取本地時區時間*/  
  8.     printf("%d-%d-%d ", (p_tm->tm_year+1900), (p_tm->mon+1), p_tm->tm_mday);  
  9.     printf("%s %d:%d:%d\n", wday[p_tm->tm_wday], p_tm->tm_hour, p_tm->tm_min, p_tm->tm_sec);  
  10.     return 0;  
  11. }  


2.5 mktime( )函數

頭文件:#include <time.h>

函數定義:time_t mktime(struct tm *p_tm);

功能描述:mktime( )將參數p_tm指向的tm結構體數據轉換成從197011000000秒至今的GMT時間經過的秒數。

例:

  1. int main(void)  
  2. {  
  3.     time_t timep:  
  4.     struct tm *p_tm;  
  5.     timep = time(NULL);  
  6.     pintf("time( ):%d\n", timep);  
  7.     p_tm = local(&timep);  
  8.     timep = mktime(p_tm);  
  9.     printf("time( )->localtime( )->mktime( ):%d\n", timep);  
  10.     return 0;  
  11. }  


2.6 asctime( )函數

頭文件:#include <time.h>

函數定義:char *asctime(const struct tm *p_tm);

功能描述:asctime( )將參數p_tm指向的tm結構體數據轉換成實際使用的時間日期表示方法,並以字符串形式返回(ctime函數相同)。字符串格式爲:"Wed Jun 20 21:00:00 2012\n"

例:

  1. int main(void)  
  2. {  
  3.     time_t timep;  
  4.     timep = time(NULL);  
  5.     printf("%s\n", asctime(gmtime(&timep)));  
  6.     return 0;  
  7. }  


2.7 difftime( )函數

頭文件:#include <time.h>

函數定義:double difftime(time_t timep1, time_t timep2);

功能描述:difftime( )比較參數timep1timep2時間是否相同,並返回之間相差秒數。

例:

  1. int main(void)  
  2. {  
  3.     time_t timep1, timep2;  
  4.     timep1 = time(NULL);  
  5.     sleep(2);  
  6.     timep2 = time(NULL);  
  7.     printf("the difference is %f seconds\n", difftime(timep1, timep2));  
  8.     return 0;  
  9. }  


2.8 gettimeofday( )函數

頭文件:#include <sys/time.h>

        #include <unistd.h>

函數定義:int gettimeofday(struct timeval *tv, struct timezone *tz);

功能描述:gettimeofday( )把目前的時間信息存入tv指向的結構體,當地時區信息則放到tz指向的結構體。

struct timezone原型:

  1. struct timezone{  
  2.     int tz_minuteswest; /*miniutes west of Greenwich*/  
  3.     int tz_dsttime; /*type of DST correction*/  
  4. };  

例:

  1. struct timeval tv;  
  2. struct timeval tz;  
  3. gettimeofday(&tv, &tz);  


附:

使用time函數族獲取時間並輸出指定格式字符串例子(strftime( )函數):

  1. int main(void)  
  2. {  
  3.     char strtime[20] = {0};  
  4.     time_t timep;  
  5.     struct tm *p_tm;  
  6.     timep = time(NULL);  
  7.     p_tm = localtime(&timep);  
  8.     strftime(strtime, sizeof(strtime), "%Y-%m-%d %H:%M:%S", p_tm);  
  9.     return 0;  
  10. }  


2.9 settimeofday( )函數

頭文件:#include <sys/time.h>

        #include <unistd.h>

函數定義:int settimeofday(const struct timeval *tv, const struct timezone *gz);

功能描述:settimeofday( )把當前時間設成由tv指向的結構體數據。當前地區信息則設成tz指向的結構體數據。

例:


  1. int main(void)  
  2. {  
  3.     char t_string[] = "2012-04-28 22:30:00";  
  4.     struct tm time_tm;  
  5.     struct timeval time_tv;  
  6.     time_t timep;  
  7.     int ret = 0;  
  8.  
  9.     sscanf(t_string, "%d-%d-%d %d:%d:%d", &time_tm.tm_year, &time_tm.tm_mon, &time_tm.tm_mday, &time_tm.tm_hour, &time_tm.tm_min, &time_tm.tm_sec);  
  10.     time_tm.tm_year -= 1900;  
  11.     time_tm.tm_mon -= 1;  
  12.     time_tm.tm_wday = 0;  
  13.     time_tm.tm_yday = 0;  
  14.     time_tm.tm_isdst = 0;  
  15.  
  16.     timep = mktime(&time_tm);  
  17.     time_tv.tv_sec = timep;  
  18.     time_tv.tv_usec = 0;  
  19.  
  20.     ret = settimeofday(&time_tv, NULL);  
  21.     if(ret != 0)  
  22.     {  
  23.         fprintf(stderr, "settimeofday failed\n");  
  24.         return -1;  
  25.     }  
  26.     return 0;  
  27. }  

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