は手動変換係数を用いて、または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}});
}
これは、すべてのtimeval
とsystem_clock
のためのエポックが同一であるという仮定に基づいています。これは指定されていませんが、既存のすべての実装に当てはまります。運があれば、近い将来、この既存のプラクティスを標準化することができます。
POSIXでtimeval
がtime_point
とduration
の両方として使用されていることに注意してください。したがって、timeval
が現在時間を表している場合、to_time_point
は実行時エラーを引き起こす可能性があります。クライアントが結果を時間として解釈すると、to_timeval
に実行時エラーが発生する可能性があります。
'dateTime.tv_sec'と' dateTime.tv_usec'に割り当てられるべきなのは、有効な 'timeval'構造体で終わることです。 –
@KyleStrand編集 –
'millisecs.count()/ 1000l;'と 'dest.tv_usec = millisecs.count()%1000l;'の 'lは必ずしも必要ではありません。マイナーな問題。 – chux