C/C++編程筆記:C語(yǔ)言中time.h用法詳解(一),滿滿的都是干貨
本文從介紹基礎(chǔ)概念入手,探討了在C/C++中對(duì)日期和時(shí)間操作所用到的數(shù)據(jù)結(jié)構(gòu)和函數(shù),并對(duì)計(jì)時(shí)、時(shí)間的獲取、時(shí)間的計(jì)算和顯示格式等方面進(jìn)行了闡述。本文還通過大量的實(shí)例向你展示了time.h頭文件中聲明的各種函數(shù)和數(shù)據(jù)結(jié)構(gòu)的詳細(xì)使用方法。?

1.概念
在C/C++中,對(duì)字符串的操作有很多值得注意的問題,同樣,C/C++對(duì)時(shí)間的操作也有許多值得大家注意的地方。最近,在技術(shù)群中有很多網(wǎng)友也多次問到過C++語(yǔ)言中對(duì)時(shí)間的操作、獲取和顯示等等的問題。下面,在這篇文章中,筆者將主要介紹在C/C++中時(shí)間和日期的使用方法.
通過學(xué)習(xí)許多C/C++庫(kù),你可以有很多操作、使用時(shí)間的方法。但在這之前你需要了解一些“時(shí)間”和“日期”的概念,主要有以下幾個(gè):?
Coordinated Universal Time(UTC):協(xié)調(diào)世界時(shí),又稱為世界標(biāo)準(zhǔn)時(shí)間,也就是大家所熟知的格林威治標(biāo)準(zhǔn)時(shí)間(Greenwich Mean Time,GMT)。比如,中國(guó)內(nèi)地的時(shí)間與UTC的時(shí)差為+8,也就是UTC+8。美國(guó)是UTC-5。?
Calendar Time:日歷時(shí)間,是用“從一個(gè)標(biāo)準(zhǔn)時(shí)間點(diǎn)到此時(shí)的時(shí)間經(jīng)過的秒數(shù)”來表示的時(shí)間。這個(gè)標(biāo)準(zhǔn)時(shí)間點(diǎn)對(duì)不同的編譯器來說會(huì)有所不同,但對(duì)一個(gè)編譯系統(tǒng)來說,這個(gè)標(biāo)準(zhǔn)時(shí)間點(diǎn)是不變的,該編譯系統(tǒng)中的時(shí)間對(duì)應(yīng)的日歷時(shí)間都通過該標(biāo)準(zhǔn)時(shí)間點(diǎn)來衡量,所以可以說日歷時(shí)間是“相對(duì)時(shí)間”,但是無論你在哪一個(gè)時(shí)區(qū),在同一時(shí)刻對(duì)同一個(gè)標(biāo)準(zhǔn)時(shí)間點(diǎn)來說,日歷時(shí)間都是一樣的。?
epoch:時(shí)間點(diǎn)。時(shí)間點(diǎn)在標(biāo)準(zhǔn)C/C++中是一個(gè)整數(shù),它用此時(shí)的時(shí)間和標(biāo)準(zhǔn)時(shí)間點(diǎn)相差的秒數(shù)(即日歷時(shí)間)來表示。?
clock tick:時(shí)鐘計(jì)時(shí)單元(而不把它叫做時(shí)鐘滴答次數(shù)),一個(gè)時(shí)鐘計(jì)時(shí)單元的時(shí)間長(zhǎng)短是由CPU控制的。一個(gè)clock tick不是CPU的一個(gè)時(shí)鐘周期,而是C/C++的一個(gè)基本計(jì)時(shí)單位。?
我們可以使用ANSI標(biāo)準(zhǔn)庫(kù)中的time.h頭文件。這個(gè)頭文件中定義的時(shí)間和日期所使用的方法,無論是在結(jié)構(gòu)定義,還是命名,都具有明顯的C語(yǔ)言風(fēng)格。下面,我將說明在C/C++中怎樣使用日期的時(shí)間功能。?

2. 計(jì)時(shí)??
C/C++中的計(jì)時(shí)函數(shù)是clock(),而與其相關(guān)的數(shù)據(jù)類型是clock_t。在MSDN中,查得對(duì)clock函數(shù)定義如下:?
clock_t clock( void );?
這個(gè)函數(shù)返回從“開啟這個(gè)程序進(jìn)程”到“程序中調(diào)用clock()函數(shù)”時(shí)之間的CPU時(shí)鐘計(jì)時(shí)單元(clock tick)數(shù),在MSDN中稱之為掛鐘時(shí)間(wal-clock)。其中clock_t是用來保存時(shí)間的數(shù)據(jù)類型,在time.h文件中,我們可以找到對(duì)它的定義:?
#ifndef _CLOCK_T_DEFINED
typedef long clock_t;
#define _CLOCK_T_DEFINED
#endif
很明顯,clock_t是一個(gè)長(zhǎng)整形數(shù)。在time.h文件中,還定義了一個(gè)常量CLOCKS_PER_SEC,它用來表示一秒鐘會(huì)有多少個(gè)時(shí)鐘計(jì)時(shí)單元,其定義如下:?
#define CLOCKS_PER_SEC ((clock_t)1000)?
可以看到每過千分之一秒(1毫秒),調(diào)用clock()函數(shù)返回的值就加1。下面舉個(gè)例子,你可以使用公式clock()/CLOCKS_PER_SEC來計(jì)算一個(gè)進(jìn)程自身的運(yùn)行時(shí)間:?
void elapsed_time()
{
printf("Elapsed time:%u secs.\n",clock()/CLOCKS_PER_SEC);
}
當(dāng)然,你也可以用clock函數(shù)來計(jì)算你的機(jī)器運(yùn)行一個(gè)循環(huán)或者處理其它事件到底花了多少時(shí)間:

