C/C++常用時間函數介紹

在介紹之前,先介紹兩個概念

 

Coordinated Universal Time(UTC):協調世界時,又稱爲世界標準時間,也就是大家所熟知的格林威治標準時間(Greenwich Mean Time,GMT)。比如,中國內地的時間與UTC的時差爲+8,也就是UTC+8。美國是UTC-5。

 

Calendar Time:日曆時間,是用“從一個標準時間點到此時的時間經過的秒數”來表示的時間。這個標準時間點對不同的編譯器來說會有所不同,但對一個編譯系統來說,這個標準時間點是不變的,該編譯系統中的時間對應的日曆時間都通過該標準時間點來衡量,所以可以說日曆時間是“相對時間”,但是無論你在哪一個時區,在同一時刻對同一個標準時間點來說,日曆時間都是一樣的。(簡單點說,可以理解爲CT時間就是UTC時間減去1900-01-01 00:00:00)

 

與日期和時間相關的數據結構

 

Cpp代碼 複製代碼 收藏代碼
  1. typedef long time_t;         /* 時間值 */  
  1. typedef long time_t;         /* 時間值 */  

 

    大家可能會產生疑問:既然time_t實際上是長整型,到未來的某一天,從一個時間點(一般是1970年1月1日0時0分0秒)到那時的秒數(即日曆時間)超出了長整形所能表示的數的範圍怎麼辦?對time_t數據類型的值來說,它所表示的時間不能晚於2038年1月18日19時14分07秒。爲了能夠表示更久遠的時間,一些編譯器廠商引入了64位甚至更長的整形數來保存日曆時間。比如微軟在Visual C++中採用了__time64_t數據類型來保存日曆時間,並通過_time64()函數來獲得日曆時間(而不是通過使用32位字的time()函數),這樣就可以通過該數據類型保存3001年1月1日0時0分0秒(不包括該時間點)之前的時間。

 

Cpp代碼 複製代碼 收藏代碼
  1. struct tm    
  2. {    
  3.     int tm_sec; /* 秒 - 取值區間爲[0,59] */    
  4.     int tm_min; /* 分 - 取值區間爲[0,59] */    
  5.     int tm_hour; /* 時 - 取值區間爲[0,23] */    
  6.     int tm_mday; /* 一個月中的日期 - 取值區間爲[1,31] */ i   
  7.     nt tm_mon; /* 月份(從一月開始,0代表一月)- 取值區間爲[0,11] */    
  8.     int tm_year; /* 年份,其值等於實際年份減去1900 */     
  9.     int tm_wday; /* 星期–取值區間爲[0,6],其中0代表星期天,1代表星期一,以此類推 */    
  10.     int tm_yday; /* 從每年的1月1日開始的天數 – 取值區間爲[0,365],其中0代表1月1日,1代表1月2日,以此類推 */    
  11.     int tm_isdst; /*夏令時標識符,實行夏令時的時候,tm_isdst爲正。不實行夏令時的進候,tm_isdst爲0;不瞭解情況時,tm_isdst()爲負。  
  12.                     夏令時可以在網上找到答案,在中國,已經不再使用夏令時*/    
  13. };  
  1. struct tm   
  2. {   
  3.     int tm_sec; /* 秒 - 取值區間爲[0,59] */   
  4.     int tm_min; /* 分 - 取值區間爲[0,59] */   
  5.     int tm_hour; /* 時 - 取值區間爲[0,23] */   
  6.     int tm_mday; /* 一個月中的日期 - 取值區間爲[1,31] */ i  
  7.     nt tm_mon; /* 月份(從一月開始,0代表一月)- 取值區間爲[0,11] */   
  8.     int tm_year; /* 年份,其值等於實際年份減去1900 */    
  9.     int tm_wday; /* 星期–取值區間爲[0,6],其中0代表星期天,1代表星期一,以此類推 */   
  10.     int tm_yday; /* 從每年的1月1日開始的天數 – 取值區間爲[0,365],其中0代表1月1日,1代表1月2日,以此類推 */   
  11.     int tm_isdst; /*夏令時標識符,實行夏令時的時候,tm_isdst爲正。不實行夏令時的進候,tm_isdst爲0;不瞭解情況時,tm_isdst()爲負。 
  12.                     夏令時可以在網上找到答案,在中國,已經不再使用夏令時*/   
  13. };  

 

