boost

Boost を用いた ISO 8601(RFC 3339)フォーマットの日付出力

Boost を用いて ISO 8601(正確には RFC 3339)フォーマット日時を出力するサンプルです。

main.cpp
#include <iostream>

#include <boost/date_time/c_local_time_adjustor.hpp>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

std::string current_local_time() {
    const auto current_time = boost::posix_time::microsec_clock::local_time();
    const auto utc_timestamp = boost::posix_time::second_clock::universal_time();
    const auto local_timestamp = boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local(utc_timestamp);
    const auto td = local_timestamp - utc_timestamp;

    std::ostringstream oss;
    oss << boost::posix_time::to_iso_extended_string(current_time);
    oss << (td.is_negative() ? '-' : '+');
    oss << std::setw(2) << std::setfill('0');
    oss << boost::date_time::absolute_value(td.hours());
    oss << ':';
    oss << std::setw(2) << std::setfill('0');
    oss << boost::date_time::absolute_value(td.minutes());
    return oss.str();
}

int main() {
    std::cout << current_local_() << std::endl;
    return 0;
}

以下のようにビルドして実行します。Boost のインクルードパスは環境に合わせて適宜変更してください。

$ g++ main.cpp -std=c++11 -I/usr/local/Cellar/boost/1.66.0/include -lboost_date_time
$ ./a.out
2018-02-24T00:09:55.980492+09:00

蛇足

ISO 8601RFC 3339 は、それぞれ詳細を確認して貰いたいのですが、簡単に特徴と違いをまとめると:

  • ISO 8601 は 20180102T212223Z または 20180102T212223+0900 が基本形式で、2018-01-02T21:22:23Z または 2018-01-02T21:22:23+0900 が拡張形式
    • 2018-01-02T21:22Z2018-01-02T21Zのような精度も可
    • 末尾には小数点を指定可能で 2018-01-02T21:22:23,5Z2018-01-02T21:22,5Z2018-01-02T21,5Z などの指定が可能(それぞれ 21:22:23.521:22:3021:30:00 を意味する)
    • 小数点はカンマが推奨されるが、ピリオドでも可
    • T または Z は小文字も可
  • RFC 3339 は秒未満の精度を持つ 2018-01-02T21:22:23.123456Z または 2018-01-02T21:22:23.123456+09:00
    • 秒未満の桁数は任意

という感じです。

ここでは詳細を省略していますが ISO 8601 はもっともっとあいまいなフォーマットで、例えば YYYY-DDD という表記で月を省略したり YYYY-Www-D で第何週の何曜日かを表したりもできます。ISO 8601 といえば上述の箇条書きのフォーマットが一般的に認知されており、こうした特殊なフォーマットはあまり使われないと思いますが、ISO 8601 の拡張かつサブセットである RFC 3339 がフォーマットとしてはカチッとしていて扱いやすいです。

今回の記事は ISO 8601 フォーマットを出力するなら strftime で比較的簡単に出力できるのですが、RFC 3339 を出力するベストプラクティスがネット上で見つからなかったので1作成しました。


  1. 実際には C++ & ISO8601 : 時刻文字列 "2016-01-25T15:30:15.123+09:00" を出力する例 - Qiita がすぐに見つかったのですが、実装が大きくて複雑なので採用できませんでした(すみません)