C ++如何将std :: chrono :: time_point转换为long和back

时间:2015-07-06 20:58:21

标签: c++ c++11 chrono

我需要将std::chrono::time_point转换为long类型(整数64位)。我开始使用std::chrono ...

这是我的代码:

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;
}

此代码编译,但未显示成功。

为什么dt最后与now不同?

该代码缺少什么?

4 个答案:

答案 0 :(得分:114)

std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();

这是auto的好地方:

auto now = std::chrono::system_clock::now();

由于您希望以millisecond精度进行流量,因此最好继续time_point

进行转换。
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);

now_mstime_point,基于system_clock,但精度为milliseconds,而不是system_clock的精确度。

auto epoch = now_ms.time_since_epoch();

epoch现在有std::chrono::milliseconds类型。而下一个陈述基本上变成了无操作(只是复制而不进行转换):

auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);

下面:

long duration = value.count();

在您和我的代码中,duration保留自milliseconds时代以来system_clock的数量。

此:

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

创建以duration表示的long,精度为seconds。这有效reinterpret_cast milliseconds valueseconds。这是一个逻辑错误。正确的代码如下:

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

这一行:

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

基于time_point创建system_clock,能够保持system_clock本机精度(通常小于毫秒)的精度。但是,运行时值将正确反映保持的整数毫秒数(假设我对dur的类型进行了更正)。

即使进行了更正,这项测试也会(几乎总是)失败但是:

if (dt != now)

由于dt包含整数milliseconds,但now包含的整数个刻度比millisecond更精细(例如microseconds或{{ 1}})。因此,只有在nanoseconds返回整数system_clock::now()的罕见机会才会通过测试。

但你可以改为:

milliseconds

现在,您将可靠地获得预期结果。

全部放在一起:

if (dt != now_ms)

就个人而言,我发现所有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; } 过于冗长,所以我将其编码为:

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;
}

最后,我建议消除临时性,以便将Success. 和整数类型之间的代码转换减少到最小。这些转换是危险的,因此编写操作裸积分类型的代码越少越好:

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; } 的路上将integral_duration解释为milliseconds。减轻这种风险的一种可能方法是写:

time_point

这样可以降低风险,只需确保在出路时使用 sys_milliseconds dt{sys_milliseconds::duration{integral_duration}}; ,并在返回途中的两个地方使用。{/ p>

还有一个例子:让我们说你要转换成一个积分来表示任何持续时间sys_milliseconds支持(微秒,10 th of microseconds或nanoseconds)。那么你不必担心如上所述指定毫秒。代码简化为:

system_clock

这是有效的,但是如果你在另一个平台上运行一半转换(转换为积分)而另一半转平(从积分转换为积分),则会冒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; } 具有不同精度的风险两次转换。

答案 1 :(得分:1)

我还要注意,有两种方法可以获得时间点的ms数。我不确定哪一个更好,我已经对它们进行了基准测试,它们都具有相同的性能,所以我想这是一个偏好问题。也许霍华德可能会说:

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();

第一个在我的脑海中从左到右读得更清楚。

答案 2 :(得分:0)

time_point objects仅支持与其他time_pointduration个对象进行算术运算。

您需要将long转换为指定单位的duration,然后您的代码才能正常运行。

答案 3 :(得分:0)

单行:

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();