以 boost::posix_time 處理時間字串

其實標題並不是那麼準確,這點我們之後再談。

其實起源很簡單,我們常常需要從各式各樣的時間字串轉成 time_t 或者 struct tm,要不然還可能是 FILETIME 跟 SYSTEMTIME 之類的結構。個人覺得 parsing 時間是一件難搞的事情,尤其是當你還要考慮 timezone 的影響,一切都變得不是那麼簡單了。

首先我必須要說,在 Windows 中沒有 strptime(3) 這樣還算好用的東西可以用,所以我又把腦袋動到 boost 上面去了。

我的目標是正確的處理「Sat, 28 Mar 2009 20:18:32 +0800」這樣的字串,然後把他轉成 time_t。我們會分兩個部份處理,首先我們先處理「Sat, 28 Mar 2009 20:18:32」這個部份,因為目前的 %q 只能處理輸出部份,請參考 Date Time Formatter/Parser Objects

    using namespace boost::posix_time;
    using namespace boost;
    using namespace std;

    std::string strDateTime = "Sat, 28 Mar 2009 20:18:32 +0800";
    std::string format = "%a, %d %b %Y %H:%M:%S";

    ptime pt(not_a_date_time);

    time_input_facet * input_facet = new time_input_facet(format);

    stringstream ss(strDateTime);
    ss.imbue(locale(ss.getloc(), input_facet ));

    ss >> pt;

這樣的確很簡單吧,只要按照文件寫的把 format 寫好,boost 就能幫你從 stringstream 的字串轉成 posix_time。

而 timezone 的部份就需要噁心一點的作法了。

    std::string strHour, strMinute;
    ss >> setw(3) >> strHour >> setw(2) >> strMinute;

    time_duration td(lexical_cast< int >(strHour), lexical_cast < int > (strMinute), 0);
    pt -= td;

我利用 setw 分別把 timezone 的小時與分抓出來,並轉成 time_duration,讓 posix_time 能直接減掉 timezone 的 offset 成為 GMT time,之後再做點手腳就可以變成 time_t 了。

嚴格來說,我想我是透過 time_input_facet 來處理字串的,希望這點小技巧對於需要 parsing 時間字串的人能有所幫助。

p.s: 其實這篇三個禮拜前就準備好了,只是一直拖到現在才把他丟出來 XD

One Reply to “以 boost::posix_time 處理時間字串”

Leave a Reply

Your email address will not be published. Required fields are marked *