Cpp代碼 複製代碼 收藏代碼
  1. typedef long clock_t;     從"開啓這個程序進程""程序中調用clock()函數"時之間的CPU時鐘計時單元(clock tick)數  
  1. typedef long clock_t;     從"開啓這個程序進程""程序中調用clock()函數"時之間的CPU時鐘計時單元(clock tick)數  

 

clock(取得CPU時鐘計時單元(clock tick)數)
函數定義 
clock_t clock( void )


函數說明 
函數返回從"開啓這個程序進程"到"程序中調用clock()函數"時之間的CPU時鐘計時單元(clock tick)數。其中clock_t是用來保存時間的數據類型


返回值 
從"開啓這個程序進程"到"程序中調用clock()函數"時之間的CPU時鐘計時單元(clock tick)數

 

在time.h文件中,定義了一個常量CLOCKS_PER_SEC,它用來表示一秒鐘會有多少個時鐘計時單元,其定義如下:

#define CLOCKS_PER_SEC ((clock_t)1000)

可以看到每過千分之一秒(1毫秒),調用clock()函數返回的值就加1。

 

範例:

Cpp代碼 複製代碼 收藏代碼
  1. #include "stdio.h"   
  2. #include "time.h"   
  3.   
  4. int main( void )   
  5. {   
  6.    long    i = 10000000L;   
  7.    clock_t start, end;   
  8.    double  timeUsed;   
  9.    start = clock();   
  10.    while( i-- )      ;   
  11.    end = clock();   
  12.    timeUsed = (double)(end - start) / CLOCKS_PER_SEC;   
  13.    printf( "執行10000000次空循環用時%f秒\n", timeUsed );   
  14. }  
  1. #include "stdio.h"  
  2. #include "time.h"  
  3.   
  4. int main( void )  
  5. {  
  6.    long    i = 10000000L;  
  7.    clock_t start, end;  
  8.    double  timeUsed;  
  9.    start = clock();  
  10.    while( i-- )      ;  
  11.    end = clock();  
  12.    timeUsed = (double)(end - start) / CLOCKS_PER_SEC;  
  13.    printf( "執行10000000次空循環用時%f秒\n", timeUsed );  
  14. }  

 

輸出結果
    執行10000000次空循環用時0.031000秒

 

time(取得目前的時間)
函數定義 
time_t time(time_t *t);


函數說明 
此函數會返回從公元1970年1月1日的0時0分0秒算起到現在所經過的秒數(CT時間)。如果t是非空指針的話,此函數也會將返回值存到t指針所指的內存。


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

 

注意:由於返回的是CT時間,所以在做時間判斷的時候一定要注意時區

 

範例

Cpp代碼 複製代碼 收藏代碼
  1. #include <stdio.h>   
  2. #include <time.h>   
  3.   
  4. #define DAY_SECONDS (24*60*60)   
  5.   
  6. int main(int argc, char**argv)   
  7. {   
  8.     time_t timeNow = time(NULL);   
  9.   
  10.     time_t timeDayNow =  timeNow%DAY_SECONDS;   
  11.     int hour = timeDayNow/3600;   
  12.     int min = (timeDayNow%3600)/60;   
  13.     int sec = timeDayNow%60;   
  14.   
  15.     printf("現在時間%d:%d:%d\n", hour, min, sec);    
  16.   
  17.     return 0;   
  18. };  
  1. #include <stdio.h>  
  2. #include <time.h>  
  3.   
  4. #define DAY_SECONDS (24*60*60)  
  5.   
  6. int main(int argc, char**argv)  
  7. {  
  8.     time_t timeNow = time(NULL);  
  9.   
  10.     time_t timeDayNow =  timeNow%DAY_SECONDS;  
  11.     int hour = timeDayNow/3600;  
  12.     int min = (timeDayNow%3600)/60;  
  13.     int sec = timeDayNow%60;  
  14.   
  15.     printf("現在時間%d:%d:%d\n", hour, min, sec);   
  16.   
  17.     return 0;  
  18. };  

 

