2012-02-10 21 views
8

Tengo una marca de tiempo de época fraccionaria, representada como double, que me gustaría convertir a un std::chrono::time_point apropiado. La época es la época UNIX habitual desde 1/1/1970. Sé que existe std::chrono::system_clock::from_time_t, pero time_t no tiene una parte fraccionaria. ¿Cuál sería la mejor manera de hacer esto con C++ 11 significa?Cómo convertir una marca de tiempo de época fraccional (doble) a std :: chrono :: time_point?

Esta pregunta está relacionada con unix timestamp to boost::posix_time::ptime, excepto que está pidiendo la versión C++ 11 en lugar de Boost.

+0

¿Ha leído sobre [N2661] (http://www.open-std.org/jtc1/sc22/ wg21/docs/papers/2008/n2661.htm)? – ildjarn

+0

"(...) marca de tiempo de época fraccional, representada como' doble' "¿Qué unidades? ¿Conoces la época? –

+0

@ R.MartinhoFernandes: es la época estándar de UNIX desde el 1/1/1970. – mavam

Respuesta

12

Suponiendo que el epoch es el mismo que el tipo clock conocido, puede usar una duración con una representación double y convertirla a la duración utilizada por ese reloj.

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

Esto debería estar bien para cualquier cálculo que implica que el reloj, ya que está utilizando la misma precisión que el reloj, pero puede perder parte de la precisión en la conversión. Si no quiere perder eso, tendrá que usar una especialización time_point que use ese tipo de duración basada en double. Y luego use eso en sus cálculos (por supuesto, con todas las salvedades de las matemáticas de coma flotante).

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

Sin embargo, esto complicará cualquier cálculo que implique ese mismo reloj, ya que requerirá conversiones. Para hacer esto más fácil, usted puede construir su propio envoltorio reloj que hace las conversiones y el uso que:

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

¿Qué pasa con '324324.342'? – Puppy

+0

Gracias por la respuesta. ¿Te importaría explicar dónde se origina la pérdida de precisión? Además, ¿el tipo de reloj en 'd_time_point' puede ser arbitrario? – mavam

+0

@Matthias: la pérdida de precisión se debe a que el tipo de duración nativa del reloj puede no ser capaz de representar la duración exacta que tiene como 'doble'. Como ejemplo, si la duración es de 10.5 segundos, pero el reloj usa una duración integral con un período de 1 segundo, se convertirá en 10s o 11s cuando se convierta. Idealmente, el tipo de reloj en 'd_time_point' debe ser uno con la misma época. –

Cuestiones relacionadas