在筆者的編譯器上,運(yùn)行結(jié)果如下:?
Time to do 10000000 empty loops is 0.03000 seconds?
上面我們看到時(shí)鐘計(jì)時(shí)單元的長(zhǎng)度為1毫秒,那么計(jì)時(shí)的精度也為1毫秒,那么我們可不可以通過改變CLOCKS_PER_SEC的定義,通過把它定義的大一些,從而使計(jì)時(shí)精度更高呢?通過嘗試,你會(huì)發(fā)現(xiàn)這樣是不行的。在標(biāo)準(zhǔn)C/C++中,最小的計(jì)時(shí)單位是一毫秒。?

3.與日期和時(shí)間相關(guān)的數(shù)據(jù)結(jié)構(gòu)??
在標(biāo)準(zhǔn)C/C++中,我們可通過tm結(jié)構(gòu)來獲得日期和時(shí)間,tm結(jié)構(gòu)在time.h中的定義如下:?

ANSI C標(biāo)準(zhǔn)稱使用tm結(jié)構(gòu)的這種時(shí)間表示為分解時(shí)間(broken-down time)。?
而日歷時(shí)間(Calendar Time)是通過time_t數(shù)據(jù)類型來表示的,用time_t表示的時(shí)間(日歷時(shí)間)是從一個(gè)時(shí)間點(diǎn)(例如:1970年1月1日0時(shí)0分0秒)到此時(shí)的秒數(shù)。在time.h中,我們也可以看到time_t是一個(gè)長(zhǎng)整型數(shù):?

大家可能會(huì)產(chǎn)生疑問:既然time_t實(shí)際上是長(zhǎng)整型,到未來的某一天,從一個(gè)時(shí)間點(diǎn)(一般是1970年1月1日0時(shí)0分0秒)到那時(shí)的秒數(shù)(即日歷時(shí)間)超出了長(zhǎng)整形所能表示的數(shù)的范圍怎么辦?
對(duì)time_t數(shù)據(jù)類型的值來說,它所表示的時(shí)間不能晚于2038年1月18日19時(shí)14分07秒。為了能夠表示更久遠(yuǎn)的時(shí)間,一些編譯器廠商引入了64位甚至更長(zhǎng)的整形數(shù)來保存日歷時(shí)間。比如微軟在Visual C++中采用了__time64_t數(shù)據(jù)類型來保存日歷時(shí)間,并通過_time64()函數(shù)來獲得日歷時(shí)間(而不是通過使用32位字的time()函數(shù)),這樣就可以通過該數(shù)據(jù)類型保存3001年1月1日0時(shí)0分0秒(不包括該時(shí)間點(diǎn))之前的時(shí)間。
在time.h頭文件中,我們還可以看到一些函數(shù),它們都是以time_t為參數(shù)類型或返回值類型的函數(shù):?
double difftime(time_t time1, time_t time0);
time_t mktime(struct tm * timeptr);
time_t time(time_t * timer);
char * asctime(const struct tm * timeptr);
char * ctime(const time_t *timer);
此外,time.h還提供了兩種不同的函數(shù)將日歷時(shí)間(一個(gè)用time_t表示的整數(shù))轉(zhuǎn)換為我們平時(shí)看到的把年月日時(shí)分秒分開顯示的時(shí)間格式tm:?
struct tm * gmtime(const time_t *timer);
struct tm * localtime(const time_t * timer);
通過查閱MSDN,我們可以知道Microsoft C/C++ 7.0中時(shí)間點(diǎn)的值(time_t對(duì)象的值)是從1899年12月31日0時(shí)0分0秒到該時(shí)間點(diǎn)所經(jīng)過的秒數(shù),而其它各種版本的Microsoft C/C++和所有不同版本的Visual C++都是計(jì)算的從1970年1月1日0時(shí)0分0秒到該時(shí)間點(diǎn)所經(jīng)過的秒數(shù)。?
關(guān)于時(shí)間和日期的函數(shù)應(yīng)用,我們將在下節(jié)詳細(xì)闡述,希望對(duì)大家有幫助!

學(xué)習(xí)C/C++編程知識(shí),提升C/C++編程能力,歡迎關(guān)注UP一起來成長(zhǎng)!
另外,UP在主頁(yè)上傳了一些學(xué)習(xí)C/C++編程的視頻教程,有興趣或者正在學(xué)習(xí)的小伙伴一定要去看一看哦!會(huì)對(duì)你有幫助的~