2011-01-28 9 views
6

Me gustaría transferir boost::posix_time::ptime a través de la red como boost::int64_t. De acuerdo con A way to turn boost::posix_time::ptime into an __int64, puedo definir fácilmente mi propia época y solo transferir time_duration de esa época de referencia como un entero de 64 bits. Pero, ¿cómo convertir de nuevo a ptime?Convierte int64_t en time_duration

#include <iostream> 
#include <cassert> 
#include <boost/date_time/posix_time/posix_time.hpp> 
#include <boost/date_time/gregorian/greg_month.hpp> 

using namespace std; 

using boost::posix_time::ptime; 
using boost::posix_time::time_duration; 
using boost::gregorian::date; 

int main(int argc, char ** argv){ 
    ptime t = boost::posix_time::microsec_clock::local_time(); 

    // convert to int64_t 
    ptime myEpoch(date(1970,boost::gregorian::Jan,1)); 
    time_duration myTimeFromEpoch = t - myEpoch; 
    boost::int64_t myTimeAsInt = myTimeFromEpoch.ticks(); 

    // convert back to ptime 
    ptime test = myEpoch + time_duration(myTimeAsInt); 

    assert(test == t); 
    return 0; 
} 

Esto no está funcionando ya que el constructor time_duration tomando un recuento de paso como argumento es privado. También estoy interesado en cualquier otra forma para simplemente transferir ese ptime sobre tipos de datos simples.

+1

¿El valor devuelto por ticks() es portátil entre las máquinas? Es posible que necesite usar ticks_per_second() para normalizarlo. Si myEpoch es el mismo en ambos extremos, ¿por qué no puedes simplemente transferir una marca de tiempo de una época de milisegundos de 64 bits? – hplbsh

+0

Está trabajando con una resolución de milisegundos. ¿Podría publicar su comentario como respuesta, por favor? – tibur

Respuesta

5

Solución de trabajo con una resolución de milisegundos:

int main(int argc, char ** argv){ 
    ptime t = boost::posix_time::microsec_clock::local_time(); 

    // convert to int64_t 
    ptime myEpoch(date(1970,boost::gregorian::Jan,1)); 
    time_duration myTimeFromEpoch = t - myEpoch; 
    boost::int64_t myTimeAsInt = myTimeFromEpoch.total_milliseconds(); 

    // convert back to ptime 
    ptime test = myEpoch + boost::posix_time::milliseconds(myTimeAsInt); 

    cout << test << endl; 
    cout << t << endl; 

    time_duration diff = test - t; 

    assert(diff.total_milliseconds()==0); 
    return 0; 
} 

Gracias 12a6.

+3

No creo que esta respuesta funcione para sistemas de 32 bits. Intenté esto en un sistema de 32 bits usando una época de 1901-01-01 00:00:00 y no funcionará. Claramente funciona para usted, pero el argumento para 'milisegundos()' es de tipo largo y el retorno de 'total_milliseconds()' también es de tipo largo para que no pierda nada en el molde implícito de int64_t a largo. – mathematician1975

+0

Esto funciona solo en compiladores donde largo es de 64 bits independientemente de la plataforma. En MSVC de 32 bits, long es 32 bits. –

2

Obras con cualquier resolución máxima de su biblioteca boost::datetime se compila a (típicamente micros/nanos):

time_duration time_duration_from_ticks(time_duration::tick_type ticks) 
{ 
    return time_duration(
     0,           // hours 
     0,           // minutes 
     ticks/time_duration::ticks_per_second(), // seconds 
     ticks % time_duration::ticks_per_second()); // fractional_seconds 
} 

(Tenga en cuenta que time_duration::tick_type es su int64_tsi haber configurado fecha y hora impulso sólo con resolución de microsegundos, que es el valor por defecto)

+1

Pero, el argumento 'seconds' debe ser de 32 bits en mi compilador de Windows 7 VS2013. Entonces, el problema 2038 todavía existe con esta solución. –

+0

Debo estar siendo tonto, pero no veo por qué debe ser de 32 bits -'ticks' será de 64 bits (incluso en el arco de 32 bits). –

+2

Si observa este constructor particular para 'time_duration', encontrará que el tercer parámetro se define como 32 bits. De hecho, he usado este constructor y las fechas son incorrectas, exactamente como uno esperaría para el problema del año 2038. Sin embargo, puede hacerse de manera simple y evitar el problema 2038 usando milisegundos; ver http://stackoverflow.com/a/26211377/368896 para una respuesta funcional. –

0

Con una resolución de microsegundos TIME_DURATION:.

boost::posix_time::microseconds(_ts/TICKS_PER_MICROSECOND) 

donde TICKS_PER_MICROSECOND es el número de tics por microsegundo (por ejemplo, 10 si los tics son hectonanosegundos, como en Windows FILETIME).

La razón por la que el constructor de milisegundos parece funcionar para algunas personas es que acepta un tipo de parámetro de largo, que es de 64 bits en algunos compiladores. En MSVC, es de 32 bits en plataformas de 32 bits, por lo que no funcionará. El constructor de microsegundos acepta un entero de 64 bits, que debería ser "suficiente para todos".