2009-03-11 3 views
6

Sto vivendo un bizzarro problema in cui il mio orologio di sistema sa che è l'ora legale, ma sembra che glibc non lo faccia. Questa è un'installazione di Ubuntu aggiornata, e ho controllato/etc/localtime e ha il tempo di passaggio corretto per il passaggio alla DST della scorsa settimana.Perché il "fuso orario" di glibc non è d'accordo con l'ora del sistema su DST?

L'ora corrente corretta per me è Pacific Daylight Time (UTC-7). Quando chiedo il mio sistema quello fuso orario mi trovo, mi dice correttamente:

$ date +%z 
-0700 

Ma quando ho eseguito il seguente programma:

#include <time.h> 
#include <stdio.h> 

int main() { 
    tzset(); 
    printf("%lu\n", timezone); 
    return 0; 
} 

L'uscita è, in modo non corretto:

28800 

Che corrisponde a UTC-8 o all'ora solare del Pacifico. (E no, TZ non è impostato nel mio ambiente)

Ho pensato che glibc e il programma di data avrebbero ottenuto le informazioni sul fuso orario dalla stessa sorgente, ma a quanto pare non lo fanno o sto fraintendendo il fuso orario di glibc opere globali.

Le domande fondamentali sono quindi:

  1. Perché questi due uscite differenti
  2. Come posso affidabile rilevare l'offset da un programma C UTC sistema?

risposta

3

Non credo che il "fuso orario" cambi con l'ora legale. Prova la variabile "daylight". Sul mio sistema:

 
     The external variable timezone contains the difference, in seconds, 
     between UTC and local standard time (for example, in the U.S. Eastern 
     time zone (EST), timezone is 5*60*60). The external variable daylight 
     is non-zero only if a summer time zone adjustment is specified in the 
     TZ environment variable. 
+0

La mia lettura della pagina di manuale per tzset indica che la variabile diurna indica solo se la zona locale utilizza l'ora legale a un certo punto e non indica necessariamente se è attualmente in vigore. –

+0

Penso di essere d'accordo con te. Suggerirei {time_t t = time (NULL); printf ("% d \ n", (int) difftime (mktime (gmtime (& t)), t)); } ma questo mi dà lo stesso risultato di "timezone". –

1

sguardo al campo tm.tm_isdst dopo aver fatto questo:

time_t current_time; 
    struct tm tm; 

    current_time = time(NULL); 
    localtime_r(&current_time, &tm); 

Secondo il localtime_r (3) pagina di manuale, questa realtà non indica se l'ora legale è in vigore al momento specificato . Penso che tu debba quindi supporre che l'ora legale aggiunga un'ora alla variabile del fuso orario (3) che stai già utilizzando, o che faccia il trucco del diff contro GMT.

Lavora per me in AEST australiano, spero che funzioni per voi.

0

Ecco il mio codice per questo utilizzo tm_gmtoff se linux è definita, e l'utilizzo di timezone.tz_minuteswest da gettimofday altrimenti (qui 'LTM' è l'uscita di localtime):

{ 
    int tz_offset; 

#if defined(__linux__) 
    tz_offset= ltm.tm_gmtoff; 
#else 
    tz_offset= -tz.tz_minuteswest*60 + ltm.tm_isdst*3600; 
#endif 

    printf ("LT = UTC +d sec\n", tz_offset); 
}