2017-01-08 14 views
2

私は%Y-%m-%d %H:%M:%S%f形式の日付/時刻文字列を扱っています。`std :: string`の` boost :: local_time :: date_time`

America/New_Yorkタイムゾーンで日付/時刻文字列を受け取り、Europe/Parisタイムゾーンで日付/時刻文字列を返す関数を設計したいとします。

私は

16:03:38.539000 UTC 

を取得した入力文字列16:03:38.539000et_timecet_timeのいずれかを印刷し、私が何かする

  • et_timeを期待していたとき、私は、次の

    std::string ec2cet(const std::string &date_time_str) 
    { 
        using namespace boost::posix_time; 
        using namespace boost::gregorian; 
        using namespace boost::local_time; 
    
        tz_database tz_db; 
        time_zone_ptr et_tz = tz_db.time_zone_from_region("America/New_York"); 
        time_zone_ptr cet_tz = tz_db.time_zone_from_region("Europe/Paris"); 
    
        ptime absolute_time = time_from_string(date_time_str); 
        local_date_time ec_time(absolute_time, et_tz); 
        local_date_time cet_time = et_time.local_time_in(cet_tz); 
    
        return to_simple_string(cet_time); 
    } 
    

    を思い付いとは異なる私はそれがet_tzタイムゾーンオブジェクトを提供して構築したので、。

  • cet_timeが異なるタイムゾーンにあることをlocal_time_inで構成し、cet_tzタイムゾーンオブジェクトを提供するように設定する必要があります。

私は間違っていますか?

+2

時間帯にブーストを使用しないでください。あなたは失望します。 Boostに関する注意事項の[tzベストプラクティスの回答](http://stackoverflow.com/questions/2532729/daylight-saving-time-and-time-zone-best-practices)を参照してください。下のHHの答えははるかに良いです。 –

答えて

2

ec2cetのブースト実装で何が問題なのか分かりません。しかし、私はこれを行う方法をこのfree, open source libraryで非常に簡単に示すことができます。まず、コード、その後、ライン・バイ・ラインの説明:物事はそれほど冗長ではありませんので

#include "tz.h" 
#include <iostream> 
#include <sstream> 
#include <string> 

std::string 
ec2cet(const std::string& date_time_str) 
{ 
    using namespace std;         // 1 
    using namespace std::chrono;       // 2 
    using namespace date;        // 3 
    constexpr auto fmt = "%F %T";      // 4 
    istringstream in{date_time_str};      // 5 
    local_time<microseconds> tp;       // 6 
    in >> parse(fmt, tp);        // 7 
    if (in.fail())          // 8 
     return std::string{};       // 9 
    auto et_time = make_zoned("America/New_York", tp); // 10 
    auto cet_time = make_zoned("Europe/Paris", et_time); // 11 
    cout << "et_time = " << et_time << '\n';   // 12 
    cout << "cet_time = " << cet_time << '\n';   // 13 
    return format(fmt, cet_time);      // 14 
} 

行1-3はちょうどローカル空間にすべてを持って来ます。

行4:書式文字列を1か所に書いてください。 "%F%T"は "%Y-%m-%d%H:%M:%S"に相当し、これも使用できます。 (私は怠け者)。

ライン5:このライブラリはストリームから解析するので、入力文字列date_time_strをストリーム(in)に変換する必要があります。

6行目: "America/New_York"に入力された文字列がローカルの日付/時刻を表すことがわかっているとします。タイプlocal_time<microseconds>は、chrono::time_pointです。これは、任意の時間帯の現地時間をマイクロ秒精度で表すことができます。この(tp)のインスタンスは、date_time_strを解析するものです。

行7:Parse into tp

8-9行:解析エラーをチェックします。

行10:zoned_time<microseconds>を「America/New_York」time_zonelocal_time tpを使用して作成します。 zoned_timeは単にpair<time_zone, local_time>と考えることができますが、詳細はそれより少し複雑です。

11行目:time_zone「ヨーロッパ/パリ」とzoned_time et_timeからzoned_time<microseconds>を作成します。これは、1つの現地時間を別の現地時間に変換します。

ライン12-13:これらの中間結果(デバッグの目的でet_timeおよびcet_time)を出力します。

行14:std::stringにフォーマットcet_timeをフォーマットして返します。

int 
main() 
{ 
    auto s = ec2cet("2017-01-08 16:03:38.539000"); 
    std::cout << "ec2cet = " << s << '\n'; 
} 

出力::

et_time = 2017-01-08 16:03:38.539000 EST 
cet_time = 2017-01-08 22:03:38.539000 CET 
ec2cet = 2017-01-08 22:03:38.539000 

このプログラムは、現在のIANAタイムゾーンデータベースを追跡し、正しくの完全な履歴のタイムゾーン規則に従います以下のドライバでこれを実行する

これらの2つのタイムゾーンのために1800年代後半に始まるIANAデータベース。

microsecondsの精度が必要でない場合は、その値を(6行目の1か所で)変更できます。入力文字列が "America/New_York"の代わりにUTCでなければならない場合は、これも行6の1行の変更です(local_time<microseconds>の代わりにtpsys_time<microseconds>のタイプにします)。

+1

うわー、この素晴らしい答えのためにハワードありがとう:) – valentin

関連する問題