Как преобразовать std::chrono::time_point в uint64_t?
Я пытаюсь выяснить, устарели ли мои данные 120 секунд (или 2 минуты), посмотрев на временную метку данных, поэтому я использую приведенный ниже код при использовании chrono
пакет в C++:
uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
// check for 2 minutes old data
bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));
uint64_t value = now;
while (now < data_holder->getTimestamp() + 80 * 1000
&& now < value + 80 * 1000) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
}
В приведенном выше коде 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
И из вышеприведенной метки времени держателя данных, похоже, что данные не старше 120 секунд, поэтому я чувствую, что в моем коде что-то не так? Поскольку, если я преобразую эту временную метку держателя данных в фактическое время (с использованием преобразователя эпох), а затем сравню ее со временем журналов, как показано выше, оно будет почти таким же.
Поэтому я решил использовать system_clock
вместо steady_clock
и придумал код ниже, в котором я начал использовать auto
вместо uint64_t
,
Решение А:
auto now = system_clock::now();
auto dh_ts = system_clock::time_point{milliseconds{data_holder->getTimestamp()}};
bool is_old = (minutes{2} < (now - dh_ts));
Ранее я использовал now
значение переменной как uint64_t
вместо auto
, Теперь после кода выше, у меня есть что-то подобное в моем исходном коде, так как now
не является uint64_t
поэтому я получаю ошибку компиляции при компиляции кода.
uint64_t value = now;
while (now < data_holder->getTimestamp() + 80 * 1000
&& now < value + 80 * 1000) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
}
Как правильно это исправить? Я не могу поменять data_holder->getTimestamp()
тип данных, это должно быть uint64_t
так как другой код также использует его.
Вот ошибка:
error: cannot convert std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1l, 1000000000l> > >â to âuint64_t {aka long unsigned int}â in initialization
ОБНОВИТЬ:
Могу ли я использовать как это вместо того, чтобы использовать Solution A
если все выглядит хорошо ниже?
Решение Б:
uint64_t now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));
2 ответа
На самом деле, я бы посоветовал пойти дальше в сторону решения А и преобразовать остальные ваши uint64_t
время в time_points: chrono
Система единиц довольно полезна. Я бы начал с определения вспомогательной функции для преобразования из uint64_t
временные метки ваших объектов в time_points:
using u64_millis = duration<uint64_t, milli>;
static time_point<system_clock, u64_millis> u64_to_time(uint64_t timestamp) {
return time_point<system_clock, u64_millis>{u64_millis{timestamp}};
}
если ваша эпоха отличается от system_clock
это было бы место, чтобы исправить это. Это, вероятно, также будет работать, чтобы использовать milliseconds
вместо u64_millis
, но тип представления для milliseconds
не определено явно, и выполнение вышеуказанного способа гарантирует, что типы совпадают правильно.
Теперь код, который вы разместили, становится примерно таким:
auto now = system_clock::now();
bool is_old = now - u64_to_time(data_holder->getTimestamp()) > minutes{2};
auto value = now;
while (now - u64_to_time(data_holder->getTimestamp()) < seconds{80}
&& now - value < seconds{80}) {
this_thread::sleep_for(milliseconds{100});
now = system_clock::now();
}
По крайней мере, пока я читаю, он спит 100 мс за раз, затем проверяет, спит ли он еще 2 минуты. Затем повторите, пока не достигнет 2-минутной точки.
Мне кажется, что имеет больше смысла вычислять желаемое время и спать до тех пор:
struct foo {
time_point<system_clock> time_stamp;
time_point<system_clock> get_timestamp() { return time_stamp; }
foo() : time_stamp(system_clock::now()) {}
};
// ...
foo f;
std::this_thread::sleep_until(f.get_timestamp() + 2m);
При этом используется пользовательский литерал (новый в C++14) для создания длительности 2 минуты. Если вам действительно нужно поддерживать более старый (C++11) компилятор, вам нужно использовать minutes(2)
вместо.
Что касается заглавного вопроса, я бы сказал: просто скажите нет. Намного лучше хранить ваши time_points как фактические time_points, чем настаивать на том, чтобы вставлять их в целые числа, а затем превращать их обратно в time_points, когда вам нужно будет использовать их снова. Совершенно не очевидно, что это приносит пользу в обмен на боль.