2016-08-11 4 views
1

私のプログラムでは、いくつかの異なる形式で時折読みなければなりません。しかし、すべてのフォーマットでは、時間はUTC(すなわち、私のローカルタイムゾーンではない)で与えられます。日付文字列と書式文字列を取り、std::time_tのタイムスタンプを出力する関数の最適な方法は何ですか?標準時から文字列をUTC時刻として読む

現在、私はブースト

#include "boost/date_time/gregorian/gregorian.hpp" 
#include "boost/date_time/posix_time/posix_time.hpp" 

std::time_t to_timestamp_utc(const std::string& _dateString) { 
    using namespace boost::gregorian; 
    using namespace boost::posix_time; 
    return to_time_t(ptime(from_undelimited_string(_dateString))); 
} 

を使用していますが、これは唯一の "YYYYMMDD" 形式のために働きます。一方、標準ライブラリ関数std::get_timeは、入力日付がUTCではなくローカル時間でフォーマットされていると仮定しています(または、少なくとも私はそれを変更する方法を見つけていません)。どんな提案も大歓迎です。

最新の解決策 Maxim Egorushkinの提案に基づいています。ここ

std::time_t utc_to_timestamp(const std::string& _dateString, const std::string& _format) { 
    // Set sec, min, hour to zero in case the format does not provide those 
    std::tm timeStruct; 
    timeStruct.tm_sec = 0; 
    timeStruct.tm_min = 0; 
    timeStruct.tm_hour = 0; 
    char* const result = strptime(_dateString.c_str(), _format.c_str(), &timeStruct); 
    // Throw exception if format did not work 
    REQUIRE(result == _dateString.c_str()+_dateString.size(), "Failed to parse dateTime."); 
    return timegm(&timeStruct); 
} 
+0

どのフォーマットが必要ですか? (UK、US、?) –

+0

期待するフォーマットを知る必要があります。例えば。 「07-06-2016」は米国ではmm-dd-yyyy、EUではdd-mm-yyyyのため、曖昧です。 –

+0

@BiagioFesta私は主に 'yyyy-mm-dd hh:mm:ss'、' yyyymmdd'と 'dd.mm.yyyy hh:mm'を必要としますが、関数を引数として任意の形式例えば ​​'std :: get_time'が実行します。 – Haatschii

答えて

2

std::basic_istream<CharT, Traits>を取るparse機能、書式文字列(std::basic_string<CharT, Traits>)、及びstd::chrono::time_point<system_clock, seconds>free, open-source C++11/14 libraryあります。

std::istringstream in{"2014-11-12 19:12:14"}; 
date::sys_seconds tp; 
in >> date::parse("%F %T", tp); 

failbitが終了時に設定されていない場合は、tpは秒の精度でUnix Timeになります:あなたはこのようにそれを使用

template <class CharT, class Traits, class Duration> 
void 
parse(std::basic_istream<CharT, Traits>& is, 
     const std::basic_string<CharT, Traits>& format, sys_time<Duration>& tp); 

。あなたはそのようなtime_tにそれを変換することができます:

time_t t = system_clock::to_time_t(tp); 

それともあなたはそれをプリントアウトすることができます:

cout << tp.time_since_epoch().count() << '\n'; 

あなたがfailbitセットを取得した場合は、あなたが別のフォーマット文字列を再び試みることができます。

タイムスタンプには秒精度が処理されます。これはタイプセーフなライブラリであるため、すべての出力はUTCになります。time_point<system_clock, whatever-duration>は、 UTC(技術的にはUnix Timeを意味します)を意味します。図書館には現地時間を解析する方法もあります。

フォーマットがあいまいである場合は、フォーマットを試す順序を間違えて誤った値を返す可能性があります。

+0

こんにちは、ありがとう。私は間違いなくそれを見ます。今のところ、私はより軽量なソリューションの後です。 – Haatschii

1

可能な形式を事前に知っている場合は、strptime関数を使用して、文字列を正常に解析する形式を見つけることができます。 struct tmを返します。このUTCは細分化されたUTCとして扱われ、timegmに渡されてtime_tになります。

+0

ありがとう、私はあなたの提案(更新を参照)に基づいて機能を実装し、これまで作業しています。 – Haatschii

+0

@Haatschiiこれまでのところ答えを受け入れる。 –

関連する問題