輸出結果會比你當前系統的時間早8個小時,那是因爲中國內地的時間與UTC的時差爲+8

 


localtime(取得當地目前時間和日期) 
函數定義 
struct tm *localtime(const time_t * timep);


函數說明 
將參數timep所指的time_t結構中的信息轉換成真實世界所使用的時間日期表示方法,然後將結果由結構tm返回。結構tm的定義請參考上面。此函數返回的時間日期已經轉換成當地時區。


返回值 
返回結構tm代表目前的當地時間。

 

gmtime(取得當地目前時間和日期) 
函數定義 
struct tm *gmtime()(const time_t * timep);


函數說明 
將日曆時間轉化爲世界標準時間(即格林尼治時間),並返回一個tm結構體來保存這個時間


返回值 
返回結構tm代表目前的當地時間。

 

上面這個兩個函數的參數和返回值都一樣,唯一區別是localtime做了時區處理,返回當前時區的時間,而gmtime返回UTC時間

 

範例

Cpp代碼 複製代碼 收藏代碼
  1. #include <stdio.h>   
  2. #include <time.h>   
  3.   
  4. int main(int argc, char**argv)   
  5. {   
  6.     const char *wday[]={"星期天","星期一","星期二","星期三","星期四","星期五","星期六"};    
  7.   
  8.     time_t timeNow = time(NULL);   
  9.   
  10.     struct tm* p = localtime(&timeNow);    
  11.   
  12.     struct tm* pp;   
  13.   
  14.     printf("%d年%d月%d日 %d:%d:%d %s\n",p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec, wday[p->tm_wday]);    
  15.   
  16.     pp = gmtime(&timeNow);   
  17.   
  18.     printf("%d年%d月%d日 %d:%d:%d %s\n",pp->tm_year+1900,pp->tm_mon+1,pp->tm_mday,pp->tm_hour,pp->tm_min,pp->tm_sec, wday[pp->tm_wday]);    
  19.   
  20.     return 0;   
  21. };  
  1. #include <stdio.h>  
  2. #include <time.h>  
  3.   
  4. int main(int argc, char**argv)  
  5. {  
  6.     const char *wday[]={"星期天","星期一","星期二","星期三","星期四","星期五","星期六"};   
  7.   
  8.     time_t timeNow = time(NULL);  
  9.   
  10.     struct tm* p = localtime(&timeNow);   
  11.   
  12.     struct tm* pp;  
  13.   
  14.     printf("%d年%d月%d日 %d:%d:%d %s\n",p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec, wday[p->tm_wday]);   
  15.   
  16.     pp = gmtime(&timeNow);  
  17.   
  18.     printf("%d年%d月%d日 %d:%d:%d %s\n",pp->tm_year+1900,pp->tm_mon+1,pp->tm_mday,pp->tm_hour,pp->tm_min,pp->tm_sec, wday[pp->tm_wday]);   
  19.   
  20.     return 0;  
  21. };  

 

輸出結果
2010年4月1日 15:16:22 星期四
2010年4月1日 7:16:22 星期四


  其中localtime的結果和當前系統時間相同,gmtime比當前時間少8個小時

 

  注意:由於localtime和gmtime都使用全局變量存儲結果,所以在使用時一定要注意,特別是在多線程中,他們都不是線程安全的函數


範例

