我试图通过查看数据的时间戳来查看我的数据是否为120秒旧数据,所以我有以下代码:
uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));
在上面的代码中,
data_holder->getTimestamp()
是uint64_t,它以毫秒为单位返回时间戳。现在,当我打印出
now
变量值时,我看到了这个10011360
,并且当我打印出了data_holder->getTimestamp()
的1437520382241
值时,现在和数据持有人时间戳的差应该为负吗?为什么它变得如下面的日志所示为正?2015-07-21 16:13:02,530 WARN 0x7f35312d1700 data_check - now value: 10011360 , data holder timestamp: 1437520382241 , difference: 18446742636199180735
我上面的代码看起来正确吗?从上面的数据持有者时间戳来看,看起来好像不是120秒的旧数据,所以我觉得我的代码有问题吗?因为如果我将数据持有者时间戳转换为实际时间(使用纪元转换器),然后将其与日志时间进行比较(如上所示),则几乎是相同的。
我正在使用上面显示的
steady_clock
。我需要在这里使用system_clock
吗?在外行方面,steady_clock
和system_clock
有什么区别。我在Ubuntu 14.04机器上运行此代码。
最佳答案
以相反的顺序回答问题:
What is the difference between
steady_clock
vssystem_clock
in layman terms.
如果您手里拿着
system_clock
,您将其称为 watch ,它会告诉您现在几点了。如果您手里拿着
steady_clock
,您将其称为秒表,它将告诉您某人跑完一圈的速度,但不会告诉您现在几点。如果需要的话,您可以安排某人为您的 watch 跑一圈。但是,如果您的 watch (例如我的 watch )定期与另一台机器(例如Boulder CO中的原子钟)通话以将其校正为当前时间,则在计时该圈时可能会犯一些小错误。秒表不会犯该错误,但也无法告诉您正确的当前时间。
Does my above code look right?
不。即使它给了您合理的答案,我也不会说这是正确的。别担心,这是很多人使用
<chrono>
库犯的初学者错误。我遵循
<chrono>
库有一个简单的规则。该规则实际上并不完全正确(因此这是一个准则)。但是,它几乎足以纠正成为几乎始终遵循的准则:Don't use
count()
.
还有一个推论:
Don't use
time_since_epoch()
.
<chrono>
库围绕类型安全的系统设计,旨在保护您免受单位转换错误的影响。如果您不小心尝试了不安全的转换,则该错误将在编译时捕获(与之相反,它是运行时错误)。成员函数
count()
和time_since_epoch()
是此类型安全系统中的“转义线”,仅在紧急情况下使用。当(例如)委员会忽视为您提供完成<chrono>
类型的工作所需的所有工具(例如I/O),或者例如需要通过整数与其他一些计时API交互时,就会出现此类紧急情况。复查您的代码和其他代码是否使用
count()
和time_since_epoch()
,并仔细检查这些函数的每种用法:是否可以通过任何方式重写代码以消除其使用?查看代码的第一行:
uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
now
是time_point
(来自steady_clock
)。它的单位是milliseconds
,但是目前我不认为这些单位很重要。重要的是now
是从time_point
检索的steady_clock
:auto now = steady_clock::now();
您的第二行更加复杂:
bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));
让我们从
data_holder->getTimestamp()
开始:如果可以修改getTimestamp()
,则应该对其进行修改以返回time_point
而不是uint64_t
。为此,您将必须知道正确的单位(毫秒),和,您必须知道正确的纪元。纪元是您以毫秒为单位的时间点。在这种情况下1437520382241ms大约是45.6年。假设这是最近的时间戳,则45.6年前的时间与1970-01-01非常接近。事实证明,
system_clock()
的每个实现都使用1970-01-01作为其纪元(尽管每个实现从该纪元计算出不同的单位)。因此,要么修改
getTimestamp()
以返回time_point<system_clock, milliseconds>
,要么将getTimestamp()
的返回结果包装在time_point<system_clock, milliseconds>
中:auto dh_ts = system_clock::time_point{milliseconds{data_holder->getTimestamp()}};
现在您的第二行是:
bool is_old = (120 * 1000 < (now - dh_ts));
另一个好的准则:
If you see conversion factors in your
<chrono>
code, you're doing it wrong.<chrono>
lives for doing the conversions for you.
bool is_old = (minutes{2} < (now - dh_ts));
下一步是风格上的,但是现在代码很简单,可以消除多余的括号(如果这对您很有吸引力):
bool is_old = minutes{2} < now - dh_ts;
如果您能够修改
getTimestamp()
以返回类型安全的值,则该代码也可能类似于:bool is_old = minutes{2} < now - data_holder->getTimestamp();
las,无论如何,这仍然无法编译!错误消息应大致说明
operator-()
和now
之间没有有效的dh_ts
。This is the type-safety system coming in to save you from run time errors!
问题在于无法从
time_point
的system_clock
减去time_point
的steady_clock
(因为两者具有不同的时期)。因此,您必须切换到:auto now = system_clock::now();
放在一起:
#include <chrono>
#include <cstdint>
#include <memory>
struct DataHolder
{
std::chrono::system_clock::time_point
getTimestamp()
{
using namespace std::chrono;
return system_clock::time_point{milliseconds{1437520382241}};
}
};
int
main()
{
using namespace std;
using namespace std::chrono;
auto data_holder = std::unique_ptr<DataHolder>(new DataHolder);
auto now = system_clock::now();
bool is_old = minutes{2} < now - data_holder->getTimestamp();
}
在C++ 14中,可以使最后一行更加简洁:
bool is_old = 2min < now - data_holder->getTimestamp();
综上所述:
count()
(I/O除外)。 time_since_epoch()
(I/O除外)。 如果您在以上四点中都成功了,则很可能不会遇到任何运行时错误(但是您会得到相当一部分编译时错误)。
关于c++ - 稳定时钟与系统时钟之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31552193/