2009-11-19 32 views
5

que tienen una cadena que contiene una fecha/hora local y tengo que convertirlo en un valor time_t (en UTC) - He estado tratando de esto:conversión de cadena que contiene hora local en UTC en C

char* date = "2009/09/01/00"; 
struct tm cal = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL}; 
strptime(date, "%Y/%m/%d/%H", &cal); 
time_t t = mktime(&cal); 

pero el valor time_t que obtengo es el valor que esperaría si la cadena se analizara como UTC, no la hora local. Tal vez no entendí lo que se supone que debe hacer strptime, pero en mi zona horaria (Reino Unido) el 1 de septiembre estamos usando BST (es decir, UTC + 1 hora), así que esperaría que el valor final sea de 1 hora por delante de UTC .

¿Hay alguna manera de interpretar la cadena como localtime, teniendo en cuenta automáticamente el desplazamiento UTC que habría estado en vigencia en esa fecha? Tenga en cuenta que necesito el valor time_t no una struct tm, en el ejemplo anterior quiero que el valor time_t corresponda a 2009-09-01 01:00:00 GMT

Respuesta

0

Creo que he agrietado que ahora, gracias a Andomar - este código hace lo que necesito y parece funcionar independientemente del estado actual del horario de verano (he cambiado el reloj de mi PC para comprobar esto):

#include <time.h> 
#include <assert.h> 

time_t parseLocalDate(char* date){ 
    struct tm cal = {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, NULL}; 
    strptime(date, "%Y/%m/%d/%H", &cal); 
    return mktime(&cal); 
} 

int main(int argc, char *argv[]){ 
// DST is effect, Local Time = GMT+1 
    assert(1251759600 == parseLocalDate("2009/09/01/00")); // Mon, 31 Aug 2009 23:00:00 GMT 
    assert(1254351600 == parseLocalDate("2009/10/01/00")); // Wed, 30 Sep 2009 23:00:00 GMT 
// DST not in effect, Local Time = GMT 
    assert(1257033600 == parseLocalDate("2009/11/01/00")); // Sun, 01 Nov 2009 00:00:00 GMT 
} 
5

Puede usar mktime para interpretar una struct tm en zona horaria local Cuando lo haga, tenga cuidado de configurar el indicador tm_isdst. Es 0 para el verano, 1 para el invierno, y para -1 para tener mktime descifrarlo. Aquí hay un código de ejemplo:

void main() 
{ 
    char* date = "2009/09/01/00"; 
    struct tm cal = {}; 
    // Read string into struct tm 
    strptime(date, "%Y/%m/%d/%H", &cal); 
    // Tell mktime to figure out the daylight saving time 
    cal.tm_isdst = -1; 
    printf("%20s: %s", "Before mktime", asctime(&cal)); 
    // Convert struct tm to time_t 
    time_t t = mktime(&cal); 
    // Convert time_t to localtime 
    struct tm localcal = *localtime(&t); 
    printf("%20s: %s", "Local time", asctime(&localcal)); 
    printf("%20s: %i\n", "Local DST", localcal.tm_isdst); 
    // Convert time_t to GMT 
    struct tm gmcal = *gmtime(&t); 
    printf("%20s: %s", "GM time", asctime(&gmcal)); 
    printf("%20s: %i\n", "GM DST", gmcal.tm_isdst); 
} 

Esta impresora (vivo en GMT + 1, y es invierno ahora):

Before mktime: Tue Sep 1 00:00:00 2009 
     Local time: Tue Sep 1 00:00:00 2009 
     Local DST: 1 
     GM time: Mon Aug 31 22:00:00 2009 
      GM DST: 0 

Parece que mktime convierte una fecha en septiembre sobre la base de los cambios de horario actuales hora. Es noviembre ahora, así que en realidad es una hora de descanso. No he encontrado una manera de corregir eso.

+0

gracias, pero su valor time_t que me interesa - si hago un mktime() en el 'localcal' struct en tu código me da el mismo resultado que hacer mktime() en ' California'. Necesito alguna manera de producir un valor time_t equivalente a '2009-09-01 01:00 GMT' – codebox

+1

La convención C es almacenar time_t como el número de segundos desde 1970-01-01 en UTC. Lo ha cambiado a localtime solo para interpretación o visualización. Si desea introducir rob_t como la variante de tiempo local, puede calcular el número de segundos entre gmtime() y localtime() y agregarlo a su time_t. :) – Andomar

+0

bien, pero quiero interpretar la cadena como hora local, no producir un equivalente de hora local de una cadena de tiempo UTC. En nuestro ejemplo, suponiendo que vivamos en GMT + 1, la cadena "2009/09/01/00" es nuestra hora local, por lo que es equivalente a "2009/09/01/01" en GMT, por lo que el el código debe devolver el valor time_t correspondiente a "2009/09/01/01". ¿Tiene sentido? – codebox

0

Aquí está mi versión, usando tm_gmtoff. Con suerte, la biblioteca se encarga de horario de verano ...

#define _BSD_SOURCE 
#define _XOPEN_SOURCE 
#include <stdio.h> 
#include <time.h> 

int gmtoffset(void) { 
    struct tm *dummy; 
    time_t t = 0; 
    dummy = localtime(&t); 
    return dummy->tm_gmtoff; /* _BSD_SOURCE */ 
} 

int main(void) { 
    int off; 
    const char *date = "2009/09/01/00"; 
    struct tm cal = {0}; 
    time_t t; 

    off = gmtoffset(); 

    strptime(date, "%Y/%m/%d/%H", &cal); /* _XOPEN_SOURCE */ 
    t = mktime(&cal); 
    printf("t  --> %s", ctime(&t)); /* ctime includes a final '\n' */ 
    t -= off; 
    printf("t-off --> %s", ctime(&t)); 
    return 0; 
} 
 
$ /usr/bin/gcc ptime.c 
 
$ ./a.out 
t  --> Tue Sep 1 01:00:00 2009 
t-off --> Tue Sep 1 00:00:00 2009 
+0

La 'struct tm' que pasa a' mktime' tiene 'tm_isdst' establecido en 0, por lo que la hora se lee sin DST. Luego lo pasa a 'ctime', que se corrige para el horario de verano agregando 1 hora. Luego, resta la compensación, que también es confusamente de 1 hora, para obtener un tiempo aleatorio. Esto me da vueltas pero me gustaría llegar al fondo :) – Andomar

+0

Este horario de verano es un negocio divertido.¡Me acabo de dar cuenta de que el horario de verano no está vigente actualmente, pero fue el 1 de septiembre! Hmmm ... supongo que no hay forma de que la biblioteca "sepa" cuando el horario de verano comience y termine en un lugar específico. Creo que debes administrar el horario de verano a mano (http://timeanddate.com/time/dst2009.html) – pmg

Cuestiones relacionadas