Cpp代碼 複製代碼 收藏代碼
  1. #include <stdio.h>   
  2. #include <time.h>   
  3.   
  4. int main(int argc, char**argv)   
  5. {   
  6.     time_t timeNow = time(NULL);   
  7.     struct tm *p = localtime(&timeNow);    
  8.   
  9.     struct tm *pp;   
  10.     timeNow += 10000;   
  11.     pp = localtime(&timeNow);   
  12.   
  13.     printf("當前時間:%d年%d月%d日 %d:%d:%d\n",p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec );    
  14.     printf("相加後時間:%d年%d月%d日 %d:%d:%d\n",pp->tm_year+1900,pp->tm_mon+1,pp->tm_mday,pp->tm_hour,pp->tm_min,pp->tm_sec );    
  15.   
  16.     return 0;   
  17. };  
  1. #include <stdio.h>  
  2. #include <time.h>  
  3.   
  4. int main(int argc, char**argv)  
  5. {  
  6.     time_t timeNow = time(NULL);  
  7.     struct tm *p = localtime(&timeNow);   
  8.   
  9.     struct tm *pp;  
  10.     timeNow += 10000;  
  11.     pp = localtime(&timeNow);  
  12.   
  13.     printf("當前時間:%d年%d月%d日 %d:%d:%d\n",p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec );   
  14.     printf("相加後時間:%d年%d月%d日 %d:%d:%d\n",pp->tm_year+1900,pp->tm_mon+1,pp->tm_mday,pp->tm_hour,pp->tm_min,pp->tm_sec );   
  15.   
  16.     return 0;  
  17. };  

 

輸出:
當前時間:2010年4月1日 18:42:46
相加後時間:2010年4月1日 18:42:46


雖然後面的時間加了10000秒,但由於他們共用同樣的全局變量,所以兩個的時間是一樣的

 

mktime(將時間結構數據轉換成經過的秒數)

函數定義
time_t mktime(strcut tm * timeptr);


函數說明 
mktime()用來將參數timeptr所指的tm結構數據轉換成從公元1970年1月1日0時0分0 秒算起至今的UTC時間所經過的秒數。


返回值 
返回經過的秒數。


注意:這裏傳入的參數必須是本地時間,不然就亂了

 

範例

Cpp代碼 複製代碼 收藏代碼
  1. #include <stdio.h>   
  2. #include <time.h>   
  3.   
  4. int main(int argc, char**argv)   
  5. {   
  6.     time_t timeNow = time(NULL);   
  7.   
  8.     struct tm* p = localtime(&timeNow);    
  9.   
  10.     time_t timeNow1 = mktime(p);    
  11.   
  12.     struct tm* pp = gmtime(&timeNow);   
  13.   
  14.     time_t timeNow2 = mktime(pp);   
  15.   
  16.     printf("%ld\n%ld\n%ld\n", timeNow, timeNow1, timeNow2);   
  17.   
  18.     return 0;   
  19. };  
  1. #include <stdio.h>  
  2. #include <time.h>  
  3.   
  4. int main(int argc, char**argv)  
  5. {  
  6.     time_t timeNow = time(NULL);  
  7.   
  8.     struct tm* p = localtime(&timeNow);   
  9.   
  10.     time_t timeNow1 = mktime(p);   
  11.   
  12.     struct tm* pp = gmtime(&timeNow);  
  13.   
  14.     time_t timeNow2 = mktime(pp);  
  15.   
  16.     printf("%ld\n%ld\n%ld\n", timeNow, timeNow1, timeNow2);  
  17.   
  18.     return 0;  
  19. };  

 

輸出結果
1270106860
1270106860
1270078060


可以發現當傳UTC時間給mktime的時候,就還原不回去了,會比當前時間少28800秒,剛好8個小時

 


夏令時間
    夏令時比標準時快一個小時。例如,在夏令時的實施期間,標準時間的上午10點就成了夏令時的上午11點。


  夏令時,又稱“日光節約時制”或“夏時制”,是一種爲節約能源而人爲規定地方時間的制度,在這一制度實行期間所採用的統一時間稱爲“夏令時間”。一般在天亮早的夏季人爲將時間提前一小時,可以使人早起早睡,減少照明量,以充分利用光照資源,從而節約照明用電。各個採納夏令時的國傢俱體規定不同。目前全世界有近110個國家每年要實行夏令時。(各時區多數位於其理想邊界之西,導致實際上全年實施夏令時。),中國現在已經不實行夏令時

 

