c mktime est-il différent sous Windows et GNU / Linux?

le code suivant:

#include  #include  #include  #include  #include  static const char * wday_abb_names[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", }; static void mb_setenv(const char *name, const char *value) { #if !(defined _WIN32) || defined HAVE_SETENV setenv(name, value, 1); #else int len = strlen(name)+1+strlen(value)+1; char *str = malloc(len); sprintf(str, "%s=%s", name, value); putenv(str); #endif } static void mb_unsetenv(const char *name) { #if !(defined _WIN32) || defined HAVE_SETENV unsetenv(name); #else int len = strlen(name)+2; char *str = malloc(len); sprintf(str, "%s=", name); putenv(str); free(str); #endif } time_t mb_timegm(struct tm *tm) { time_t ret; char *tz; tz = getenv("TZ"); mb_setenv("TZ", ""); tzset(); ret = mktime(tm); if (tz) { mb_setenv("TZ", tz); } else { mb_unsetenv("TZ"); } tzset(); return ret; } time_t get_test_time() { struct tm msg_time; msg_time.tm_isdst = 0; msg_time.tm_wday = 4; msg_time.tm_mon = 5; msg_time.tm_mday = 16; msg_time.tm_hour = 4; msg_time.tm_min = 53; msg_time.tm_sec = 0; msg_time.tm_year = 111; //2011 - 1900 time_t retval = mb_timegm(&msg_time); printf("final msg_time = %ld\n", retval); return retval; } void print_time(const char *msg, struct tm *t) { printf("%s %s, %02d.%02d.%2d %2d:%02d\n", msg, wday_abb_names[t->tm_wday], t->tm_mday, t->tm_mon, t->tm_year, t->tm_hour, t->tm_min); } int main() { printf( "=== ENVIRON ===\n"); printf("TZ = %s\n", getenv("TZ")); time_t now; struct tm l, g; time(&now); l = *localtime(&now); g = *gmtime(&now); print_time("Local time :", &l); print_time("utc :", &g); printf("=== END ENVIRON ===\n\n"); time_t tt = get_test_time(); printf("fix test (16.6.2011 04:53) --> %s\n", ctime(&tt)); printf("done.\n"); return 0; } 

fonctionnant sous GNU / Linux, il produit:

 === ENVIRON === TZ = (null) Local time : Sat, 24.05.111 14:20 utc : Sat, 24.05.111 12:20 === END ENVIRON === final msg_time = 1308199980 fix test (16.6.2011 04:53) --> Thu Jun 16 06:53:00 2011 done. 

en cours d’exécution sur Win7, il produit:

 === ENVIRON === TZ = (null) Local time : Sat, 24.05.111 14:25 utc : Sat, 24.05.111 12:25 === END ENVIRON === final msg_time = 1308196380 fix test (16.6.2011 04:53) --> Thu Jun 16 05:53:00 2011 done. 

Les deux systèmes ont un fuseau horaire de UTC + 1, y compris DST (qui rend UTC + 2 en vigueur) et les deux systèmes ne rencontrent aucun problème de temps, sauf pour la différence affichée.

Comme vous pouvez le voir, le “msg_time final” manque exactement 3600 secondes, donc ce n’est pas un problème en temps réel.

Quelqu’un peut-il m’expliquer pourquoi mktime semble se comporter différemment sous GNU / Linux et Windows – ou comment corriger cela?

Modifier:
Les deux systèmes (après avoir appelé tzset() ) signalent tzname [0] = CET, tzname [1] = CEST, daylight = 1, fuseau horaire = -3600

Mon mb_timegm était basé sur le code indiqué dans man 3 timegm et indiquait "set the TZ environment variable to UTC" pour faire cette setenv("TZ", ""); est appelé.

Cependant, cela ne fonctionne pas sur Windows.

En utilisant setenv("TZ", "UTC"); (ou, dans le cas ci-dessus, mb_setenv) corrige le problème.

Je suppose que sur la base des informations fournies lorsque l’heure d’été est en vigueur, vous devez définir msg_time.tm_isdst dans get_test_time() sur une valeur de 1 plutôt que sur 0 . Cela peut être le problème de l’heure manquante. Soit cela, soit vous pouvez le définir sur -1 et permettre au système de tenter de déterminer si vous êtes en heure d’été ou non pour la valeur d’entrée donnée.