轉(zhuǎn)載:https://www.cnblogs.com/renjiashuo/p/6913668.html
在c/c++實(shí)際問(wèn)題的編程中,我們經(jīng)常會(huì)用到日期與時(shí)間的格式,在算法運(yùn)行中,通常將時(shí)間轉(zhuǎn)化為int來(lái)進(jìn)行計(jì)算,而處理輸入輸出的時(shí)候,日期時(shí)間的格式卻是五花八門(mén),以各種標(biāo)點(diǎn)空格相連或者不加標(biāo)點(diǎn)。
首先,在c中,是有一個(gè)標(biāo)準(zhǔn)的日期時(shí)間結(jié)構(gòu)體的,在標(biāo)準(zhǔn)庫(kù)wchar.h內(nèi),我們可以看到結(jié)構(gòu)體tm的聲明如下:
1 #ifndef _TM_DEFINED 2 struct tm { 3 int tm_sec; /* seconds after the minute - [0,59] */ 4 int tm_min; /* minutes after the hour - [0,59] */ 5 int tm_hour; /* hours since midnight - [0,23] */ 6 int tm_mday; /* day of the month - [1,31] */ 7 int tm_mon; /* months since January - [0,11] */ 8 int tm_year; /* years since 1900 */ 9 int tm_wday; /* days since Sunday - [0,6] */ 10 int tm_yday; /* days since January 1 - [0,365] */ 11 int tm_isdst; /* daylight savings time flag */ 12 }; 13 #define _TM_DEFINED 14 #endif /* _TM_DEFINED */
由于各項(xiàng)英文注釋很好理解,這里只做簡(jiǎn)要補(bǔ)充。
1)注意月份是0-11,而不是1-12,所以在tm結(jié)構(gòu)體與string轉(zhuǎn)換的時(shí)候,要相應(yīng)的做減1加1處理。
2)tm_isdst為夏令時(shí)設(shè)置,0為非夏令時(shí),1為夏令時(shí)。由于21世紀(jì)的中國(guó)并沒(méi)有實(shí)行夏令時(shí)制度,所以編寫(xiě)國(guó)內(nèi)程序我們可以忽略這個(gè)變量。
利用這個(gè)結(jié)構(gòu)體,我們就可以完成日期時(shí)間與string字符串的轉(zhuǎn)換了,由于計(jì)算的方便,我們一般選擇將日期時(shí)間的string轉(zhuǎn)換成time_t類(lèi)型。
如果你非要int的話,我可以負(fù)責(zé)任的告訴你,time_t在visual studio環(huán)境下,就是"__int64"類(lèi)型的變量,它由typedef關(guān)鍵字在庫(kù)文件crtdefs.h里給定,所以,把time_t放心的拿去用就好了。
言歸正傳,這里,我們假定輸入的字符串格式為"2017-05-27 19:50:02",這個(gè)設(shè)定并不影響其他格式的字符串時(shí)間與可參與計(jì)算的變量的轉(zhuǎn)換,如果要參與轉(zhuǎn)換的日期字符串不是這個(gè)格式,讀者可自行更改下面給出代碼的對(duì)應(yīng)部分。
下面給出日期時(shí)間string轉(zhuǎn)換為time_t的函數(shù)代碼。
time_t StringToDatetime(string str) { char *cha = (char*)str.data(); // 將string轉(zhuǎn)換成char*。 tm tm_; // 定義tm結(jié)構(gòu)體。 int year, month, day, hour, minute, second;// 定義時(shí)間的各個(gè)int臨時(shí)變量。 sscanf(cha, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second);// 將string存儲(chǔ)的日期時(shí)間,轉(zhuǎn)換為int臨時(shí)變量。 tm_.tm_year = year - 1900; // 年,由于tm結(jié)構(gòu)體存儲(chǔ)的是從1900年開(kāi)始的時(shí)間,所以tm_year為int臨時(shí)變量減去1900。 tm_.tm_mon = month - 1; // 月,由于tm結(jié)構(gòu)體的月份存儲(chǔ)范圍為0-11,所以tm_mon為int臨時(shí)變量減去1。 tm_.tm_mday = day; // 日。 tm_.tm_hour = hour; // 時(shí)。 tm_.tm_min = minute; // 分。 tm_.tm_sec = second; // 秒。 tm_.tm_isdst = 0; // 非夏令時(shí)。 time_t t_ = mktime(&tm_); // 將tm結(jié)構(gòu)體轉(zhuǎn)換成time_t格式。 return t_; // 返回值。 }
其中,第6行為給定的日期string設(shè)置語(yǔ)句,由于這里假定是輸入的string是"2017-05-27 19:50:02",所以將參數(shù)設(shè)置為"%d-%d-%d %d:%d:%d",如果輸入的是其他格式的日期時(shí)間形式,將這個(gè)參數(shù)改為對(duì)應(yīng)的格式即可。另外,如果在一個(gè)程序中,設(shè)計(jì)到多種不同的日期時(shí)間格式,可以將這個(gè)參數(shù)作為這個(gè)函數(shù)的參數(shù)之一來(lái)給定。
第14行的mktime函數(shù)位于c頭文件time.h中,用來(lái)將輸入?yún)?shù)所指的tm結(jié)構(gòu)數(shù)據(jù)轉(zhuǎn)換成從公元1970年1月1日0時(shí)0分0秒算起至今的本地時(shí)間所經(jīng)過(guò)的秒數(shù)。
由于返回的time_t通常很大,不利于算法計(jì)算的效率,所以我們可以將所有的時(shí)間轉(zhuǎn)換完畢后,將所有的time_t全部減去一個(gè)數(shù),這個(gè)數(shù)可以是這個(gè)time_t中最小的那個(gè)數(shù),也可以是其他方便算法計(jì)算的數(shù)。在算法執(zhí)行完畢之后,我們?cè)賹⒔Y(jié)果的時(shí)間全部加上這個(gè)數(shù),以便將時(shí)間轉(zhuǎn)換回來(lái)。
現(xiàn)在假定我們已經(jīng)將算法運(yùn)行完畢,那么我們需要將結(jié)果的time_t轉(zhuǎn)換為之前給定的string格式以便于結(jié)果的展示。
下面給出日期時(shí)間time_t轉(zhuǎn)換為string的函數(shù)代碼。
string DatetimeToString(time_t time) { tm *tm_ = localtime(&time); // 將time_t格式轉(zhuǎn)換為tm結(jié)構(gòu)體 int year, month, day, hour, minute, second;// 定義時(shí)間的各個(gè)int臨時(shí)變量。 year = tm_->tm_year + 1900; // 臨時(shí)變量,年,由于tm結(jié)構(gòu)體存儲(chǔ)的是從1900年開(kāi)始的時(shí)間,所以臨時(shí)變量int為tm_year加上1900。 month = tm_->tm_mon + 1; // 臨時(shí)變量,月,由于tm結(jié)構(gòu)體的月份存儲(chǔ)范圍為0-11,所以臨時(shí)變量int為tm_mon加上1。 day = tm_->tm_mday; // 臨時(shí)變量,日。 hour = tm_->tm_hour; // 臨時(shí)變量,時(shí)。 minute = tm_->tm_min; // 臨時(shí)變量,分。 second = tm_->tm_sec; // 臨時(shí)變量,秒。 char yearStr[5], monthStr[3], dayStr[3], hourStr[3], minuteStr[3], secondStr[3];// 定義時(shí)間的各個(gè)char*變量。 sprintf(yearStr, "%d", year); // 年。 sprintf(monthStr, "%d", month); // 月。 sprintf(dayStr, "%d", day); // 日。 sprintf(hourStr, "%d", hour); // 時(shí)。 sprintf(minuteStr, "%d", minute); // 分。 if (minuteStr[1] == '