C++14系列(2):C/C++的時間函數
C++筆記開始
為了好好研究下C++14。順便復習下曾經的C++知識。搞了個git(不斷完好中):
https://github.com/rododo/cpp14examples.git
裏面會慢慢封裝一些經常使用的函數。並做一些測試驗證。project是建立在Ubuntu的Eclipse之上,見系列(1)環境搭建。
經常使用的時間函數
參考:
http://blog.chinaunix.net/uid-24517893-id-363870.html
時間函數經常使用到的幾個概念:Calendar Time(日歷時間)。epoch(時間點),clock tick(時鐘計時單元)Coordinated Universal Time(UTC):世界標準時間,即格林威治標準時間(Greenwich Mean Time,GMT)。
epoch:時間點。
在標準C/C++中是一個整數,它用當前的時間和標準時間點的相差秒數來表示。它能夠理解成日歷時間,由於它已經是一個差值了。
日歷時間(Calendar Time),是用“從一個標準時間點到此時的時間經過的秒數”來表示的時間。
clock tick:時鐘計時單元。一個時鐘計時單元的時間長短是由CPU控制的。一個clock tick不是CPU的一個時鐘周期。而是C/C++的一個基本計時單位。
進程的CPU使用時間計時
C/C++中的cpu使用計時函數是clock(),而與其相關的數據類型是clock_t。這個函數返回從“開啟這個程序進程”到“程序中調用clock()函數”時之間的CPU時鐘計時單元(clock tick)數。當中clock_t是用來保存時間的數據類型。
clock_t是一個長整形數。在time.h文件裏,還定義了一個常量CLOCKS_PER_SEC,它用來表示一秒鐘會有多少個時鐘計時單元,例如以下打印的是進程執行至今占用的cpu時間秒數。而且它是算單核的秒數,假設這個程序是多線程的。core1和core2同一時候被某程序的兩個線程使用了5s的cpu執行時間片。那麽此時打印的應該是10s(已經驗證)。
printf("Elapsed time:%u secs.\n",clock()/CLOCKS_PER_SEC);
日歷時間
在C/C++中通過 < time.h > 裏的time函數獲得日歷時間。日歷時間(Calendar Time)是通過time_t數據類型來表示的。用time_t表示的時間(日歷時間)是從一個時間點(比如:1970年1月1日0時0分0秒)到此時的秒數。time_t實際上是長整型。
用time()函數結合其它函數(如:localtime、gmtime、asctime、ctime)能夠獲得當前系統時間或是標準時間。
time_t time(time_t * timer );
日歷時間(秒)與日期(年月日)關系
在標準C/C++中。我們可通過tm結構來獲得日期。tm結構在time.h中有定義,相當於一個包括了年月日小時分鐘等的結構體。
ANSI C標準稱使用tm結構的這樣的時間表示為分解時間(broken-down time)。
而日歷時間(Calendar Time)是從一個時間點到此時的秒數,類型比較簡單。
在time.h頭文件裏,我們還能夠看到一些函數,它們都是以time_t為參數類型或返回值類型的函數:
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還提供了兩種不同的函數將日歷時間(一個用time_t表示的整數)轉換為我們平時看到的把年月日時分秒分開顯示的時間格式tm:
struct tm * gmtime(const time_t *timer);
struct tm * localtime(const time_t * timer);
固定的日期格式打印
使用函數:
char * asctime(const struct tm * timeptr);
char * ctime(const time_t *timer);
打印結果:
比如 Wed Jan 02 02:03:55 1980\n\0
當中asctime()函數是通過tm結構來生成字符串。所以能夠傳給世界時間或者本地時間,而ctime()是通過日歷時間來生成字符串。ctime()函數須要先參照本地的時間設置,把日歷時間轉化為本地時間,然後再生成格式化後的字符串。所以一般其打印的是本地時間字符串。
自己定義的日期格式打印
使用strftime()函數將時間格式化為想要的格式。它的原型例如以下:
size_t strftime(
char *strDest,
size_t maxsize,
const char *format,
const struct tm *timeptr
);
樣例:
strftime(str,100,"It is now %I %p",ptr);
printf(str);
其執行結果為:
It is now 4PM
樣例:
strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime);
printf(tmpbuf);
執行結果:
Today is Saturday, day 30 of July in the year 2005.
分解時間轉化為日歷時間
分解時間,在C/C++中指tm結構。我們能夠使用mktime()函數將tm結構轉化為日歷時間。其函數原型例如以下:
time_t mktime(struct tm * timeptr);
< sys/time.h >的計時函數
除了上述的標準C/C++用到的時間函數外,Linux系統也提供了一個函數。能夠精確到微秒。
這就是gettimeofday函數,它獲得的時間精確到微秒(1e-6 s)量級。
在一段代碼前後分別使用例如以下:
struct timeval tv_begin, tv_end;
gettimeofday(&tv_begin, NULL);
foo();
gettimeofday(&tv_end, NULL);
結構體timeval的定義為:
struct timeval{
long int tv_sec; // 秒數
long int tv_usec; // 微秒數
}
time僅僅能返回秒級的返回值。而該結構體能精確到微秒級。
該函數和time函數一樣都是按真實世界的時間來計算的。
總結
本文介紹了C/C++中的有關日期和時間的概念,並通過各種實例講述了這些函數和數據結構的用法。
假設要測試優化的程序的執行效率,一般測量進程在cpu上使用的時間片之和,能夠用clock函數,clock函數並不代表真實世界的時間。
真實世界的時間則是time或者gettimeofday函數得到的。它們也能夠用於日期的顯示。
C++14系列(2):C/C++的時間函數