Boost で日付処理


昨日に続いて同じネタなんですが Boost がなかったのと Boost.Date_Time あまり使ったことがないので練習がてら書いてみました。

[現在時刻のDateTime取得]

#include <iostream>
#include <sstream>

int
main(){
    namespace pt = boost::posix_time;
    namespace gg = boost::gregorian;

    // フォーマットの指定
    // facet はストリーム側で自動的に delete される
    auto facet = new pt::time_facet("%Y-%m-%d %H:%M:%S");
    std::stringstream ss;
    ss.imbue(std::locale(std::cout.getloc(), facet));
    
    // 現在の時刻を取得
    auto now_time = pt::second_clock::local_time();
    ss << now_time;
    std::cout << ss.str() << std::endl;

    return 0;
}
/*
output:
2013-06-19 21:23:29
*/


指定されたフォーマットで出力するためにストリームに対して time_facet を設定しています。

[現在時刻のTimeStamp取得]

#include <boost/date_time.hpp>
#include <boost/date_time/c_local_time_adjustor.hpp>
#include <iostream>
#include <sstream>

int
main(){
    namespace pt = boost::posix_time;
    namespace gg = boost::gregorian;
    
    typedef boost::date_time::c_local_adjustor<pt::ptime> local_adj;

    // 1970/1/1 からの差分を取得
    auto epoch = local_adj::utc_to_local(pt::ptime(gg::date(1970, 1, 1)));
    auto diff = pt::second_clock::local_time() - epoch;

    // 差分を秒で表示
    std::cout << diff.total_seconds() << std::endl;
    
    return 0;
}
/*
output:
1371644642
*/


1970/1/1 から現時刻の差分を秒にして出力しています。
その際に UTC からローカルのタイムゾーンへと時刻を変換指定ます。

[DateTime => TimeStamp変換]

#include <boost/date_time.hpp>
#include <boost/date_time/c_local_time_adjustor.hpp>
#include <iostream>
#include <sstream>

int
main(){
    namespace pt = boost::posix_time;
    namespace gg = boost::gregorian;
    
    typedef boost::date_time::c_local_adjustor<pt::ptime> local_adj;
    auto epoch = local_adj::utc_to_local(pt::ptime(gg::date(1970, 1, 1)));

    auto date_time = pt::time_from_string("2013-06-15 19:37:33");
    auto diff = date_time - epoch;
    auto time_stamp = diff.total_seconds();

    std::cout << time_stamp << std::endl;
    
    return 0;
}
/*
output:
1371292653
*/


time_from_string で指定されていたフォーマットの文字列から時刻を取得できたのでそれを使用しています。
その他、独自フォーマットをパースしたい場合は date_input_facet を使用すれば変換出来るようです。

[TimeStamp => DateTime変換]

#include <boost/date_time.hpp>
#include <boost/date_time/c_local_time_adjustor.hpp>
#include <iostream>
#include <sstream>

int
main(){
    namespace pt = boost::posix_time;
    namespace gg = boost::gregorian;

    typedef boost::date_time::c_local_adjustor<pt::ptime> local_adj;
    auto epoch = local_adj::utc_to_local(pt::ptime(gg::date(1970, 1, 1)));

    auto facet = new pt::time_facet("%Y-%m-%d %H:%M:%S");
    std::stringstream ss;
    ss.imbue(std::locale(std::cout.getloc(), facet));
        
    pt::seconds time_stamp(1371292653L);
    auto date_time = epoch + time_stamp;
    ss << date_time;
    std::cout << ss.str() << std::endl;

    return 0;
}
/*
output:
2013-06-15 19:37:33
*/


1970/1/1 に対して TimeStamp を足して計算します。

[所感]

日付を計算するのは比較的簡単ですね。
ただ、フォーマットを指定して文字列に変換するにはちと手順が複雑な感じ。
ここら辺は簡単なラッパーとかがあってもいい気がする。
あと最初 date(1970, 1, 1) で生成したデータが UTC 基準だったのに気づかなくてぐぬぬ…となっていた。