C++ time_t與string的互相轉換


轉載:https://www.cnblogs.com/renjiashuo/p/6913668.html

在c/c++實際問題的編程中,我們經常會用到日期與時間的格式,在算法運行中,通常將時間轉化為int來進行計算,而處理輸入輸出的時候,日期時間的格式卻是五花八門,以各種標點空格相連或者不加標點。

首先,在c中,是有一個標准的日期時間結構體的,在標准庫wchar.h內,我們可以看到結構體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 */

由於各項英文注釋很好理解,這里只做簡要補充。

1)注意月份是0-11,而不是1-12,所以在tm結構體與string轉換的時候,要相應的做減1加1處理。

2)tm_isdst為夏令時設置,0為非夏令時,1為夏令時。由於21世紀的中國並沒有實行夏令時制度,所以編寫國內程序我們可以忽略這個變量。

利用這個結構體,我們就可以完成日期時間與string字符串的轉換了,由於計算的方便,我們一般選擇將日期時間的string轉換成time_t類型。

如果你非要int的話,我可以負責任的告訴你,time_t在visual studio環境下,就是"__int64"類型的變量,它由typedef關鍵字在庫文件crtdefs.h里給定,所以,把time_t放心的拿去用就好了。

言歸正傳,這里,我們假定輸入的字符串格式為"2017-05-27 19:50:02",這個設定並不影響其他格式的字符串時間與可參與計算的變量的轉換,如果要參與轉換的日期字符串不是這個格式,讀者可自行更改下面給出代碼的對應部分。

下面給出日期時間string轉換為time_t的函數代碼。

time_t StringToDatetime(string str)
{
    char *cha = (char*)str.data();             // 將string轉換成char*。
    tm tm_;                                    // 定義tm結構體。
    int year, month, day, hour, minute, second;// 定義時間的各個int臨時變量。
    sscanf(cha, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second);// 將string存儲的日期時間,轉換為int臨時變量。
    tm_.tm_year = year - 1900;                 // 年,由於tm結構體存儲的是從1900年開始的時間,所以tm_year為int臨時變量減去1900。
    tm_.tm_mon = month - 1;                    // 月,由於tm結構體的月份存儲范圍為0-11,所以tm_mon為int臨時變量減去1。
    tm_.tm_mday = day;                         // 日。
    tm_.tm_hour = hour;                        // 時。
    tm_.tm_min = minute;                       // 分。
    tm_.tm_sec = second;                       // 秒。
    tm_.tm_isdst = 0;                          // 非夏令時。
    time_t t_ = mktime(&tm_);                  // 將tm結構體轉換成time_t格式。
    return t_;                                 // 返回值。
}

其中,第6行為給定的日期string設置語句,由於這里假定是輸入的string是"2017-05-27 19:50:02",所以將參數設置為"%d-%d-%d %d:%d:%d",如果輸入的是其他格式的日期時間形式,將這個參數改為對應的格式即可。另外,如果在一個程序中,設計到多種不同的日期時間格式,可以將這個參數作為這個函數的參數之一來給定。

第14行的mktime函數位於c頭文件time.h中,用來將輸入參數所指的tm結構數據轉換成從公元1970年1月1日0時0分0秒算起至今的本地時間所經過的秒數。

由於返回的time_t通常很大,不利於算法計算的效率,所以我們可以將所有的時間轉換完畢后,將所有的time_t全部減去一個數,這個數可以是這個time_t中最小的那個數,也可以是其他方便算法計算的數。在算法執行完畢之后,我們再將結果的時間全部加上這個數,以便將時間轉換回來。

現在假定我們已經將算法運行完畢,那么我們需要將結果的time_t轉換為之前給定的string格式以便於結果的展示。

下面給出日期時間time_t轉換為string的函數代碼。

string DatetimeToString(time_t time)
{
    tm *tm_ = localtime(&time);                // 將time_t格式轉換為tm結構體
    int year, month, day, hour, minute, second;// 定義時間的各個int臨時變量。
    year = tm_->tm_year + 1900;                // 臨時變量,年,由於tm結構體存儲的是從1900年開始的時間,所以臨時變量int為tm_year加上1900。
    month = tm_->tm_mon + 1;                   // 臨時變量,月,由於tm結構體的月份存儲范圍為0-11,所以臨時變量int為tm_mon加上1。
    day = tm_->tm_mday;                        // 臨時變量,日。
    hour = tm_->tm_hour;                       // 臨時變量,時。
    minute = tm_->tm_min;                      // 臨時變量,分。
    second = tm_->tm_sec;                      // 臨時變量,秒。
    char yearStr[5], monthStr[3], dayStr[3], hourStr[3], minuteStr[3], secondStr[3];// 定義時間的各個char*變量。
    sprintf(yearStr, "%d", year);              // 年。
    sprintf(monthStr, "%d", month);            // 月。
    sprintf(dayStr, "%d", day);                // 日。
    sprintf(hourStr, "%d", hour);              // 時。
    sprintf(minuteStr, "%d", minute);          // 分。
    if (minuteStr[1] == '\0')                  // 如果分為一位,如5,則需要轉換字符串為兩位,如05。
    {
        minuteStr[2] = '\0';
        minuteStr[1] = minuteStr[0];
        minuteStr[0] = '0';
    }
    sprintf(secondStr, "%d", second);          // 秒。
    if (secondStr[1] == '\0')                  // 如果秒為一位,如5,則需要轉換字符串為兩位,如05。
    {
        secondStr[2] = '\0';
        secondStr[1] = secondStr[0];
        secondStr[0] = '0';
    }
    char s[20];                                // 定義總日期時間char*變量。
    sprintf(s, "%s-%s-%s %s:%s:%s", yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);// 將年月日時分秒合並。
    string str(s);                             // 定義string變量,並將總日期時間char*變量作為構造函數的參數傳入。
    return str;                                // 返回轉換日期時間后的string變量。
}

