2010-12-16 17 views
39

¿Hay alguna forma "estándar" o lo mejor que puedo hacer es calcularla directamente restando de gregorian::date(1970,1,1)?¿Cómo convierto boost :: posix_time :: ptime a time_t?

+4

Sólo un pensamiento; Estoy usando boost :: posix_time :: from_time_t (0) en lugar de tiempo explícito en el calendario gregoriano, para obtener un punto de referencia que se ajustará automáticamente a la época del sistema compilado. – Rawler

+0

@Rawler, eso es mucho mejor: he encontrado que la época real es aparentemente de 2000 n antes de lo que representa 'gregorian :: date (1970,1,1)'. –

+1

@BrianCain ¿De dónde sacaste 2000n antes de la marca de tiempo de la época infame? Por lo que recuerdo y he leído, siempre he oído que la época es 1970-01-01 00: 00: 00.0 UTC. –

Respuesta

14

time_t es el tipo utilizado para mantener el tiempo en segundos (por lo general, el tiempo de época). Supongo que estás después del tiempo de la época, si es así, no estoy al tanto de ninguna forma de aumentar el tiempo de época directamente, aparte de la resta que ya tienes. Una vez que tenga un time_duration (resultado de la resta), puede llamar al total_seconds() en la duración y almacenarlo en time_t.

btw. si buscas tiempo de época, puedes usar gettimeofday() y ahorrarte un dolor de cabeza.

5

Creo que lo mejor que puede hacer es usar to_tm para obtener una tm y mktime para convertir el tm a un time_t.

+3

Pero creo que mktime tiene un ajuste de zona horaria implícita (muestra el número de segundos de epoch en hora local) ' – gerrytan

31

Dado que el método de @hielocrime se convierte dos veces (ptime usa la representación lineal internamente), he decidido usar el cálculo directo en su lugar. Aquí está:

time_t to_time_t(boost::posix_time::ptime t) 
{ 
    using namespace boost::posix_time; 
    ptime epoch(boost::gregorian::date(1970,1,1)); 
    time_duration::sec_type x = (t - epoch).total_seconds(); 

    // ... check overflow here ... 

    return time_t(x); 
} 

EDIT: Gracias @jaaw por traer esto a mi atención. Desde el impulso 1.58, esta función se incluye en date_time/posix_time/conversion.hpp, std::time_t to_time_t(ptime pt).

+13

¡Qué pena que no lo hayan agregado como una función directa en la biblioteca ... Me pregunto cuáles son las razones fueron ... – Nim

+2

podrían hacer que ptime epoch sea estático versus computar cada llamada. –

+0

use std :: time_t posix_time :: to_time_t (posix_time :: ptime pt) en conversion.hpp – jaaw

14

Aquí hay una variación del método de @ ybungalobill que lo hará pasar 2038, por las dudas. :)

int64_t rax::ToPosix64(const boost::posix_time::ptime& pt) 
{ 
    using namespace boost::posix_time; 
    static ptime epoch(boost::gregorian::date(1970, 1, 1)); 
    time_duration diff(pt - epoch); 
    return (diff.ticks()/diff.ticks_per_second()); 
} 
+0

time_t ya tiene 64 bits en muchos sistemas. – ybungalobill

+1

Sí, pero cuando está escribiendo una aplicación multiplataforma, también debe admitir 32 bits. – kgriffs

+2

@ybungalobill: El problema no es tanto 'time_t' sino' time_duration :: sec_type' que es de 32 bits (al menos en mi máquina). –

2

Estas 2 líneas deberían hacerlo.

tm td_tm = to_tm(pt); 
time_t tt = mktime(&td_tm); 
+5

Lo que hay que tener cuidado con esto y la solución de icecrime anterior es el contrato de entrada de posix mktime. mktime toma una estructura "expresada como tiempo local, para representar el tiempo del calendario" y la convierte para usted. Sin embargo, boost p_time no hace ninguna conversión de TZ para usted al completar la tm struct. Por lo tanto, si está buscando un tiempo de época absoluto como el número de segundos desde el UTC del 1 de enero de 1970 a medianoche y el TZ local de su máquina no es GMT, esta llamada no le proporcionará lo que desea. Restar una época explícitamente construida y tomar la segunda diferencia es clara, obvia y segura a tz. – timmyl

Cuestiones relacionadas