Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tzset and daylight global variable interpretation in time.h

Tags:

c

timezone

dst

In the time.h header for the daylight global variable it says: "This variable has a nonzero value if Daylight Saving Time rules apply. A nonzero value does not necessarily mean that Daylight Saving Time is now in effect; it means only that Daylight Saving Time is sometimes in effect."

Now I've noticed that in both Solaris 11.2 and Linux the "daylight" variable is being set to 1, even though my time-zone does not use daylight savings at all (Australia/Brisbane).

Sample code confirms this, if I run tzset and output the global variables we get: daylight = 1 tz[0] = [AEST] tz[1] = [AEDT] timezone = [-36000]

But by my understanding, daylight should be set to 0 since my zone does not have daylight savings at any time during the year.

I also noticed that the struct tm when set to current time returns a tm_isdst = 0, which is correct.

So why is the daylight variable set to 1? Shouldn't it be set to 0? Or am I misinterpreting this?

Code is:

#include <stdio.h>
#include <time.h>
void main()
{
  time_t t;
  struct tm     *tms = { 0 };
  tzset();
  time(&t);
  tms = localtime(&t);
  printf("date and time : %s",ctime(&t));
  printf("daylight = %d tz[0] = [%s] tz[1] = [%s] timezone = [%ld]\n", daylight, tzname[0], tzname[1], timezone);
  printf("tm_isdst = %d\n",tms->tm_isdst);
}

Output is:

date and time : Mon Nov 30 16:41:01 2015
daylight = 1 tz[0] = [AEST] tz[1] = [AEDT] timezone = [-36000]
tm_isdst = 0
like image 433
Andrew G Avatar asked Nov 30 '15 06:11

Andrew G


People also ask

What does tzset do?

The tzset() function uses the value of the environment variable TZ to set time conversion information used by ctime(), localtime(), mktime(), and strftime(). If TZ is absent from the environment, or it is incorrect, time-conversion information is obtained from the LC_TOD locale category.

What is Tm_isdst in C?

Setting tm_isdst to - 1 tells the mktime() function to determine whether daylight savings time applies.


2 Answers

About the C Standard tm_isdst member.

The value of tm_isdst is positive if Daylight Saving Time is in effect, zero if Daylight Saving Time is not in effect, and negative if the information is not available. C11dr §7.27.1 4

This slightly differs from *nix specification about the *nix global variable daylight.
daylight is not part of standard C.


gnu.org reports

Variable: int daylight
This variable has a nonzero value if Daylight Saving Time rules apply. A nonzero value does not necessarily mean that Daylight Saving Time is now in effect; it means only that Daylight Saving Time is sometimes in effect.


The tm_isdst refers to the struct tm timestamp. It only means DST is in effect for that time-stamp.

daylight != 0 implies DST is used sometimes in the timezone's timestamps.

As Australia/Brisbane once observed DST prior (@Jon Skeet) to 1972, having daylight == 1 is reasonable as daylight implies DST was in effect for some periods of time for that timezone (likely since 1970).

OP's "... even though my time-zone does not use daylight savings at all" is not correct.


The following code shows that DST is used (at least the timezone DB thinks so) for some years since 1970 in "Australia/Brisbane".

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

int main(void) {
  setenv("TZ", "Australia/Brisbane", 1);
  tzset();
  time_t now;
  time(&now);
  struct tm tm;
  int isdst = 42; // See Hitchhiker's_Guide_to_the_Galaxy
  time_t t;
  for (t = 0; t < now; t += 3600) {
    tm = *localtime(&t);
    if (tm.tm_isdst != isdst) {
      printf("dst:%d %s", tm.tm_isdst, ctime(&t));
      isdst = tm.tm_isdst;
    }
  }
  printf("dst:%d %s", tm.tm_isdst, ctime(&t));
  return 0;
}

Output

dst:0 Thu Jan  1 10:00:00 1970
dst:1 Sun Oct 31 03:00:00 1971
dst:0 Sun Feb 27 02:00:00 1972
dst:1 Sun Oct 29 03:00:00 1989
dst:0 Sun Mar  4 02:00:00 1990
dst:1 Sun Oct 28 03:00:00 1990
dst:0 Sun Mar  3 02:00:00 1991
dst:1 Sun Oct 27 03:00:00 1991
dst:0 Sun Mar  1 02:00:00 1992
dst:0 Tue Dec  1 16:00:00 2015
like image 60
chux - Reinstate Monica Avatar answered Sep 28 '22 05:09

chux - Reinstate Monica


Australia/Brisbane doesn't use daylight saving time at the moment, but it has in the past; look at the australasia file you'll see the few years where it has observed DST.

My interpretation of daylight is that it indicates whether that time zone has ever observed (or will ever obseve with the current rules) daylight savings. In other words, if this is 1 you need to be careful when performing date/time handling, whereas if it's 0 you can assume a constant UTC offset.

(It's not immediately clear to me whether a time zone which has never observed DST, but has shifted its standard UTC offset over time, would set daylight to 1 or not. I guess it would be strictly wrong to set it, but it would be practical to do so for the reasons above...)

like image 27
Jon Skeet Avatar answered Sep 28 '22 07:09

Jon Skeet