2009-08-01 7 views
4

Après avoir écrit un exemple de code pour la question sur converting between timezones, l'un des commentaires était la nécessité d'une méthode plus générale pour la conversion du fuseau horaire A au fuseau horaire B. J'étais curieux moi aussi d'avoir des primitives de plus haut niveau pour une telle des manipulations, donc j'ai écrit le code ci-dessous. Un inconvénient que je vois est qu'il remue constamment le TZ dans les variables d'environnement, en changeant la notion de 'temps local'. Bien que cela semble fonctionner (bien que je ne vérifie pas comment elle réagit aux périodes d'heure d'été, mais comme il est basé sur la base de données Olson, probablement), j'étais curieux de savoir si quelqu'un pouvait avoir de meilleures idées sur la façon de traiter tâche ?Manière générale de manipuler les temps (entre les fuseaux horaires) en C?

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <sys/time.h> 

time_t utc_now() { 
    struct timeval tv_utc; 
    gettimeofday(&tv_utc, NULL); 
    return tv_utc.tv_sec; 
} 

void use_tz(char *timezone) { 
    if(timezone) { 
    setenv("TZ", timezone, 1); 
    } else { 
    unsetenv("TZ"); 
    } 
    tzset(); 
} 

time_t utc_from_local_tm(struct tm *local_tm, char *timezone) { 
    time_t utc; 
    use_tz(timezone); 
    utc = mktime(local_tm); 
    return utc; 
} 

struct tm *local_tm_from_utc(time_t utc, char *timezone) { 
    use_tz(timezone); 
    return localtime(&utc); 
} 

int main(int argc, char *argv[]) { 
    struct tm *tm; 
    struct tm tm2; 
    time_t utc, utc2, utc3; 
    utc = utc_now(); 
    tm = local_tm_from_utc(utc, "Europe/Brussels"); 
    printf("Local time in Brussels now: %s", asctime(tm)); 
    utc2 = utc_from_local_tm(tm, "Europe/Moscow"); 
    tm = local_tm_from_utc(utc2, "UTC"); 
    printf("UTC time if the above was the Moscow local time: %s", asctime(tm)); 

    memset(&tm2, sizeof(tm2), 0); 
    /* 13:00:00 on 11 dec 2010 */ 
    tm2.tm_sec = tm2.tm_min = 0; 
    tm2.tm_hour = 13; 
    tm2.tm_mon = 11; 
    tm2.tm_mday = 11; 
    tm2.tm_year = 110; 


    utc3 = utc_from_local_tm(&tm2, "Europe/Brussels"); 
    printf("Brussels time: %s", asctime(&tm2)); 
    tm = local_tm_from_utc(utc3, "Europe/Moscow"); 
    printf("At 13:00:00 on 11 dec 2010 CET the time in Moscow will be: %s", asctime(tm)); 

    exit(0); 
} 

Répondre

1

Si le stockage des informations TZ dans une variable d'environnement bogues vous, que diriez-vous de créer une nouvelle structure qui contient à la fois tm struct ainsi qu'un char * pour les informations TZ?

Je suis gâtée parce R fait ces choses très bien:

R> now <- Sys.time() 
R> now 
[1] "2009-08-01 17:19:07 CDT" 
R> format(now, tz="Europe/Brussels") 
[1] "2009-08-02 00:19:07" 
R> 

Il a quelques d'extension/de remplacement aux fonctions POSIX standard, consultez le fichier R-2.9.1/src/main/datetime. c (où R-2.9.1 est la version actuelle)

+0

Ah, intéressant. Je vais jeter un coup d'oeil aux sources R - j'ai entendu parler de R mais je ne l'ai pas encore regardé. Merci! +1 :) Le sentiment de démangeaison était principalement parce qu'il y aurait potentiellement d'autres threads - donc mon code naïf pourrait se comporter comme un buggy dans l'environnement multithread. –

+0

Enfin eu le temps de le regarder - génial. Merci pour la référence, il répond vraiment à la question. –

+0

Un exemple de code serait une belle contribution. Pouvez-vous coller comment vous l'avez fait pour gagner du temps sur d'autres personnes qui sont intéressées. Je serais reconnaissant. – NickSoft

Questions connexes