日期與unix時間戳之間的轉換C++實現
技術標籤:C/C++/C++11unix timestamp
之前在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(×tamp);
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(×tamp);
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);
}
執行結果如下: