Why does glibc timezone globally disagree with system time on DST?

I am experiencing a strange problem when my system clock knows that it is summer time, but glibc does not seem to be so. This is a modern Ubuntu installation, and I checked / etc / localtime, and it has the correct switch time to switch to DST last week.

The current correct time zone for me is Pacific Daylight Time (UTC-7). When I ask my system in which time zone I enter, it tells me correctly:

$ date +%z -0700 

But when I run the following program:

 #include <time.h> #include <stdio.h> int main() { tzset(); printf("%lu\n", timezone); return 0; } 

The result is incorrect:

 28800 

Which corresponds to UTC-8, or Pacific Standard Time. (And no, TZ is not installed in my environment)

I thought that glibc and the date program would get timezone information from the same source, but apparently they either don’t do it, or I don’t understand how the glibc global timezone works.

Main questions:

  • Why are these two outputs different from each other?
  • How can I reliably determine the offset of a UTC system from program C?
+6
c timezone glibc
source share
4 answers

I do not think that the "time zone" changes with daytime. Try the daylight variable. In my system:

  The external variable timezone contains the difference, in seconds,
       between UTC and local standard time (for example, in the US 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.
+3
source share

Look at the tm.tm_isdst field after this:

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

According to the localtime_r (3) man page, this really indicates whether the DST is valid at the specified time. I think you then need to assume that DST adds one hour to the timezone (3) variable that you are already using, or apply the trick against GMT.

Works for me in Australian AEST, hope this works for you.

+1
source share

Here is my code for this using tm_gmtoff if linux is defined and uses gettimofday timezone.tz_minuteswest otherwise (here 'ltm' is the result of local time):

 { 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); } 
0
source share

You can use tm_gmtoff member struct tm, which is the same as :: timezone, but it takes into account DST and the character is canceled.

http://www.gnu.org/s/libc/manual/html_node/Time-Zone-Functions.html#Time-Zone-Functions

-one
source share

All Articles