2012-02-10 20 views
8

Ho un timestamp in epoca frazionaria, rappresentato come double, che vorrei convertire in un appropriato std::chrono::time_point. L'epoca è la solita epoca UNIX dall'1/1/1970. So che esiste std::chrono::system_clock::from_time_t, ma uno time_t non ha una parte frazionaria. Quale sarebbe il modo migliore per farlo con C++ 11 significa?Come convertire un timestamp di epoca epocale (doppio) in uno std :: chrono :: time_point?

Questa domanda è relativa a unix timestamp to boost::posix_time::ptime, tranne che richiede il C++ 11 anziché la versione Boost.

+0

Hai letto sopra [N2661] (http://www.open-std.org/jtc1/sc22/ WG21/docs/documenti/2008/n2661.htm)? – ildjarn

+0

"(...) timestamp in epoca frazionaria, rappresentato come' double' "Quali unità? Conosci l'epoca? –

+0

@ R.MartinhoFernandes: è l'epoca UNIX standard dall'1/1/1970. – mavam

risposta

12

Supponendo che l'epoca sia la stessa di un tipo noto clock, è possibile utilizzare una durata con una rappresentazione double e convertirla nella durata utilizzata da tale orologio.

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

Questo dovrebbe essere ok per qualsiasi calcolo che coinvolge che l'orologio, dal momento che si sta utilizzando la stessa precisione come l'orologio, ma può perdere un po 'della precisione nella conversione. Se non vuoi perdere, dovrai utilizzare una specializzazione time_point che utilizza il tipo di durata basato su double. E poi usalo nei tuoi calcoli (ovviamente, con tutti gli avvertimenti della matematica in virgola mobile).

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

Tuttavia, questo complica i calcoli coinvolgono stesso orologio, in quanto richiede conversioni. Per facilitare questa operazione, è possibile costruire il proprio involucro orologio che fa le conversioni e l'uso che:

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() 
       )); 
    } 
}; 
+0

cosa succede con '324324.342'? – Puppy

+0

Grazie per la risposta. Ti dispiacerebbe elaborare dove proviene la perdita di precisione? Inoltre, l'orologio in "d_time_point" può essere arbitrario? – mavam

+0

@Matthias: la perdita di precisione è dovuta al fatto che il tipo di durata nativa dell'orologio potrebbe non essere in grado di rappresentare la durata esatta che si ha come 'double'. Ad esempio, se la durata è 10,5 secondi, ma l'orologio utilizza una durata integrale con periodo 1 secondo, diventerà 10 o 11 se convertito. Idealmente, il tipo di orologio in "d_time_point" dovrebbe essere uno con la stessa epoca. –

Problemi correlati