C++時間操做

C支持的平常時間格式或種類html

一、時間值 time_t安全

時間值是指從1970-01-01 00:00:00 +0000 (UTC) 這個時間點開始到當前時間的秒數。
在C語言中,用time_t來表示一個秒數,查看頭文件能夠發現time_t是對long的一個重定義而已。
相關函數:time()多線程

二、時間詳情 struct tmapp

有了具體的時間值time_t,但存在着閱讀和理解不方便的問題,因此但願能夠把時間值轉化爲相應的年、月、日、時、分、秒等數據。
對應的結構體爲struct tm。以下代碼:函數

 1 struct tm {
 2    int tm_sec;    /* 秒,取值範圍(0~59),但當遇到閏秒時則會有60秒的取值。 */
 3    int tm_min;    /* 分鐘數,取值範圍(0-59) */
 4    int tm_hour;   /* 小時數,取值範圍(0-23) */
 5    int tm_mday;   /* 當天在這個月中是第幾天,取值範圍(1-31) */
 6    int tm_mon;    /* 當前月份是第幾個月,取值範圍(0-11) */
 7    int tm_year;   /* 從1900年開始至今的年數,即(Year - 1900)的值 */
 8    int tm_wday;   /* 當天在本週是第幾天,取值範圍(0-6, Sunday = 0) */
 9    int tm_yday;   /* 當天在今年是第幾天,取值範圍(0-365, 1 Jan = 0) */
10    int tm_isdst;  /* 夏令時標記,值大於0表示夏令時生效;等於0表示夏令時失效;小於0表示數據不可用。 */
11    char *tm_zone; /* 時區名稱,根據系統不一樣可能不被聲明或不一樣全名。 */
12 };

相關函數:localtime()、gmtime()this

三、時間字符串 char *spa

有了年、月、日等具體的數據,C也提供函數將數據轉爲轉爲可視的、有意義的字符串。
相關函數:線程

固定格式時間文本:ctime()、asctime()指針

自定義格式時間文本: strftime()code

 

平常時間函數的調用關係

獲取當前時間值

time_t time(time_t *t);
time_t mktime(struct tm *tm);
time()能夠從當前系統中獲取時間值並返回,若是參數t不爲NULL,則時間值一樣也會存儲中t中。
若是函數執行異常,則返回-1,可經過errno查詢出錯緣由。
mktime()則是將struct tm逆解析爲time_t的函數。
若是參數tm是由用戶本身組裝的,則tm中的tm_wdaytm_yday會在本函數執行後根據tm中的tm_year``tm_mon…等字段計算爲真實的值。

例子1:

 1 #include <stdio.h>
 2 #include <time.h>
 3 
 4 int main ()
 5 {
 6   time_t seconds;
 7 
 8   seconds = time(NULL);
 9   printf("自 1970-01-01 起的小時數 = %ld\n", seconds/3600);
10   
11   return(0);
12 }

運行結果:

自 1970-01-01 起的小時數 = 420254

 

例子2:

 1 #include <stdio.h>
 2 #include <time.h>
 3 
 4 int main ()
 5 {
 6    int ret;
 7    struct tm info;
 8    char buffer[80];
 9 
10    info.tm_year = 2001 - 1900;
11    info.tm_mon = 7 - 1;
12    info.tm_mday = 4;
13    info.tm_hour = 0;
14    info.tm_min = 0;
15    info.tm_sec = 1;
16    info.tm_isdst = -1;
17 
18    ret = mktime(&info);
19    if( ret == -1 )
20    {
21        printf("錯誤:不能使用 mktime 轉換時間。\n");
22    }
23    else
24    {
25       strftime(buffer, sizeof(buffer), "%c", &info );
26       print(buffer);
27    }
28 
29    return(0);
30 }

運行結果:

Wed Jul 4 00:00:01 2001

 

獲取時間詳情

時間詳情也就是上文所說的struct tm,manual中也把struct tm稱爲broken-down time。相關函數:

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

gmtime()localtime()均可以把時間值轉換爲時間詳情,二者的區別在於gmtime()所獲得的結果是世界標準時間Coordinated Universal Time (UTC);而localtime()獲取的是本地時間。以北京時間爲例,gmtime()獲得的結果比localtime()要提早(早)8小時。

gmtime_r()localtime_r()分別是gmtime()localtime()的可重入實現版本。

爲何有了localtime()還要有其餘兩個函數呢,由於localtime並非線程安全的,觀察localtime()localtime_r()的調用發現,localtime在使用時,咱們只需定義一個指針,並不須要爲指針申請空間,而指針必需要指向內存空間纔可使用,其實申請空間的動做由函數本身完成,這樣在多線程的狀況下,若是有另外一個線程調用了這個函數,那麼指針指向的struct tm結構體的數據就會改變。在localtime_s()localtime_r()調用時,定義的是struct tm的結構體,獲取到的時間已經保存在struct tm中,並不會受其餘線程的影響。

當函數執行錯誤時,則返回NULL,可經過errno查詢出錯緣由。

