2016-10-05 27 views
0

私はboost::posix_time::ptimeオブジェクト(Boost v1.60)にシステムのタイムゾーンに日付と時刻の情報があります。これをUTCのUNIXタイムスタンプに変換する必要があります。現地時間からUTCにブーストptimeを変換する

time_t convertLocalPtimeToTimestamp(const boost::posix_time::ptime& pt) 
{ 
     using namespace boost::local_time; 
     static const time_t t_null = 0; 
     static struct tm* tm_local = localtime(&t_null); 
     static time_zone_ptr zone(new posix_time_zone(tm_local->tm_zone)); 
     LOG(debug) << "Zone " << zone->to_posix_string(); 

     local_date_time az(pt.date(), pt.time_of_day(), zone, local_date_time::EXCEPTION_ON_ERROR); 
     LOG(debug) << "local_date_time: " << az; 
     LOG(debug) << "local_time: " << az.local_time(); 
     LOG(debug) << "utc_time: " << az.utc_time(); 
     struct tm t = to_tm(az); 
     time_t ts = mktime(&t); 

     return ts; 
} 

私の場合(ヨーロッパ/マドリッド)での結果は次のとおりです。

Zone CET+00 
local_date_time: 2016-Oct-05 17:36:27.701162 CET 
local_time: 2016-Oct-05 17:36:27.701162 
utc_time: 2016-Oct-05 17:36:27.701162 
1475685387 

様々なエラーは、この結果であります。

  • タイムゾーンは、夏時間として検出する必要があります(CEST +0200)CET(+0100)
  • DSTの検出がなくても、utc_timeはlocal_timeと異なる必要があります。
  • 最後に、タイムスタンプは現地時間ではなく、UTC時間を表す必要があります。

助けていただければ幸いです。このfree, open source libraryから

+1

これでブーストが悪臭を放つ。あなたはhttps://github.com/HowardHinnant/dateを考えました –

答えて

3

FWIW、:

#include "chrono_io.h" 
#include "tz.h" 
#include <iostream> 

int 
main() 
{ 
    using namespace date; 
    using namespace std::chrono; 
    auto az = make_zoned("Europe/Madrid", 
         local_days{2016_y/oct/5} + 17h + 36min + 27s + 701162us); 
    std::cout << "Zone " << az.get_time_zone()->name() << '\n'; 
    std::cout << "local_date_time: " << az << '\n'; 
    std::cout << "local_time:  " << az.get_local_time() << '\n'; 
    std::cout << "utc_time:  " << az.get_sys_time() << '\n'; 
    std::cout << floor<seconds>(az.get_sys_time()).time_since_epoch() << '\n'; 
} 

、出力は次のとおりです。

auto az = make_zoned(current_zone(), 
         local_days{2016_y/oct/5} + 17h + 36min + 27s + 701162us); 

または::

Zone Europe/Madrid 
local_date_time: 2016-10-05 17:36:27.701162 CEST 
local_time:  2016-10-05 17:36:27.701162 
utc_time:  2016-10-05 15:36:27.701162 
1475681787s 

1つはまた、このようなcurrent_zone()を使用してzoned_timeを構築することができ

auto az = make_zoned(current_zone(), system_clock::now()); 
+0

ありがとうございました。それはまさに私が探していたものです。しかし、なぜデータベースをダウンロードする必要がありますか?それはオペレーティングシステムのタスクではありませんか?私は本当にオフラインの解決策が必要です。 – jgaida

+0

データベースがダウンロードされると、ライブラリはオフラインで動作します。しかし、データベースは数ヶ月で期限切れになります(データベースが更新される頻度です)。最新の状態に保つかどうかを選択できます。 –

0

一方、私はLinuxでUTCオフセットを検出する簡単な方法を発見しました。 localtimeは、現在のタイムゾーンとオフセットを計算するために、NULLでないタイムスタンプが必要です。私が現地時間から現在のタイムゾーンを取得しているため

私が知っている
time_t convertLocalPtimeToTimestamp(const boost::posix_time::ptime& pt) 
{ 
     time_t tt = to_time_t(pt); 
     struct tm* local = localtime(&tt); 
     LOG(debug) << "Timezone: " << local->tm_zone << " Offset: " << local->tm_gmtoff; 
     return (tt - local->tm_gmtoff); 
} 

は、欠陥があるので、夏時間の変更の周りの時間内でのオフセットが存在します。この方法では、それが動作します。しかし私の目的のために、それは問題ではない。

1

ここでは、問題を解決するためのBoost実装を紹介します。

私は別のサードパーティのライブラリを使いたくないし、Windowsでjgaidaの答えで問題が発生していた(tm_zoneとtm_gmtoffはtmのメンバーではない)。

私はWindows 10のPCでタイムゾーンを何度か変更してこのコードをテストしました。

「(UTC-12:00)International Date Line West」と「(UTC + 14:00)Kiritimati Island」のエッジケースもテストされ、結果は成功しました。

time_t convertLocalPtimeToTimestamp (const boost::posix_time::ptime& pt) 
{ 
    using namespace boost::posix_time; 
    using namespace boost::local_time; 

    _tzset(); // This is needed if the time zone changes after the program starts. 

    // Grab copies of the current time in local and UTC form. 
    auto p_time = microsec_clock::universal_time(); // UTC. 
    auto lp_time = boost::date_time::c_local_adjustor<ptime>::utc_to_local (p_time); 

    // Calculate the difference between the UTC and local time and put it in a string. 
    // This will yield "-07:00:00" for PST and "-08:00:00" for PDT. 
    auto time_diff = to_simple_string (lp_time - p_time); 

    // Convert the ptime to a local_date_time object using the local time zone. 
    // We will create the time zone with the time difference string generated above. 
    local_date_time local_time (p_time, time_zone_ptr (new posix_time_zone (time_diff))); 

    // Calculate the difference in milliseconds between the UTC and local time. 
    auto time_t_diff = to_time_t (p_time) - to_time_t (local_time.local_time()); 

    // Return the given time in ms plus the time_t difference (to get the UTC ms). 
    return to_time_t (pt) + time_t_diff; 
} 
+0

興味深いアプローチ@Zo_。私はあなたが新しい 'time_zone_ptr'を作成する部分を削除することができると思います。私はそれが 'to_time_t(pt - (lp_time - p_time)); return 'と同じだと信じています。 – jgaida

+0

私の機能と大きな違いは、機能を実行してから現在のタイムゾーン(および夏時間の状態)が取れることです。私の関数は、関数の引数の 'ptime'からタイムゾーンを取得します。 – jgaida

関連する問題