範例

Cpp代碼 複製代碼 收藏代碼
  1. #include <stdio.h>   
  2. #include <time.h>   
  3.   
  4. int main(int argc, char**argv)   
  5. {   
  6.     time_t timeNow = time(NULL);   
  7.   
  8.     struct tm p = *(localtime(&timeNow));    
  9.     struct tm pp = p;   
  10.   
  11.     printf("當前時間:%ld\n", mktime(&p));   
  12.   
  13.     pp.tm_isdst = 1;   
  14.   
  15.     printf("啓動夏令時後的時間:%ld\n", mktime(&pp));   
  16.   
  17.     return 0;   
  18. };  
  1. #include <stdio.h>  
  2. #include <time.h>  
  3.   
  4. int main(int argc, char**argv)  
  5. {  
  6.     time_t timeNow = time(NULL);  
  7.   
  8.     struct tm p = *(localtime(&timeNow));   
  9.     struct tm pp = p;  
  10.   
  11.     printf("當前時間:%ld\n", mktime(&p));  
  12.   
  13.     pp.tm_isdst = 1;  
  14.   
  15.     printf("啓動夏令時後的時間:%ld\n", mktime(&pp));  
  16.   
  17.     return 0;  
  18. };  

 
輸出:
當前時間:1270109197
啓動夏令時後的時間:1270109197

 

從這裏的輸出發現,設置這個值好像沒什麼用處,同時我試了下調試運行,發現執行了mktime(&pp)後,pp中的tm_isdst又等於0了
暫時沒發現tm_isdst變量的實際用途


還有一點要注意,struct tm結構體中字段tm_mday的值是從1開始,所以在構造月初時間的時候一定要把這個字段置爲1

Cpp代碼 複製代碼 收藏代碼
  1. #include <stdio.h>   
  2. #include <time.h>   
  3.   
  4. int main(int argc, char**argv)   
  5. {   
  6.     time_t timeNow = time(NULL);   
  7.     struct tm *p = localtime(&timeNow); //取得當前時間   
  8.   
  9.     struct tm pp;   
  10.     memset(&pp, '\0'sizeof(pp));   
  11.     pp.tm_year = p->tm_year;   
  12.     pp.tm_mon = p->tm_mon;//設置成了當前月   
  13.        
  14.     time_t timePP = mktime(&pp);   
  15.   
  16.     printf("時間:%d年%d月%d日 %d:%d:%d\n",pp.tm_year+1900,pp.tm_mon+1,pp.tm_mday,pp.tm_hour,pp.tm_min,pp.tm_sec );    
  17.   
  18.     return 0;   
  19. };  
  1. #include <stdio.h>  
  2. #include <time.h>  
  3.   
  4. int main(int argc, char**argv)  
  5. {  
  6.     time_t timeNow = time(NULL);  
  7.     struct tm *p = localtime(&timeNow); //取得當前時間  
  8.   
  9.     struct tm pp;  
  10.     memset(&pp, '\0'sizeof(pp));  
  11.     pp.tm_year = p->tm_year;  
  12.     pp.tm_mon = p->tm_mon;//設置成了當前月  
  13.       
  14.     time_t timePP = mktime(&pp);  
  15.   
  16.     printf("時間:%d年%d月%d日 %d:%d:%d\n",pp.tm_year+1900,pp.tm_mon+1,pp.tm_mday,pp.tm_hour,pp.tm_min,pp.tm_sec );   
  17.   
  18.     return 0;  
  19. };  

 
輸出結果:時間:2010年3月31日 0:0:0

 

我們期待的輸出是“2010年4月1日 0:0:0”,但由於pp.tm_mday等於0,所以最後得到的時間timePP是上個月月底,相差了一天,正確的做法是設置pp.tm_mday等於1

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