例子1:

 1 #include <stdio.h>
 2 #include <time.h>
 3 
 4 #define BST (+1)
 5 #define CCT (+8)
 6 
 7 int main ()
 8 {
 9 
10    time_t rawtime;
11    struct tm *info;
12 
13    time(&rawtime);
14    /* 獲取 GMT 時間 */
15    info = gmtime(&rawtime );
16    
17    printf("當前的世界時鐘:\n");
18    printf("倫敦:%2d:%02d\n", (info->tm_hour+BST)%24, info->tm_min);
19    printf("中國:%2d:%02d\n", (info->tm_hour+CCT)%24, info->tm_min);
20 
21    return(0);
22 }

運行結果:

當前的世界時鐘:
倫敦:15:58
中國:22:58

 

例子2:

 1 #include <stdio.h>
 2 #include <time.h>
 3 
 4 int main ()
 5 {
 6    time_t rawtime;
 7    struct tm *info;
 8    char buffer[80];
 9 
10    time( &rawtime );
11 
12    info = localtime( &rawtime );
13    printf("當前的本地時間和日期:%s", asctime(info));
14 
15    return(0);
16 }

運行結果:

當前的本地時間和日期:Sun Dec 10 22:57:38 2017

 

例子3:

 1 #include <stdio.h>  
 2 #include <time.h>  
 3   
 4 int main()  
 5 {  
 6     time_t time_seconds = time(0);  
 7     struct tm now_time;  
 8     localtime_r(&time_seconds, &now_time);  
 9   
10     printf("%d-%d-%d %d:%d:%d\n", now_time.tm_year + 1900, now_time.tm_mon + 1,  
11         now_time.tm_mday, now_time.tm_hour, now_time.tm_min, now_time.tm_sec);  
12 } 

運行結果:

2017-12-11 14:28:11

 

格式化的時間字符串

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

asctime()能直接從時間詳情中計算出時間字符串,該字符串包含字符串終止符,計算出來的時間字符串格式是固定的,示例爲:Wed Jun 30 21:49:08 1993\n
ctime()則是asctime(localtime(time_t))的封裝實現。

asctime_r()ctime_r()分別是asctime()ctime()的可重入實現版本。

注意:以上函數返回的字符串都會包含換行符\n

例子1:

 1 #include <stdio.h>
 2 #include <time.h>
 3 
 4 int main ()
 5 {
 6    time_t curtime;
 7 
 8    time(&curtime);
 9 
10    printf("當前時間 = %s", ctime(&curtime));
11 
12    return(0);
13 }

運行結果:

當前時間 = Sun Dec 10 22:58:54 2017

 

例子2:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <time.h>
 4 
 5 int main()
 6 {
 7    struct tm t;
 8 
 9    t.tm_sec    = 10;
10    t.tm_min    = 10;
11    t.tm_hour   = 6;
12    t.tm_mday   = 25;
13    t.tm_mon    = 2;
14    t.tm_year   = 89;
15    t.tm_wday   = 6;
16 
17    puts(asctime(&t));
18    
19    return(0);
20 }

運行結果:

Sat Mar 25 06:10:10 1989

 

size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);

C語言爲了格式化輸出時間信息又提供了強大的格式化函數strftime(),支持按自定義的格式打印出完整可閱讀的時間信息,包括月份的全稱或簡稱,或只選擇某些關鍵時間值進行輸出。
參數s指向格式化後的時間字符串。
參數max表示時間字符串的最大字符數(含字符串終止符)。
參數format表示時間字符串的格式化表達式。
參數tm表示待格式化的時間詳情。

其中format表達式支持格式化參數與字符混合使用,且所支持的格式化參數很是多,具體以下:

說明符 替換爲 實例
%a 縮寫的星期幾名稱 Sun
%A 完整的星期幾名稱 Sunday
%b 縮寫的月份名稱 Mar
%B 完整的月份名稱 March
%c 日期和時間表示法 Sun Aug 19 02:56:02 2012
%d 一月中的第幾天(01-31) 19
%H 24 小時格式的小時(00-23) 14
%I 12 小時格式的小時(01-12) 05
%j 一年中的第幾天(001-366) 231
%m 十進制數表示的月份(01-12) 08
%M 分(00-59) 55
%p AM 或 PM 名稱 PM
%S 秒(00-61) 02
%U 一年中的第幾周,以第一個星期日做爲第一週的第一天(00-53) 33
%w 十進制數表示的星期幾,星期日表示爲 0(0-6) 4
%W 一年中的第幾周,以第一個星期一做爲第一週的第一天(00-53) 34
%x 日期表示法 08/19/12
%X 時間表示法 02:50:06
%y 年份,最後兩個數字(00-99) 01
%Y 年份 2012
%Z 時區的名稱或縮寫 CDT
%% 一個 % 符號 %

 

