我正在编写一个需要访问旧C库的C ++代码,该库使用timeval作为当前时间的表示。
在旧包中获取我们使用的当前日期/时间:
struct timeval dateTime;
gettimeofday(&dateTime, NULL);
function(dateTime); // The function will do its task
现在我需要使用C ++ chrono,例如:
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);
稍后在代码中我需要返回的方法,从返回的time_point
构建struct timeval
变量:
struct timeval dateTime;
function(&dateTime);
system_clock::time_point returnedDateTime = ?? // Help appreacited
我正在使用C ++ 11。
答案 0 :(得分:6)
[编辑使用time_val
代替免费邮箱]
假设您信任您的system_clock
精确度为毫秒,您可以这样:
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
中使用duration_cast
并相应地调整您的(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)
;
答案 1 :(得分:4)
请参阅std::chrono::system_clock::to_time_t()
,将time_point
转换为time_t
,后者将成为您的tv_sec
。你没有得到tv_usec
,你可以设置为0;或者你可以摆弄一些其他的东西,包括duration_cast
,以便从你的time_point
中提取一小部分。
from_time_t
()反过来。
答案 2 :(得分:3)
以下是如何在不使用手动转换因子的情况下进行转换,或者取决于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
个正值。然后,从上一个microseconds
开始查找second
是一个简单的操作。
如果我对我的假设不正确(并且可以找到更精确的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
。如果to_time_point
当前表示持续时间,则timeval
可能会导致运行时错误。如果客户端将结果解释为持续时间,则to_timeval
可能会导致运行时错误。