Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a fractional epoch timestamp (double) to an std::chrono::time_point?

I have a fractional epoch timestamp, represented as double, that I would like to convert to an appropriate std::chrono::time_point. The epoch is the usual UNIX epoch since 1/1/1970. I know that there exists std::chrono::system_clock::from_time_t, but a time_t does not have a fractional part. What would be the best way to do this with C++11 means?

This question is related to unix timestamp to boost::posix_time::ptime, except that it's asking for the C++11 rather than Boost version of it.

like image 314
mavam Avatar asked Feb 10 '12 00:02

mavam


1 Answers

Assuming the epoch is the same as a known clock type you can use a duration with a double representation and convert to the duration used by that clock.

// 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);

This should be ok for any calculation involving that clock, since you're using the same precision as the clock, but it may lose some of the precision in the conversion. If you don't want to lose that you'll have to use a time_point specialization that uses that double-based duration type. And then use that in your calculations (of course, with all the caveats of floating-point math).

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

However, this will complicate any calculations involving that same clock, as it will require conversions. To make this easier, you can build your own clock wrapper that does the conversions and use that:

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()
               ));
    }
};
like image 151
R. Martinho Fernandes Avatar answered Sep 28 '22 14:09

R. Martinho Fernandes