綜合例子:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <time.h>
 4 int main (int argc, char ** argv) {
 5     time_t calendar_time = time(NULL);
 6     printf("calendar_time :%ld \n", calendar_time);
 7     
 8     char * calendar_str = ctime(&calendar_time);
 9     printf("calendar_str  :%s \n", calendar_str);
10     
11     struct tm * tm_local = localtime(&calendar_time);
12     printf("localtime :year=%d mon=%d mday=%d hour=%d min=%d sec=%d   wday=%d yday=%d isdst=%d \n",
13            tm_local->tm_year + 1900, tm_local->tm_mon + 1, tm_local->tm_mday, tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec,
14            tm_local->tm_wday, tm_local->tm_yday, tm_local->tm_isdst);
15     
16     char * asc_time = asctime(tm_local);
17     printf("asc_time  :%s", asc_time);
18     char * c_time = ctime(&calendar_time);
19     printf("c_time    :%s", c_time);
20     
21     time_t mk_time = mktime(tm_local);
22     printf("\nmk_time   :%ld \n\n", mk_time);
23     
24     
25     char str_f_t [100];
26     strftime(str_f_t, sizeof(str_f_t), "%G-%m-%d %H:%M:%S", tm_local);
27     printf("local  :format=%s \n", str_f_t);
28     struct tm * gm_time = gmtime(&calendar_time);
29     strftime(str_f_t, sizeof(str_f_t), "%G-%m-%d %H:%M:%S", gm_time);
30     printf("gmtime :format=%s \n\n", str_f_t);
31     
32     struct tm my_tm = {2,2,2,16,2,2015,0,0,0};
33     time_t my_time_t = mktime(&my_tm);
34     printf("my yday:%d \n", my_tm.tm_yday);
35     
36     return 0;
37 }

運行結果:

calendar_time :1512916710 
calendar_str  :Sun Dec 10 22:38:30 2017
 
localtime :year=2017 mon=12 mday=10 hour=22 min=38 sec=30   wday=0 yday=343 isdst=0 
asc_time  :Sun Dec 10 22:38:30 2017
c_time    :Sun Dec 10 22:38:30 2017

mk_time   :1512916710 

local  :format=2017-12-10 22:38:30 
gmtime :format=2017-12-10 14:38:30 

my yday:74 

 

difftime

double difftime(time_t time1, time_t time2);

返回 time1 和 time2 之間相差的秒數 (time1 - time2)。這兩個時間是在日曆時間中指定的,表示了自紀元 Epoch(協調世界時 UTC:1970-01-01 00:00:00)起通過的時間。

 1 #include <stdio.h>
 2 #include <time.h>
 3 #ifdef _WIN32
 4 #include <Windows.h>
 5 #else
 6 #include <unistd.h>
 7 #endif
 8  
 9 int main ()
10 {
11    time_t start_t, end_t;
12    double diff_t;
13  
14    printf("程序啓動...\n");
15    time(&start_t);
16  
17    printf("休眠 5 秒...\n");
18    sleep(5);
19  
20    time(&end_t);
21    diff_t = difftime(end_t, start_t);
22  
23    printf("執行時間 = %f\n", diff_t);
24    printf("程序退出...\n");
25  
26    return(0);
27 }

運行結果:

程序啓動...
休眠 5 秒...
執行時間 = 5.000000
程序退出...

 

clock

clock_t clock(void);

返回程序執行起(通常爲程序的開頭),處理器時鐘所使用的時間。爲了獲取 CPU 所使用的秒數,須要除以 CLOCKS_PER_SEC。在 32 位系統中,CLOCKS_PER_SEC 等於 1000000,該函數大約每 72 分鐘會返回相同的值。本方法有必定缺陷,在32bit機器上,運行時間較長達到(超過1小時),有可能出現計時錯誤。
clock()文檔說明以下:
Note that the time can wrap around. On a 32-bit system where CLOCKS_PER_SEC equals 1000000 this function will return the same value approximately every 72 minutes.
所以,當出現計時爲負數或者很小的數時,須要人爲憑經驗加上若干個72minutes……

因此這個函數仍是不要用了!

例子:

 1 #include <time.h>
 2 #include <stdio.h>
 3  
 4 int main()
 5 {
 6    clock_t start_t, end_t;
 7    double total_t;
 8    int i;
 9  
10    start_t = clock();
11    printf("程序啓動,start_t = %ld\n", start_t);
12     
13    printf("開始一個大循環,start_t = %ld\n", start_t);
14    for(i=0; i< 10000000; i++)
15    {
16    }
17    end_t = clock();
18    printf("大循環結束,end_t = %ld\n", end_t);
19    
20    printf("CLOCKS_PER_SEC = %ld\n", CLOCKS_PER_SEC);
21    total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;
22    printf("CPU 佔用的總時間:%f\n", total_t  );
23    printf("程序退出...\n");
24  
25    return(0);
26 }

運行結果:

程序啓動,start_t = 549
開始一個大循環,start_t = 549
大循環結束,end_t = 25777
CLOCKS_PER_SEC = 1000000
CPU 佔用的總時間:0.025228
程序退出...

 

 

本文參考自:

http://sodino.com/2015/03/15/c-time/

http://www.runoob.com/cprogramming/c-standard-library-time-h.html

相關文章
相關標籤/搜索