其實標題並不是那麼準確,這點我們之後再談。
其實起源很簡單,我們常常需要從各式各樣的時間字串轉成 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 response to “以 boost::posix_time 處理時間字串”
[…] boost::posix_time::time_input_facet可以很好的分析输入的时间串,但是,美中不足的是,最新的1.38.0的boost也未支持对输入串中的时区做分析(Date Time Input/Output)。该post给出了一个变通的办法分析时区。 […]