使用std :: chrono进行时间戳记-如何基于相对时间“过滤”数据? 以秒为单位获取时钟的周期和每秒滴答值获取时钟的时间点现在作为uint64值以对数据流进行时间戳记根据存储的uint64值获取时钟时间点

问题描述

我想对我产生的数据流进行时间标记,为此我要使用 std :: chrono :: steady_clock

这些时间戳与数据一起存储(作为uint64值的数组吗?),以后我将需要再次处理这些时间戳。

现在,到目前为止我还没有使用过std :: chrono库,因此我确实需要一些有关该库的语法和最佳实践的帮助。

我可以使用以下方法获取和存储值:

uint64_t timestamp = std::chrono::steady_clock::Now().time_since_epoch().count();

但我该怎么办:

  • 在读取数据时,从uint64创建一个时间点吗?

  • 是否获取稳定时钟的每秒滴答数(uint64)?

  • 找到一个在给定时间点之前一定时间(以秒为单位)的“截止”时间点(如uint64)?

上面的代码段将不胜感激。

我想结合以上三个基本内容来执行以下操作:具有一组(递增的)时间戳记值(如uint64),我希望将其截断,以使所有数据都比上次时间戳记“旧”减去X秒。

解决方法

让我们看看您可能在chrono的cppreference文档中使用的功能。

首先,您需要确定要使用哪个时钟。您建议使用steady_clockhigh_resolution_clocksystem_clock

high_resolution_clock是依赖于实现的,所以除非我们确实需要它,否则我们将其丢弃。 steady_clock可以保证是单调的,但是不能保证所获得的值的含义。是对事件进行排序或测量其间隔的理想选择,但您无法从中获得时间点。

另一方面,system_clock的含义是UNIX时代,因此您可以从中获取时间值,但不能保证它是单调的。

要获取steady_clock的时间段(一滴答的持续时间),您需要拥有period成员:

auto period = std::chrono::steady_clock::period();
std::cout << "Clock period " << period.num << " / " << period.den << " seconds" << std::endl;
std::cout << "Clock period " << static_cast<double>(period.num) / period.den << " seconds" << std::endl;

假设您要使用steady_clock值过滤最近几秒钟内发生的事件,则首先需要计算所需时间段内的滴答数,并将其从now中减去。类似于:

std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t t_c = std::chrono::system_clock::to_time_t(now - std::chrono::seconds(10));

并使用t_c作为截止点。

但是,不要依靠std::chrono::steady_clock::now().time_since_epoch().count();来获得有意义的东西-仅仅是数字。 steady_clock的时期通常是启动时间。如果需要时间,则应使用system_clock(请注意,这不是单调的)。

C ++ 20a引入了更多的时钟,这些时钟可以转换为时间。

,

由于我花了很长时间才从今天的各种来源中弄清楚,所以我将在此处发布我的解决方案作为自我解答。 (我希望对此发表评论,以防万一某些事情不正确或可以做得更好。)

以秒为单位获取时钟的周期和每秒滴答值

    using namespace std::chrono;
    auto period = system_clock::period();
    double period_s = (double) period.num / period.den; 
    uint64 tps = period.den / period.num;

获取时钟的时间点(现在)作为uint64值以对数据流进行时间戳记

    using namespace std::chrono;
    system_clock::time_point tp_now = system_clock::now();
    uint64 nowAsTicks = tp_now.time_since_epoch().count();

根据存储的uint64值获取时钟时间点

    using namespace std::chrono;
    uint64 givenTicks = 12345;  // Whatever the value was
    system_clock::time_point tp_recreated = system_clock::time_point{} + system_clock::duration(givenTicks);
    uint64 recreatedTicks = tp_now.time_since_epoch().count();
    Assert( givenTicks == recreatedTicks );  // has to be true now

最后一个(从uint64到timepoint)让我最困扰。所需的主要见解是:

  • (在Win10上) system_clock 使用100纳秒的时间分辨率。因此,不能直接将std::chrono::nanoseconds添加到其本地时间点。 (std::chrono:system_clock_time_point

  • 但是,由于刻度是100纳秒,因此也不能使用下一个较高的持续时间单位(微秒),因为它不能表示为整数值。

  • 一个人可以使用 explicit 强制转换为微秒,但这会降低刻度的0.1us分辨率。

  • 正确的方法是使用system_clock自己的持续时间,并使用存储的滴答值直接对其进行初始化。

在搜索中,我发现以下资源最有帮助:

,

参考手册是通常看起来不错的地方:

https://en.cppreference.com/w/cpp/chrono

在这种情况下,您正在寻找:

https://en.cppreference.com/w/cpp/chrono/clock_time_conversion

因为实际上您使用的时钟是“历元” 1/1/70作为原点,而ms作为单位。 然后只需对持续时间使用算术即可完成所需的截止时间:

https://en.cppreference.com/w/cpp/chrono/duration

每个链接页面底部都有代码示例。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...