使用 chrono c++ 库计算时间戳的差异

Using chrono c++ library to calculate difference of timestamp

跟进

我试图通过查看数据的时间戳来查看我的数据是否存在 120 秒,所以我在使用 std::chrono 包的库项目中有以下小代码:

uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));

// some logging to print out above values
LOG4CXX_WARN(logger, "data logging, now: " << now << ", data holder timestamp: " << data_holder->getTimestamp() << ", is_old: " << is_old << ", difference: " << (now -         data_holder->getTimestamp()));

在上面的代码中 data_holder->getTimestamp()uint64_t 其中 returns 时间戳以毫秒为单位。

现在当我打印出 now 变量值时,我看到这个 433425679 并且当我打印出 data_holder->getTimestamp() 值时 1437943796841 和现在的区别数据持有者时间戳将作为 18446742636199180454 出现,如下面的日志所示:

2015-07-26 13:49:56,850 WARN 0x7fd050bc9700 simple_process - data logging, now: 433425679 , data holder timestamp: 1437943796841 , is_old: 1 , difference: 18446742636199180454

现在,如果我使用纪元转换器转换数据持有者时间戳 1437943796841,我会看到:

Your time zone: 7/26/2015, 1:49:56 PM

这与日志中显示的时间戳完全相同 2015-07-26 13:49:56,850 WARN 因此这意味着我的数据看起来不是 120 秒的旧数据。如果是,那为什么我看到 is_old 值是 1?

看起来 data_holder->getTimestamp() 值来自我们代码库中的以下代码,然后我们正在比较它以进行 120 秒旧数据检查。

// is this the problem?
struct timeval val;
gettimeofday(&val, NULL);
uint64_t time_ms = uint64_t(val.tv_sec) * 1000 + val.tv_usec / 1000;

现在仔细阅读了C++中的各种时钟实现,看来我们应该使用相同的时钟来进行比较。

我计算 data_holder->getTimestamp() 值的上述代码是否有问题?因为我没有在那里使用 steady_clock,所以纪元时间会有所不同,这就是我看到这个问题的原因?

现在我的问题是 - 我应该使用什么代码来解决这个问题? data_holder->getTimestamp() 代码也应该使用 steady_clock 吗?如果是,那么正确的方法是什么?

同样的代码在 Ubuntu 12 框中工作正常,但在 Ubuntu 14 中不能正常工作。我是 运行 所有静态链接库。对于 Ubuntu 12,代码在 Ubuntu 12 运行 4.7.3 编译器上编译,对于 Ubuntu 14,代码在 Ubuntu 14 [=61= 上编译] 4.8.2编译器。

你应该明确地为两者使用相同的时间函数。

我建议更改创建 getTimestamp() 值的方式(例如,通过使用 chrono::system_clock)或比较时间戳的方式。

干净的方法是像这样更改它:

struct timeval val;
gettimeofday(&val, NULL);
uint64_t now = uint64_t(val.tv_sec) * 1000 + val.tv_usec / 1000;
bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));

或者反过来

1.Change getTimestamp() 值的创建方式

long long time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();

2.Adjust 比较函数

long long now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));

两者使用相同的时钟。如果您的时间戳需要在应用程序的 运行 中保持意义,则必须使用 system_clock,而不是 steady_clock。如果您的时间戳仅在单个 运行 中有意义,您可以使用 steady_clock.

steady_clock 就像 "stopwatch"。你可以用它来计时,但你不能用它来获取当前时间。

DataHolder::DataHolder()
    : timestamp_{system_clock::now()}
    {}

system_clock::time_point
DataHolder::getTimestamp()
{
    return timestamp_;
}

bool is_old = minutes{2} < system_clock::now() - data_holder->getTimestamp();

在 C++14 中,您可以将其缩短为:

bool is_old = 2min < system_clock::now() - data_holder->getTimestamp();

  • 请使用 <chrono>
  • 不要使用 count()time_since_epoch()(调试目的除外)。
  • 不要使用 1000120 等换算系数。

违反上述准则会将编译时错误变成 运行 时错误。编译时错误是你的朋友。 <chrono> 在编译时捕获许多错误。一旦你逃避了 <chrono> 的类型安全(例如通过使用 count()),你就在用相当于计时的汇编语言编程。 space/time <chrono> 类型安全系统的开销为零。