c/c++時間操作函數總結

一、時區相關概念

地球自西往東轉動,東邊比西邊先看到太陽,所以東邊的時間比西邊的時間早。將地球經度按照24個時區進行劃分,每個時區相隔的經度爲15度。以英國倫敦(格林尼治天文臺舊址)爲中時區(零時區),向東有11個時區,向西也有11個時區,太平洋白令海峽所在經度爲12區,東西各佔一半。0時區向東每隔一個時區時間快1小時,向西每隔一個時區時間慢1小時。在12區中間,左邊剛好比右邊日期大1天。

UTC協調時間時間=世界標準時間=格林尼治時間=G.M.T(Greenwich Mean Time),指0時區所處的時間。

夏令時(陽光節約時/DST/Daylight Saving Time):因爲北半球大部分國家在夏天日照時間較長,爲了節約能源,讓人們充分利用太陽光源,某些國家在夏天會人爲地將時間設置快一個小時。例如美國每年3月的第二個星期日開始,至每年11月的第一個星期日爲夏令時。

二、計算機時間

1970-01-01 00:00:00是計算機元年,因爲Unix操作系統和C語言於1971年發佈,所以將這一時間作爲時間元年。

三、C庫時間操作函數

1、time

函數原型:time_t time(time_t* timer);

函數說明:獲取系統UTC時間到1970-01-01 00:00:00的秒數。timer爲NULL,通過返回值返回。也可以通過timer參數返回。time_t在32位系統下最大隻能表示到2038-01-19 03:14:07,在64位系統下則完全夠用

2、localtime

函數原型:struct tm* localtime(const timer_t* timer);

tm結構:

         struct tm
         {
             int tm_sec;         /* 秒,範圍從 0 到 59      */
             int tm_min;         /* 分,範圍從 0 到 59      */
             int tm_hour;        /* 小時,範圍從 0 到 23     */
             int tm_mday;        /* 一月中的第幾天,範圍從 1 到 31    */
             int tm_mon;         /* 月,範圍從 0 到 11  */
             int tm_year;        /* 自 1900 年起的年數      */
             int tm_wday;        /* 一週中的第幾天,範圍從 0 到 6 */
             int tm_yday;        /* 一年中的第幾天,範圍從 0 到 365   */
             int tm_isdst;       /* 夏令時               */
         };

函數說明:將time_t類型值轉換爲tm結構,採用本地時區

線程安全:locltime爲非線程安全函數,返回的爲內部靜態變量指針,linux下線程安全函數爲localtime_r(),windows下沒有

3、gmtime

函數原型:struct tm* gmtime(time_t* timer);

函數說明:將time_t類型值轉換爲tm結構,採用0時區

線程安全:linux下線程安全函數爲gmtime_r()

4、mktime

函數原型:time_t mktime(struct tm* timeptr);

函數說明:計算將timeptr按照系統時區轉換爲0時區,然後到計算機元年間的秒數

例子:

#include <time.h>
#include <stdio.h>

int main()
{
	time_t t = time(NULL);
    //or
    //time_t t;
    //time(&t);

	struct tm* tmLocalNow = localtime(&t);
	tmLocalNow->tm_year += 1900;
	tmLocalNow->tm_mon += 1;
	printf("local now datetime: %d.%02d.%02d %02d:%02d:%02d\n",
		tmLocalNow->tm_year,tmLocalNow->tm_mon,tmLocalNow->tm_mday,tmLocalNow->tm_hour,tmLocalNow->tm_min,tmLocalNow->tm_sec);

    struct tm* tmUTCNow = gmtime(&t);
	tmUTCNow->tm_year += 1900;
	tmUTCNow->tm_mon += 1;
	printf("UTC now datetime: %d.%02d.%02d %02d:%02d:%02d\n",
		tmUTCNow->tm_year,tmUTCNow->tm_mon,tmUTCNow->tm_mday,tmUTCNow->tm_hour,tmUTCNow->tm_min,tmUTCNow->tm_sec);

	return 0;
}

線程不安全例子:

#include <time.h>
#include <stdio.h>

int main()
{
	time_t t1 = time(NULL);
    time_t t2 += 1800;
    
    struct tm* tm1 = localtime(&t1);
    struct tm* tm2 = localtime(&t2);
    //執行到這裏的時候tm1值變爲tm2,因爲內部他們指向的是同一內存地址

	return 0;
}

5、Sleep/sleep/usleep

Sleep(毫秒)爲windows下掛起函數,精確到毫秒級

sleep(秒)爲linux下掛起函數,精確到秒級。

usleep(微秒)爲linux下掛起函數,精確到微秒級。

Sleep()在windows下掛起後仍然會佔用CPU處理時間,而sleep()和usleep()在linux下不會佔用

6、clock

函數原型:clock_t clock();

函數說明,返回從程序執行時起到現在,消耗的處理器時間(不是程序執行時間)對應的時鐘數,每秒鐘處理器的時鐘數爲CLOCKS_PER_SEC。

例子:

#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

#include <time.h>

int main()
{
	clock_t clockStart;
	clockStart = clock();
#ifdef WIN32
	Sleep(2000);
#else
	sleep(2);
#endif
	clock_t clockEnd;
	clockEnd = clock();
	double dInterval = (double)(clockEnd - clockStart) / CLOCKS_PER_SEC;
	printf("interval: %f\n", dInterval);
}

