Подтвердить что ты не робот

Сохранение экземпляров std:: chrono time_point

Каков правильный способ сохранения экземпляров std:: chrono time_point и затем их повторного чтения в другой экземпляр того же типа?

   typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t;

   time_point_t tp = std::chrono::high_resolution_clock::now();
   serializer.write(tp);
   .
   .
   .
   time_point_t another_tp;
   serializer.read(another_tp);

Призывы к записи/чтению предполагают, что экземпляр типа time_point_t может быть каким-то образом преобразован в представление байтов, которое затем может быть записано или прочитано с диска или сокета и т.д.

Возможное решение, предложенное Alf, выглядит следующим образом:

   std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();

   //Generate POD to write to disk
   unsigned long long ns0 = t0.time_since_epoch().count();

   //Read POD from disk and attempt to instantiate time_point
   std::chrono::high_resolution_clock::duration d(ns0)

   std::chrono::high_resolution_clock::time_point t1(d);

   unsigned long long ns1 = t1.time_since_epoch().count();

   if ((t0 != t1) || (ns0 != ns1))
   {
      std::cout << "Error time points don't match!\n";
   }

Примечание.. Приведенный выше код имеет ошибку, поскольку конечный момент времени, указанный в момент времени, не соответствует оригиналу.

В случае старого стиля time_t, как правило, просто записывается весь объект на диск на основе его sizeof, а затем считывается обратно таким же образом. Короче говоря, что эквивалентно новым типам std:: chrono

4b9b3361

Ответ 1

конструктор time_point принимает duration, и вы можете получить duration из члена time_since_epoch. поэтому вопрос сводится к сериализации значения duration. и duration имеет конструктор, который принимает несколько тиков, и функцию-член count, которая производит количество тиков.

все это просто с помощью googling std::chrono::time_point и, глядя на документацию cppreference, Google приземлился на меня.

часто бывает полезно прочитать документация.


Добавление: пример.

#include <chrono>
#include <iostream>
#include <typeinfo>
using namespace std;

auto main() -> int
{
    using Clock = chrono::high_resolution_clock;
    using Time_point = Clock::time_point;
    using Duration = Clock::duration;

    Time_point const t0 = Clock::now();

    //Generate POD to write to disk
    Duration::rep const ns0 = t0.time_since_epoch().count();

    //Read POD from disk and attempt to instantiate time_point
    Duration const d(ns0);
    Time_point const t1(d);

    cout << "Basic number type is " << typeid( ns0 ).name() << "." << endl;
    if( t0 != t1 )
    {
        cout << "Error time points don't match!" << endl;
    }
    else
    {
        cout << "Reconstituted time is OK." << endl;
    }
}

С Visual С++ 12.0 основной тип сообщения __int64, т.е. long long, а при g++ 4.8.2 в Windows указанный тип x, который предположительно означает то же самое.

С обоими компиляторами восстановленное время идентично оригиналу.

Добавление: как отмеченное Dina в комментариях, как и в С++ 14, стандарт С++ не указывает эпоху, и поэтому для выполнения этой работы через машины или с разными часами необходимо добавить дополнительные шаги, которые нормализуют эпоху для сериализованных данных, например и, наиболее естественно, Posix time, то есть время с 00:00:00 Скоординированное универсальное время (UTC), четверг, 1 января 1970 года.

Ответ 2

Чтение с диска или сокета означает, что вы можете читать в экземпляре приложения, которое не выполняло запись. И в этом случае сериализация только одной продолжительности недостаточно.

A time_point - это время duration с неопределенной эпохи. Эпоха могла быть чем угодно. На моем компьютере эпоха std::chrono::high_resolution_clock - всякий раз, когда компьютер загружается. То есть эти часы сообщают о количестве наносекунд с момента загрузки.

Если одно приложение записывает time_since_epoch(). count(), компьютер перезагружается, а затем другое (или даже одно и то же) приложение считывает его обратно, значение чтения не имеет никакого значения, если только вы случайно не знайте количество времени между ботинками.

Чтобы надежно сериализовать a time_point, необходимо учесть, что писатель и читатель согласны с какой-то эпохой, а затем убедитесь, что текст time_point написан и прочитан относительно этой эпохи. Например, можно было бы использовать эпоху POSIX: Новый год 1970 UTC.

Как оказалось, каждая реализация std::chrono::system_clock, о которой я знаю, использует Unix time, близкое приближение UTC, измеренное от Нового года 1970. Однако я не знаю общей эпохи для std::chrono::high_resolution_clock.

Только если вы можете каким-то образом убедиться, что часы считывателя и писателя совпадают с общей эпохой, вы можете сериализовать time_point как продолжительность.