2009-04-17 14 views
27

¿Cuál es la mejor manera de convertir las fechas entre hora local y UTC en C/C++?Convirtiendo entre horas locales y GMT/UTC en C/C++

Por "datetime", me refiero a una representación de tiempo que contiene la fecha y la hora del día. Estaré contento con time_t, struct tm, o cualquier otra representación que lo haga posible.

Mi plataforma es Linux.

Aquí está el problema específico que estoy tratando de resolver: obtengo un par de valores que contienen una fecha juliana y una cantidad de segundos en el día. Esos valores están en GMT. Necesito convertir eso a un valor de "zona horaria local" AAAAMMDDHHMMSS ". Sé cómo convertir la fecha juliana a Y-M-D, y obviamente es fácil convertir segundos en HHMMSS. Sin embargo, la parte difícil es la conversión de la zona horaria. Estoy seguro de que puedo encontrar una solución, pero preferiría encontrar una manera "estándar" o "conocida" en lugar de tropezar.


Una cuestión relacionada es posiblemente Get Daylight Saving Transition Dates For Time Zones in C

Respuesta

21

Se supone que debes usar combinaciones de gmtime/localtimetimegm y/mktime. Eso debería darle las herramientas ortogonales para hacer conversiones entre struct tm y time_t.

Por UTC/GMT:

time_t t; 
struct tm tm; 
struct tm * tmp; 
... 
t = timegm(&tm); 
... 
tmp = gmtime(t); 

Para localtime:

t = mktime(&tm); 
... 
tmp = localtime(t); 

Todo tzset() hace es establecer la variable de zona horaria interna de la variable TZ medio ambiente. No creo que se suponga que se llame más de una vez.

Si está intentando convertir zonas horarias, debe modificar el tm_gmtoff.

+0

Gracias! Sabía que algo como timegm() tenía que existir, pero no sabía el nombre. –

+0

Me alegra ayudar. La conversión de tiempo puede ser un área bastante complicada. Por lo general, es una buena idea almacenar todo en UTC siempre que sea posible. Convertir entre zonas horarias es aún más complicado. –

+1

Sí, lamentablemente los diseñadores del sistema eligieron la hora local como el formato de marca de tiempo "estándar" para el protocolo de mensajería. Odio cuando la gente hace eso. –

2

Si necesita preocuparse por la conversión de fecha/hora con las reglas de zona horaria, es posible que desee consultar ICU.

17

Si en Windows, usted no tiene timegm() a su disposición:

struct tm *tptr; 
time_t secs, local_secs, gmt_secs; 
time(&secs); // Current time in GMT 
// Remember that localtime/gmtime overwrite same location 
tptr = localtime(&secs); 
local_secs = mktime(tptr); 
tptr = gmtime(&secs); 
gmt_secs = mktime(tptr); 
long diff_secs = long(local_secs - gmt_secs); 

o algo similar ...

+0

¿No deberían ser idénticos' secs' y 'gmt_secs'? Creo que podría simplificar esto un poco. – jowo

+1

Intenté esto. Intenté verificarlo probando el resultado en la inversa. Algunas veces funciona, y para otros, está apagado por una hora. Supongo que es porque el DST comienza y se detiene. en diferentes fechas en las diferentes ubicaciones que estoy intentando (usando GMT, pero convirtiendo contra PST localtime). ¿Hay alguna manera de compensar eso? –

+1

Esta versión, que usa la biblioteca de tiempo de Boost POSIX, parece funcionar a pesar de las diferentes fechas de horario de verano en zonas horarias: http://stackoverflow.com/a/6849810/857029. –