其中,第3行的localtime函數位於c頭文件time.h中,用來將從公元1970年1月1日0時0分0秒算起至今的本地時間所經過的秒數轉換成標准tm結構體。

第31行是輸出日期時間字符串string格式的給定,如果需要其他格式,可以修改"%s-%s-%s %s:%s:%s"為指定格式,如果在同一個程序里需要多種格式的輸出,可以將這個參數作為本函數的參數來輸入。

下面給出完整調試用程序及所需頭文件,代碼測試通過環境windows10 + vs2013;Ubuntu 14.04 + gcc version 4.8.2。

#include <iostream>
#include <ctime>
#include <string>
using namespace std;
time_t StringToDatetime(string str)
{
    char *cha = (char*)str.data();             // 將string轉換成char*。
    tm tm_;                                    // 定義tm結構體。
    int year, month, day, hour, minute, second;// 定義時間的各個int臨時變量。
    sscanf(cha, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second);// 將string存儲的日期時間,轉換為int臨時變量。
    tm_.tm_year = year - 1900;                 // 年,由於tm結構體存儲的是從1900年開始的時間,所以tm_year為int臨時變量減去1900。
    tm_.tm_mon = month - 1;                    // 月,由於tm結構體的月份存儲范圍為0-11,所以tm_mon為int臨時變量減去1。
    tm_.tm_mday = day;                         // 日。
    tm_.tm_hour = hour;                        // 時。
    tm_.tm_min = minute;                       // 分。
    tm_.tm_sec = second;                       // 秒。
    tm_.tm_isdst = 0;                          // 非夏令時。
    time_t t_ = mktime(&tm_);                  // 將tm結構體轉換成time_t格式。
    return t_;                                 // 返回值。
}
string DatetimeToString(time_t time)
{
    tm *tm_ = localtime(&time);                // 將time_t格式轉換為tm結構體
    int year, month, day, hour, minute, second;// 定義時間的各個int臨時變量。
    year = tm_->tm_year + 1900;                // 臨時變量,年,由於tm結構體存儲的是從1900年開始的時間,所以臨時變量int為tm_year加上1900。
    month = tm_->tm_mon + 1;                   // 臨時變量,月,由於tm結構體的月份存儲范圍為0-11,所以臨時變量int為tm_mon加上1。
    day = tm_->tm_mday;                        // 臨時變量,日。
    hour = tm_->tm_hour;                       // 臨時變量,時。
    minute = tm_->tm_min;                      // 臨時變量,分。
    second = tm_->tm_sec;                      // 臨時變量,秒。
    char yearStr[5], monthStr[3], dayStr[3], hourStr[3], minuteStr[3], secondStr[3];// 定義時間的各個char*變量。
    sprintf(yearStr, "%d", year);              // 年。
    sprintf(monthStr, "%d", month);            // 月。
    sprintf(dayStr, "%d", day);                // 日。
    sprintf(hourStr, "%d", hour);              // 時。
    sprintf(minuteStr, "%d", minute);          // 分。
    if (minuteStr[1] == '\0')                  // 如果分為一位,如5,則需要轉換字符串為兩位,如05。
    {
        minuteStr[2] = '\0';
        minuteStr[1] = minuteStr[0];
        minuteStr[0] = '0';
    }
    sprintf(secondStr, "%d", second);          // 秒。
    if (secondStr[1] == '\0')                  // 如果秒為一位,如5,則需要轉換字符串為兩位,如05。
    {
        secondStr[2] = '\0';
        secondStr[1] = secondStr[0];
        secondStr[0] = '0';
    }
    char s[20];                                // 定義總日期時間char*變量。
    sprintf(s, "%s-%s-%s %s:%s:%s", yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);// 將年月日時分秒合並。
    string str(s);                             // 定義string變量,並將總日期時間char*變量作為構造函數的參數傳入。
    return str;                                // 返回轉換日期時間后的string變量。
}
int main()
{
    string timeStr = "2017-05-27 19:50:02";
    cout << timeStr << endl;
    time_t timet = StringToDatetime(timeStr);
    timet += 5 * 24 * 3600;
    string timeStr2 = DatetimeToString(timet);
    cout << timeStr2 << endl;
    return 0;
}

主函數中給定一個字符串"2017-05-27 19:50:02"。

經過增加5*24*3600秒之后,得到的字符串是"2017-6-1 19:50:02"。

端午節過了就到兒童節啦,完結撒花!*★,°*:。☆\(~▽~)/$:*。°★*。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM