日期與unix時間戳之間的轉換C++實現

之前在https://blog.csdn.net/fengbingchun/article/details/107023645 中介紹過gmtime和localtime的區別,這裏介紹下日期與Unix時間戳之間轉換的實現,其中也會用到這兩個函數。

Unix時間戳(Unix timestamp):是一種時間表示方式,定義爲從格林威治時間(Greenwich Mean Time, GMT)1970年01月01日00時00分00秒起至現在的總秒數。如果操作系統使用32位二進制數字表示時間,則此類系統的Unix時間戳最多可以使用到格林威治時間2038年01月19日03時14分07秒(二進制: 01111111 11111111 11111111 11111111)。

時區:地球上的區域使用同一個時間定義。由於世界各國家與地區經度不同,地方時也有所不同,因此會劃分爲不同的時區。正式的時區劃分包括24個時區,每一時區由一個英文字母表示。每差一個時區,區時相差一個小時,相差多少個時區,就相差多少個小時。爲了照顧到各地區的使用方便,又使其它地方的人容易將本地的時間換算到別的地方時間上去。有關國際會議決定將地球表面按經線從東到西,劃成一個個區域,並且規定相鄰區域的時間相差1小時。在同一區域內的東端和西端的人看到太陽昇起的時間最多相差不過1小時。當人們跨過一個區域,就將自己的時鐘校正1小時(向西減1小時,向東加1小時),跨過幾個區域就加或減幾小時。例如,中國東8區的時間總比泰國東7區的時間早1小時,而比日本東9區的時間晚1小時。因此,出國旅行的人,必須隨時調整自己的手錶,才能和當地時間相一致。凡向西走,每過一個時區,就要把表撥慢1小時(比如2點撥到1點);凡向東走,每過一個時區,就要把表撥快1小時(比如1點撥到2點)。並且規定英國(格林尼治天文臺舊址)爲本初子午線,即零度經線。

本地時間(locale time):可由localtime函數獲得,在中國爲UTC+08:00,或稱北京時間或東八時區。

協調世界時(Coordinated Universal Time, UTC):或世界標準時間,UTC的表示方式爲:年、月、日、時、分、秒,均用數字表示。可以認爲格林威治時間就是協調世界時(GMT=UTC),格林威治時間和UTC時間均有秒數來計算。

C語言中一些常用的函數:

(1).time_t:時間類型,基礎算術類型的別名,能夠表示時間,通常是一個大整數值,該整數值表示自UTC時間1970年1月1日00:00:00時起經過的秒數(即Unix時間戳)。

(2).struct tm:時間結構體,包含日曆日期和時間的結構體,該結構體包含int類型的9個成員。

(3).time:獲取當前時間,返回time_t,如果參數不是空指針,還將此值設置爲參數指向的對象。返回的值通常代表自1970年1月1日00:00:00時起經過的秒數(即本地時間的Unix時間戳)。

(4).ctime:將time_t轉換爲字符串,返回char*。此函數等價於asctime(localtime(time_t))。

(5).asctime:將tm結構體轉換爲字符串,返回char*。

(6).strftime:將tm結構體轉換爲字符串,返回size_t。

(7).localtime:將time_t轉換爲本地時間,返回tm結構體。

(8).gmtime:將time_t轉換爲UTC時間,返回tm結構體。

(9).difftime:計算兩個time_t之間的時間差(以秒爲單位),返回double。

(10).mktime:將tm結構體轉換爲time_t,返回類型爲time_t,本地時間,如無法表示日曆時間,則返回值爲-1。

以上函數用法的測試代碼段如下:

void test_time()
{
	time_t rawtime = time(nullptr); //time_t rawtime; time(&rawtime);

	struct tm* timeinfo = localtime(&rawtime);
	fprintf(stdout, "The current local date/time is: %s", asctime(timeinfo));

	timeinfo = gmtime(&rawtime);
	fprintf(stdout, "The current utc date/time is: %s", asctime(timeinfo));

	fprintf(stdout, "The current local date/time is: %s", ctime(&rawtime));

	timeinfo = localtime(&rawtime);
	timeinfo->tm_hour = timeinfo->tm_min = timeinfo->tm_sec = timeinfo->tm_mon = 0; timeinfo->tm_mday = 1;
	fprintf(stdout, "%.f seconds since new year in the current timezone\n", difftime(rawtime, mktime(timeinfo)));

	timeinfo = localtime(&rawtime);
	char buffer[64];
	strftime(buffer, 64, "Now it's %I:%M%p", timeinfo);
	fprintf(stdout, "buffer: %s\n", buffer);
}

執行結果如下:

下面測試代碼段是本地時間的日期與時間戳之間的轉換:可通過localtime和mktime函數實現

void test_date_to_timestamp_local()
{
	// timestamp --> date
	time_t timestamp = time(nullptr);
	struct tm* timeinfo = localtime(&timestamp);
	int year = timeinfo->tm_year + 1900; // years since 1900
	int month = timeinfo->tm_mon + 1; // monthes since January - [0, 11]
	int day = timeinfo->tm_mday;
	int date = year * 10000 + month * 100 + day;
	int hour = timeinfo->tm_hour;
	int minute = timeinfo->tm_min;
	int second = timeinfo->tm_sec;
	fprintf(stdout, "timestamp: %ld, date: %d %.2d:%.2d:%.2d\n", timestamp, date, hour, minute, second);

	// date --> timestamp
	int date2 = 20211122;
	struct tm timeinfo2;
	memset(&timeinfo2, 0, sizeof(struct tm));
	timeinfo2.tm_year = date2 / 10000 - 1900;
	timeinfo2.tm_mon = date2 % 10000 / 100 - 1;
	timeinfo2.tm_mday = date2 % 100;
	time_t timestamp2 = mktime(&timeinfo2);
	fprintf(stdout, "date2: %d, timestamp2: %ld\n", date2, timestamp2);
}

執行結果如下:

下面測試代碼段是UTC的日期與時間戳之間的轉換:Linux下通過gmtime和timegm函數,Windows下通過gmtime和_mkgmtime函數。

#ifdef _MSC_VER
#define timegm _mkgmtime
#endif

void test_date_to_timestamp_utc()
{
	// timestamp --> date
	time_t timestamp = 86470; // 1day = 24 * 60 * 60 = 86400
	struct tm* timeinfo = gmtime(&timestamp);
	int year = timeinfo->tm_year + 1900; // years since 1900
	int month = timeinfo->tm_mon + 1; // monthes since January - [0, 11]
	int day = timeinfo->tm_mday;
	int date = year * 10000 + month * 100 + day;
	int hour = timeinfo->tm_hour;
	int minute = timeinfo->tm_min;
	int second = timeinfo->tm_sec;
	fprintf(stdout, "timestamp: %ld, date: %d %.2d:%.2d:%.2d\n", timestamp, date, hour, minute, second);

	// date --> timestamp
	int date2 = 19700102;
	struct tm timeinfo2;
	memset(&timeinfo2, 0, sizeof(struct tm));
	timeinfo2.tm_year = date2 / 10000 - 1900;
	timeinfo2.tm_mon = date2 % 10000 / 100 - 1;
	timeinfo2.tm_mday = date2 % 100;
	time_t timestamp2 = timegm(&timeinfo2);
	fprintf(stdout, "date2: %d, timestamp2: %ld\n", date2, timestamp2);
}

執行結果如下:

GitHubhttps://github.com/fengbingchun/Messy_Test

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