執行結果:

linux下爲0.000040,windows下爲2.001000,因爲linux下sleep()不佔用CPU處理時間,而windows下Sleep()下佔用系統時間。

四、linux時間系統函數

1、gettimeofday

獲取當前時間,返回從計算機元年到現在經歷的時間。

頭文件:

sys/time.h

unistd.h

函數聲明:int gettimeofday(struct timeval* tv, struct timezone* tz);

timeval結構定義爲: 

struct timeval

    long tv_sec; /*秒*/ 
    long tv_usec; /*微秒*/ 
}; 
timezone 結構定義爲: 
struct timezone

    int tz_minuteswest; /*和Greenwich 時間差了多少分鐘*/ 
    int tz_dsttime; /*日光節約時間的狀態*/ 
}; 
上述兩個結構都定義在/usr/include/sys/time.h。tz_dsttime 所代表的狀態如下 
DST_NONE /*不使用*/ 
DST_USA /*美國*/ 
DST_AUST /*澳洲*/ 
DST_WET /*西歐*/ 
DST_MET /*中歐*/ 
DST_EET /*東歐*/ 
DST_CAN /*加拿大*/ 
DST_GB /*大不列顛*/ 
DST_RUM /*羅馬尼亞*/ 
DST_TUR /*土耳其*/ 
DST_AUSTALT /*澳洲(1986年以後)*/
返回值:成功則返回0,失敗返回-1,錯誤代碼存於errno。附加說明EFAULT指針tv和tz所指的內存空間超出存取權限。

2、settimeofday()

設置當前時間,只有root權限才能使用此函數修改時間。

頭文件:

sys/time.h

unistd.h

函數聲明:int settimeofday(struct timeval* tv, struct timezone* tz);

返回值:成功則返回0,失敗返回-1,錯誤代碼存於errno。

錯誤代碼:
EPERM 並非由root權限調用settimeofday(),權限不夠。 
EINVAL 時區或某個數據是不正確的,無法正確設置時間。

3、clock_gettime

函數聲明:int clock_gettime(clockid_t clk_id,struct timespec* tp);

clk_id取值

CLOCK_REALTIME:系統從計算機元年到現在的時間,隨系統時間變化而變化

CLOCK_MONOTONIC:系統啓動到現在的時間,不隨系統時間變化而變化

CLOCK_PROCESS_CPUTIME_ID:本進程從啓動到現在CPU花費的時間,sleep和usleep不佔用cpu時間

CLOCK_THREAD_CPUTIME_ID:本線程從啓動到現在CPU花費的時間

timespec結構

struct timespec
{
        time_t tv_sec; /* 秒*/
        long tv_nsec; /* 納秒*/
};

五、windows時間系統函數

1、GetLocalTime

獲取當前系統時間,以系統時區爲標準,精確到毫秒級。

函數聲明:void GetLocalTime(LPSYSTEMTIME lpSystemTime);

SYSTMETIME結構定義:

typedef struct _SYSTEMTIME

{

WORD wYear;//年

WORD wMonth;//月

WORD wDayOfWeek;//星期

WORD wDay;//日

WORD wHour;//時

WORD wMinute;//分

WORD wSecond;//秒

WORD wMilliseconds;//毫秒

}SYSTEMTIME,*PSYSTEMTIME;

2、GetSystemTime

獲取當前系統時間,以0時區爲標準。

3、SetLocalTime

設置系統本地時間

4、SetSystemTime

設置系統UTC時間

5、GetTickCount

返回操作系統啓動到現在所經過的毫秒數

函數聲明:DWORD GetTickCount(void);

GetTickCount()和Clock()函數是向主板BIOS要real time clock時間,會有中斷產生,以及延遲問題。

6、QueryPerformaceFrequency和QueryPerformanceCounter

返回硬件支持的高精度計數器的頻率,返回系統從啓動到現在的時間。

函數聲明:

BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount);

參數類型定義如下:

typeef union _ LARGE_INTEGER

{

struct

{

DWORD LowPart;

LONG HighPart;

};

LONGLONG QuadPart;

} LARGE_INTEGER;

QueryPerformanceCounter獲取系統啓動到現在計數器時鐘數。QueryPerformanceFrequency獲取系統的時鐘頻率,也就是每秒系統的時鐘數。

例子:


#include <windows.h>

int main()
{
	LARGE_INTEGER lagerCounter1;
	QueryPerformanceCounter(&lagerCounter1);
	long long llCounter1 = lagerCounter1.QuadPart;

	Sleep(2000);

	LARGE_INTEGER lagerCounter2;
	QueryPerformanceCounter(&lagerCounter2);
	long long llCounter2 = lagerCounter2.QuadPart;

	LARGE_INTEGER largerFreq;
	QueryPerformanceFrequency(&largerFreq);
	long long llFreq = largerFreq.QuadPart;

	double dIntervals = (llCounter2 - llCounter1) / llFreq;
	printf("the interval is: %f",dIntervals);
}

例子輸出爲2.0。

 

參考:

1.https://blog.csdn.net/hmxz2nn/article/details/77986450

2.https://blog.csdn.net/tsx86/article/details/49965171

3.https://blog.csdn.net/weixin_34295316/article/details/86061183

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