C++ 如何将 std::chrono::time_point 转换为 long 和 back
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31255486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ How do I convert a std::chrono::time_point to long and back
提问by Mendes
I need to convert std::chrono::time_point
to and from a long
type (integer 64 bits). I′m starting working with std::chrono
...
我需要转换std::chrono::time_point
,并从一个long
类型(整数64位)。我开始与std::chrono
...一起工作
Here is my code:
这是我的代码:
int main ()
{
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
auto epoch = now.time_since_epoch();
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
long duration = value.count();
std::chrono::duration<long> dur(duration);
std::chrono::time_point<std::chrono::system_clock> dt(dur);
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
This code compiles, but does not show success.
此代码编译,但不显示成功。
Why is dt
different than now
at the end?
为什么dt
不同于now
在结束了吗?
What is missing on that code?
该代码缺少什么?
回答by Howard Hinnant
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
This is a great place for auto
:
这是一个很好的地方auto
:
auto now = std::chrono::system_clock::now();
Since you want to traffic at millisecond
precision, it would be good to go ahead and covert to it in the time_point
:
由于您想millisecond
精确地进行流量,最好继续并在以下位置进行隐蔽time_point
:
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
now_ms
is a time_point
, based on system_clock
, but with the precision of milliseconds
instead of whatever precision your system_clock
has.
now_ms
是time_point
,基于system_clock
,但精度为 ,milliseconds
而不是您system_clock
拥有的任何精度。
auto epoch = now_ms.time_since_epoch();
epoch
now has type std::chrono::milliseconds
. And this next statement becomes essentially a no-op (simply makes a copy and does not make a conversion):
epoch
现在有类型std::chrono::milliseconds
。下一个语句本质上变成了一个空操作(只是制作一个副本而不进行转换):
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
Here:
这里:
long duration = value.count();
In both your and my code, duration
holds the number of milliseconds
since the epoch of system_clock
.
在你和我的代码中,都duration
保存了milliseconds
自system_clock
.
This:
这个:
std::chrono::duration<long> dur(duration);
Creates a duration
represented with a long
, and a precision of seconds
. This effectively reinterpret_cast
s the milliseconds
held in value
to seconds
. It is a logic error. The correct code would look like:
创建一个duration
表示为long
,精度为seconds
。这实际上reinterpret_cast
是milliseconds
保持在value
to 中seconds
。这是一个逻辑错误。正确的代码如下所示:
std::chrono::milliseconds dur(duration);
This line:
这一行:
std::chrono::time_point<std::chrono::system_clock> dt(dur);
creates a time_point
based on system_clock
, with the capability of holding a precision to the system_clock
's native precision (typically finer than milliseconds). However the run-time value will correctly reflect that an integral number of milliseconds are held (assuming my correction on the type of dur
).
创建一个time_point
基于system_clock
,能够将精度保持为system_clock
的本机精度(通常小于毫秒)。然而,运行时值将正确反映保持整数毫秒(假设我对 的类型进行了更正dur
)。
Even with the correction, this test will (nearly always) fail though:
即使进行了修正,这个测试也会(几乎总是)失败:
if (dt != now)
Because dt
holds an integral number of milliseconds
, but now
holds an integral number of ticks finer than a millisecond
(e.g. microseconds
or nanoseconds
). Thus only on the rare chance that system_clock::now()
returned an integral number of milliseconds
would the test pass.
因为dt
持有整数个milliseconds
,但now
持有整数个比 a 更细的刻度millisecond
(例如microseconds
或nanoseconds
)。因此,只有在system_clock::now()
返回整数的极少数情况下milliseconds
,测试才会通过。
But you can instead:
但您可以改为:
if (dt != now_ms)
And you will now get your expected result reliably.
现在,您将可靠地获得预期的结果。
Putting it all together:
把它们放在一起:
int main ()
{
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
std::chrono::milliseconds dur(duration);
std::chrono::time_point<std::chrono::system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
Personally I find all the std::chrono
overly verbose and so I would code it as:
就我个人而言,我发现所有这些都std::chrono
过于冗长,因此我将其编码为:
int main ()
{
using namespace std::chrono;
auto now = system_clock::now();
auto now_ms = time_point_cast<milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
milliseconds dur(duration);
time_point<system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
Which will reliably output:
这将可靠地输出:
Success.
Finally, I recommend eliminating temporaries to reduce the code converting between time_point
and integral type to a minimum. These conversions are dangerous, and so the less code you write manipulating the bare integral type the better:
最后,我建议消除临时变量以将在time_point
整数类型之间转换的代码减少到最低限度。这些转换是危险的,因此您编写的处理裸整数类型的代码越少越好:
int main ()
{
using namespace std::chrono;
// Get current time with precision of milliseconds
auto now = time_point_cast<milliseconds>(system_clock::now());
// sys_milliseconds is type time_point<system_clock, milliseconds>
using sys_milliseconds = decltype(now);
// Convert time_point to signed integral type
auto integral_duration = now.time_since_epoch().count();
// Convert signed integral type to time_point
sys_milliseconds dt{milliseconds{integral_duration}};
// test
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
The main danger above is notinterpreting integral_duration
as milliseconds
on the way back to a time_point
. One possible way to mitigate that risk is to write:
上面的主要危险不是解释integral_duration
为milliseconds
在返回 a 的路上time_point
。减轻这种风险的一种可能方法是编写:
sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};
This reduces risk down to just making sure you use sys_milliseconds
on the way out, and in the two places on the way back in.
这将风险降低到确保您sys_milliseconds
在出去的路上和在回来的路上在两个地方使用。
And one more example: Let's say you want to convert to and from an integral which represents whatever duration system_clock
supports (microseconds, 10thof microseconds or nanoseconds). Then you don't have to worry about specifying milliseconds as above. The code simplifies to:
和一个例子:你要转换,并从代表任何时间不可分割的假设system_clock
支持(微秒,10个微秒或纳秒)。那么你就不必担心像上面那样指定毫秒。代码简化为:
int main ()
{
using namespace std::chrono;
// Get current time with native precision
auto now = system_clock::now();
// Convert time_point to signed integral type
auto integral_duration = now.time_since_epoch().count();
// Convert signed integral type to time_point
system_clock::time_point dt{system_clock::duration{integral_duration}};
// test
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
This works, but if you run half the conversion (out to integral) on one platform and the other half (in from integral) on another platform, you run the risk that system_clock::duration
will have different precisions for the two conversions.
这是可行的,但如果您在一个平台上运行一半的转换(输出到积分),而另一半(从积分输入)在另一个平台上,您将面临system_clock::duration
两种转换具有不同精度的风险。
回答by Feem
I would also note there are two ways to get the number of ms in the time point. I'm not sure which one is better, I've benchmarked them and they both have the same performance, so I guess it's a matter of preference. Perhaps Howard could chime in:
我还要注意有两种方法可以获得时间点的毫秒数。我不确定哪个更好,我已经对它们进行了基准测试,它们的性能相同,所以我想这是一个偏好问题。也许霍华德可以插话:
auto now = system_clock::now();
//Cast the time point to ms, then get its duration, then get the duration's count.
auto ms = time_point_cast<milliseconds>(now).time_since_epoch().count();
//Get the time point's duration, then cast to ms, then get its count.
auto ms = duration_cast<milliseconds>(tpBid.time_since_epoch()).count();
The first one reads more clearly in my mind going from left to right.
第一个在我的脑海中从左到右读得更清楚。
回答by Harald P.
as a single line:
作为一行:
long value_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch()).count();
回答by Mr. Llama
time_point
objectsonly support arithmetic with other time_point
or duration
objects.
time_point
对象仅支持与其他对象time_point
或duration
对象的算术运算。
You'll need to convert your long
to a duration
of specified units, then your code should work correctly.
您需要将long
a转换duration
为指定单位,然后您的代码应该可以正常工作。