2015年8月2日日曜日

to_string_iso8601: std::chrono::time_point --> ISO8601

C++でISO8601の時刻文字列を取得するお話。

お仕事以外ではだいたいLinuxを使っていますが、お仕事ではWindows向けのC++アプリも作る都合もあってそのときはおおよそTDM-GCC-5.1.0を使っています。

以前書いたstd::chronoベースからISO8601の時刻文字列を取得する機能、これまでmingwでも動作に問題無かったはずなのだけどTDM-GCC-5.1.0を使ったところ、翻訳はできても時刻文字列が出て来ない現象に遭遇しました。

この機能のコードを確認してみると、std::strftimeのフォーマット文字列として%F%Tを使っていたのですが、これがどちらもTDM-GCC-5.1.0では未サポートだったらしい。

ところが、gcc-E -dMして見る限り、TDM-GCCを判別できそうなCPPマクロ定義が無いみたい。

/// @brief time_point to iso8601 string
/// @tparam T clock type
/// @param t time_point
/// @return iso8601 string
template < class CLOCK = std::chrono::steady_clock >
auto to_string_iso8601 ( const typename CLOCK::time_point& t = CLOCK::now() )
  -> std::string
{
  using namespace std::chrono;
  const time_t ct
  ( ( duration_cast< seconds > ( system_clock::now( ).time_since_epoch( ) )
  + duration_cast< seconds > ( t - CLOCK::now( ) )
    ).count( )
  );
  std::string r = "0000-00-00T00:00:00Z.";
#ifdef _WIN32
  // TDM-GCC-5.1.0 is not support %F and %T
  //   note: mingw is supported. but we cannot predicate TDM or not.
  constexpr auto format = "%Y-%m-%dT%H:%M:%SZ";
#else
  constexpr auto format = "%FT%TZ";
#endif
  std::strftime ( const_cast< char* > ( r.data( ) ), r.size( ), format, std::gmtime ( &ct ) );
  return r;
}

と、いうわけで、_WIN32の場合は包括的に%Fと%Tを使わない分岐にしてしまいました。目的はISO8601時刻文字列が出る事なので、まあ、よいのだけど、なんだかちょっと格好悪いですね(´・ω:;.:…

0 件のコメント:

コメントを投稿