Как преобразовать метку времени дробной эпохи (double) в точку std :: chrono :: time_point? - PullRequest
8 голосов
/ 10 февраля 2012

У меня есть отметка времени дробной эпохи, представленная как double, которую я хотел бы преобразовать в соответствующий std::chrono::time_point. Эпоха - обычная эпоха UNIX с 1 января 1970 года. Я знаю, что существует std::chrono::system_clock::from_time_t, но time_t не имеет дробной части. Каков наилучший способ сделать это с помощью средств C ++ 11?

Этот вопрос относится к метке времени unix для boost :: posix_time :: ptime , за исключением того, что он запрашивает C ++ 11, а не Boost-версию.

1 Ответ

13 голосов
/ 10 февраля 2012

Предполагая, что эпоха совпадает с известным типом clock, вы можете использовать длительность с представлением double и преобразовать в длительность, используемую этими часами.

// change period to appropriate units - I'm assuming seconds
typedef std::chrono::duration<double, std::ratio<1>> d_seconds;

d_seconds since_epoch_full(324324.342);
auto since_epoch = std::chrono::duration_cast<clock::duration>(since_epoch_full);
clock::time_point point(since_epoch);

Это должно быть в порядкедля любых вычислений, связанных с этими часами, поскольку вы используете ту же точность, что и часы, но они могут потерять часть точности при преобразовании.Если вы не хотите потерять это, вам придется использовать специализацию time_point, которая использует этот тип продолжительности double.И затем используйте это в своих вычислениях (конечно, со всеми предостережениями математики с плавающей точкой).

typedef std::chrono::time_point<clock, d_seconds> d_time_point;

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

template <typename Clock>
struct my_clock_with_doubles {
    typedef double rep;
    typedef std::ratio<1> period;
    typedef std::chrono::duration<rep, period> duration;
    typedef std::chrono::time_point<my_clock_with_doubles<Clock>> time_point;
    static const bool is_steady = Clock::is_steady;

    static time_point now() noexcept {
        return time_point(std::chrono::duration_cast<duration>(
                   Clock::now().time_since_epoch()
               ));
    }

    static time_t to_time_t(const time_point& t) noexcept {
        return Clock::to_time_t(typename Clock::time_point(
                             std::chrono::duration_cast<typename Clock::duration>(
                                 t.time_since_epoch()
                             )
                        ));
    }
    static time_point from_time_t(time_t t) noexcept {
        return time_point(std::chrono::duration_cast<duration>(
                   Clock::from_time_t(t).time_since_epoch()
               ));
    }
};
...