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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:54:38  来源:igfitidea点击:

C++ How do I convert a std::chrono::time_point to long and back

c++c++11chrono

提问by Mendes

I need to convert std::chrono::time_pointto and from a longtype (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 dtdifferent than nowat 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 millisecondprecision, 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_msis a time_point, based on system_clock, but with the precision of millisecondsinstead of whatever precision your system_clockhas.

now_mstime_point,基于system_clock,但精度为 ,milliseconds而不是您system_clock拥有的任何精度。

auto epoch = now_ms.time_since_epoch();

epochnow 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, durationholds the number of millisecondssince the epoch of system_clock.

在你和我的代码中,都duration保存了millisecondssystem_clock.

This:

这个:

std::chrono::duration<long> dur(duration);

Creates a durationrepresented with a long, and a precision of seconds. This effectively reinterpret_casts the millisecondsheld in valueto seconds. It is a logic error. The correct code would look like:

创建一个duration表示为long,精度为seconds。这实际上reinterpret_castmilliseconds保持在valueto 中seconds。这是一个逻辑错误。正确的代码如下所示:

std::chrono::milliseconds dur(duration);

This line:

这一行:

std::chrono::time_point<std::chrono::system_clock> dt(dur);

creates a time_pointbased 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 dtholds an integral number of milliseconds, but nowholds an integral number of ticks finer than a millisecond(e.g. microsecondsor nanoseconds). Thus only on the rare chance that system_clock::now()returned an integral number of millisecondswould the test pass.

因为dt持有整数个milliseconds,但now持有整数个比 a 更细的刻度millisecond(例如microsecondsnanoseconds)。因此,只有在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::chronooverly 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_pointand 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_durationas millisecondson the way back to a time_point. One possible way to mitigate that risk is to write:

上面的主要危险不是解释integral_durationmilliseconds在返回 a 的路上time_point。减轻这种风险的一种可能方法是编写:

    sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};

This reduces risk down to just making sure you use sys_millisecondson 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_clocksupports (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::durationwill 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_pointobjectsonly support arithmetic with other time_pointor durationobjects.

time_point对象仅支持与其他对象time_pointduration对象的算术运算。

You'll need to convert your longto a durationof specified units, then your code should work correctly.

您需要将longa转换duration为指定单位,然后您的代码应该可以正常工作。