2013-03-27 110 views
2

給定一個輸入日期和時間(以字符串格式),我試圖用給出的time函數獲得它的歷元時間,如mktime。將time_t紀元時間轉換回日期和時間會導致日期和時間比原始時間少一小時。我經歷了一些討論,說夏時制可能會有一小時的調整。下面是代碼:應對夏令時 - C++

//sample strptime program. 

#include <iostream> 
#include <ctime> 
#include <string> 
using namespace std; 

long parseTime(string time) { 

    cout << "Time entered = " << time << endl; 

    long timeSinceEpoch; 

    struct tm t; 

    if(time.find("/") != string::npos) { 
    //format of date is mm/dd/yyyy. followed by clock in hh:mm (24 hour clock). 
    if(strptime(time.c_str(), "%m/%e/%Y %H:%M", &t) == NULL) { 
     cout << "Error. Check string for formatting." << endl; 
    } 
    } else if(time.find("-") != string::npos) { 
    //format of date is yyyy-mm-dd hh:mm:ss (hh in 24 hour clock format). 
    cout << "I am here." << endl; 
    if(strptime(time.c_str(), "%Y-%m-%e %H:%M:%S", &t) == NULL) { 
     cout << "Error. Check string for formatting of new date." << endl; 
    } 
    } 

    cout << "Details of the time structure:" << endl; 
    cout << "Years since 1900 = " << t.tm_year << endl; 
    cout << "Months since January = " << t.tm_mon << endl; 
    cout << "Day of the month = " << t.tm_mday << endl; 
    cout << "Hour = " << t.tm_hour << " Minute = " << t.tm_min << " second = " << t.tm_sec << endl; 

    timeSinceEpoch = mktime(&t); 
    time_t temp = mktime(&t); 
    cout << "Time since epoch = " << timeSinceEpoch << endl; 

    cout << "Reconverting to the time structure:" << endl; 
    struct tm* t2 = localtime(&temp); 
    cout << "Details of the time structure:" << endl; 
    cout << "Years since 1900 = " << t2->tm_year << endl; 
    cout << "Months since January = " << t2->tm_mon << endl; 
    cout << "Day of the month = " << t2->tm_mday << endl; 
    cout << "Hour = " << t2->tm_hour << " Minute = " << t2->tm_min << " second = " << t2->tm_sec << endl; 

    return timeSinceEpoch; 
} 

int main(int argc, char *argv[]) { 

    string date, t; 
    cout << "Enter date: " << endl; 
    cin >> date; 
    cout << "Enter time: " << endl; 
    cin >> t; 

    struct tm time; 
    string overall = date + " " + t; 

    long result = parseTime(overall); 
    cout << "Time in date + time = " << overall << " and since epoch = " << result << endl; 

return 0; 
} 

的麻煩的輸入是: 日期:2013年3月11日 時間:4時41分53秒

我的問題(S):
1.檢查tm_idst標誌返回一個非零值,表示DST生效。但是,我怎麼知道正在討論什麼時區?
2.上述時間戳可能沒有被記錄在同一時區,我在,有沒有這樣的tm_idst標誌設置是否正確,指定時區的方法嗎?
3.當我不確定時間戳記錄在哪個時區時,我該如何處理DST?

+0

獲取時區取決於您的操作系統和C語言庫上,沒有標準或平臺無關的方式得到它。例如,在使用glibc的Linux上,'tm'結構中有一個名爲'tm_zone'的額外成員字段,它是一個包含時區縮寫的C風格字符串。 – 2013-03-27 19:09:36

+0

@Joachim:我試過'tm_zone'選項,但它似乎不在那裏。所以基本上,我只是從時代開始就有時間,重新轉換爲'struct tm',並且如果有一個小時的差異,則增加3600秒?這是我處理DST的唯一選擇嗎? – Sriram 2013-03-27 19:22:26

+0

評論 - 如果你接受'ISO'類型的日期,那麼正確的輸入格式是YYYY-MM-DD(即4 + 2 + 2 **總是***) - 所以解析爲'% Y-%m-%d',%e格式在理論上接受單位數字日期的前導空間,而[ISO總是期望兩位數的月份和年份](http://en.wikipedia.org/wiki/ ISO_8601)。 – Petesh 2013-03-27 19:47:19

回答

2

Plain C++與時區數據相當稀疏,並且在格式化時沒有時區規範,有幾個時期您將得到不一致的結果 - 例如,重複的時間跟隨時鐘回來。這就是爲什麼它總是建議記錄所有時間戳在UTC - 即從未應用時區所記錄的時間戳,它在格林尼治標準時間記錄,然後備份和反覆與價值爲顯示變量,你必須總掌控。

的Linux/BSD具有可以被用來確定所述時區的一些附加的字段,並從UTC的偏移 - 例如在linux上它是__tm_gmtoff字段,而在BSD(/ Mac OS X)中,它被稱爲tm_gmtoff

還有一個標記時區的字段,它是linux上的__tm_zone和BSD(/ Mac OS X)中的tm_zone,但該字段僅在獲得本地時間時填充。

我改變你的榜樣略顯不足,得到了以下的輸出:

Time entered = 2013-04-05 15:00 
I am here. 
Error. Check string for formatting of new date. 
Details of the time structure: 
Years since 1900 = 113 
Months since January = 3 
Day of the month = 5 
Hour = 15 Minute = 0 second = 0 
gmtoff = 0 
Time since epoch = 1365174000 
Reconverting to the time structure: 
Details of the time structure: 
Years since 1900 = 113 
Months since January = 3 
Day of the month = 5 
Hour = 16 Minute = 0 second = 0 
gmtoff = 3600 
Zone = IST 
Time in date + time = 2013-04-05 15:00 and since epoch = 1365174000 

如果你正在使用Windows此結構中,你將不得不使用另一種機制,不過,因爲它不」沒有這兩個額外的領域。

+0

我在cygwin上。我沒有'tm_gmtoff'或'tm_zone'。我有什麼選擇?從曆元時間重新轉換成日期時間,並且如果存在原始和重新轉換後的時間之間1小時的差異,因爲曆元添加3600秒的時間? – Sriram 2013-03-27 20:19:15

+0

您只處理UTC的建議很好,但我無法控制時間戳生成。我必須處理數據。我被告知時間戳記錄在CST中。 – Sriram 2013-03-27 20:20:50

+0

@Sriram正如我在回答Windows不支持這些領域的末尾提到。我認爲你的意思是時間是在CST/CDT,而不是嚴格的CST。 strptime的cygwin實現是有限的。我會建議使用這種提升 - 它將允許更合理的日期/時間處理。 – Petesh 2013-03-27 21:31:28