2016-09-09 18 views
11

現在の時刻を表すtimevalを使用する古いCライブラリにアクセスする必要があるC++コードを記述しています。我々が使用される現在の日付/時刻を取得するために、古いパッケージでstd :: chrono :: system_clock :: time_pointをstruct timevalとbackに変換する

struct timeval dateTime; 
gettimeofday(&dateTime, NULL); 

function(dateTime); // The function will do its task 

今、私はC++クロノを使用する必要がある、など何か:

system_clock::time_point now = system_clock::now(); 
    struct timeval dateTime; 

    dateTime.tv_sec = ???? // Help appreaciated here 
    dateTime.tv_usec = ???? // Help appreaciated here 

    function(dateTime); 

後のコードで、私は方法が必要です私は

struct timeval dateTime; 
    function(&dateTime); 

    system_clock::time_point returnedDateTime = ?? // Help appreacited 

:バック、返さstruct timevalからtime_point変数を構築します

答えて

6

あなたsystem_clockミリ秒の精度で、あなたはこのように行くことができる信頼と仮定

[代わり自由VARSのtime_valを使用するように編集]:duration_cast

struct timeval dest; 
    auto now=std::chrono::system_clock::now(); 
    auto millisecs= 
    std::chrono::duration_cast<std::chrono::milliseconds>(
     now.time_since_epoch() 
    );; 
    dest.tv_sec=millisecs.count()/1000; 
    dest.tv_usec=(millisecs.count()%1000)*1000; 

    std::cout << "s:" << dest.tv_sec << " usec:" << dest.tv_usec << std::endl; 

使用std::chrono::microsecondsをし、あなたの(DIVを調整/ mod)コードを使用して、精度を高めます。取得する値の精度をどれだけ信頼するかに注意してください。

バック変換されます。ここでは

timeval src; 

    // again, trusting the value with only milliseconds accuracy 
    using dest_timepoint_type=std::chrono::time_point< 
    std::chrono::system_clock, std::chrono::milliseconds 
    >; 
    dest_timepoint_type converted{ 
    std::chrono::milliseconds{ 
     src.tv_sec*1000+src.tv_usec/1000 
    } 
    }; 

    // this is to make sure the converted timepoint is indistinguishable by one 
    // issued by the system_clock 
    std::chrono::system_clock::time_point recovered = 
     std::chrono::time_point_cast<std::chrono::system_clock::duration>(converted) 
    ; 
+0

'dateTime.tv_sec'と' dateTime.tv_usec'に割り当てられるべきなのは、有効な 'timeval'構造体で終わることです。 –

+0

@KyleStrand編集 –

+0

'millisecs.count()/ 1000l;'と 'dest.tv_usec = millisecs.count()%1000l;'の 'lは必ずしも必要ではありません。マイナーな問題。 – chux

4

time_tに変換するstd::chrono::system_clock::to_time_t()を参照してください。これはtv_secになります。あなたはtv_usecを得ていません、それを0にすることができます。またはduration_castなどの他のいくつかのものを試して、time_pointから1秒の部分を抽出することができます。

from_time_t()はその逆です。

2

は手動変換係数を用いて、またはtime_tの不特定の丸めモードに依存することなく、両方の変換を行う方法である:

timeval 
to_timeval(std::chrono::system_clock::time_point tp) 
{ 
    using namespace std::chrono; 
    auto s = time_point_cast<seconds>(tp); 
    if (s > tp) 
     s = s - seconds{1}; 
    auto us = duration_cast<microseconds>(tp - s); 
    timeval tv; 
    tv.tv_sec = s.time_since_epoch().count(); 
    tv.tv_usec = us.count(); 
    return tv; 
} 

std::chrono::system_clock::time_point 
to_time_point(timeval tv) 
{ 
    using namespace std::chrono; 
    return system_clock::time_point{seconds{tv.tv_sec} + microseconds{tv.tv_usec}}; 
} 

to_timevalは、世話をしますtpを丸める(負の場合)。これについてはPOSIX仕様が少し曖昧ですが、timevalは、エポックの前に負の値のtv_secの値を、次に正の値tv_usecの値を持つと仮定しています。その後、最後のsecondからmicrosecondsを見つけるのは簡単な操作です。

私の仮定が間違っていて(より正確なPOSIX仕様が見つかることがあります)、<chrono>は、それが何であれモデリングする機能を持っています。

逆変換は、上記の規則を前提として、信じられないほど読みやすくなります。コメントは必要ありません。

これは、すべてこのようにテストすることができます。

timeval 
make_timeval(time_t s, long us) 
{ 
    timeval tv; 
    tv.tv_sec = s; 
    tv.tv_usec = us; 
    return tv; 
} 

bool 
operator==(timeval x, timeval y) 
{ 
    return x.tv_sec == y.tv_sec && x.tv_usec == y.tv_usec; 
} 

int 
main() 
{ 
    using namespace std::chrono; 
    assert(make_timeval(0, 0) == to_timeval(system_clock::time_point{})); 
    assert(make_timeval(1, 0) == to_timeval(system_clock::time_point{seconds{1}})); 
    assert(make_timeval(1, 400000) == to_timeval(system_clock::time_point{seconds{1} + microseconds{400000}})); 
    assert(make_timeval(-1, 400000) == to_timeval(system_clock::time_point{seconds{-1} + microseconds{400000}})); 

    assert(to_time_point(make_timeval(0, 0)) == system_clock::time_point{}); 
    assert(to_time_point(make_timeval(1, 0)) == system_clock::time_point{seconds{1}}); 
    assert(to_time_point(make_timeval(1, 400000)) == system_clock::time_point{seconds{1} + microseconds{400000}}); 
    assert(to_time_point(make_timeval(-1, 400000)) == system_clock::time_point{seconds{-1} + microseconds{400000}}); 
} 

これは、すべてのtimevalsystem_clockのためのエポックが同一であるという仮定に基づいています。これは指定されていませんが、既存のすべての実装に当てはまります。運があれば、近い将来、この既存のプラクティスを標準化することができます。

POSIXでtimevaltime_pointdurationの両方として使用されていることに注意してください。したがって、timevalが現在時間を表している場合、to_time_pointは実行時エラーを引き起こす可能性があります。クライアントが結果を時間として解釈すると、to_timevalに実行時エラーが発生する可能性があります。

関連する問題