mktime and tm_isdst

Dan Nelson dnelson at allantgroup.com
Fri Nov 21 11:15:31 PST 2003


I've got a question about mktime and FreeBSD's use of the tm_isdst
flag.  POSIX says:
http://www.opengroup.org/onlinepubs/007904975/functions/mktime.html

    A positive or 0 value for tm_isdst shall cause mktime() to presume
    initially that Daylight Savings Time, respectively, is or is not in
    effect for the specified time.

"presume initially" I guess is a euphamism for "implementation
defined", since it allows the implementation to override the value if
it happens to determine the correct value.

A defect reported posted for C99 asks the question:
http://std.dkuug.dk/JTC1/SC22/WG14/www/docs/dr_280.htm

Q3  In a general case, what should we do in case tm_isdst is different
    from -1?

A3  It is implementation defined. One possibility would be to consider
    any two struct tm values as being exactly one hour apart if all
    members have the same value except that one struct tm value has
    tm_isdst=1 and the other has tm_isdst=0 (regardless of the date
    stored in the struct tm values).

FreeBSD seems to ignore the value of tm_isdst except for the duplicate
fall-back hour.  Unfortunately, every other OS I've tested (Linux,
TRU64 5.1b, AIX 5.2, Solaris 9) trusts the user's tz_isdst value if
isn't not -1.  Would it be a good idea to change our behaviour to match
everyone else's, even though it's in "undefined" territory according to
the spec?

I've attached a test program to show what I'm talking about.  It
converts three dates using tm_isdst values of 0, -1, and 1, and prints
the time_t generated.

-- 
	Dan Nelson
	dnelson at allantgroup.com
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main(int argc, char *argv[])
{
	struct tm tm;
	time_t t;

	putenv("TZ=America/Chicago");

	printf("Testing 1994-10-29 01:00:00 (DST)\n");

	memset(&t, 0, sizeof(t));
	tm.tm_year = 94; tm.tm_mon = 9; tm.tm_mday = 29; tm.tm_hour = 1; tm.tm_min = 0; tm.tm_sec = 0; 
	tm.tm_isdst = 0;
	t = mktime(&tm);
	printf("isdst=0  -> %d, isdst=%d\n", t, tm.tm_isdst);

	memset(&t, 0, sizeof(t));
	tm.tm_year = 94; tm.tm_mon = 9; tm.tm_mday = 29; tm.tm_hour = 1; tm.tm_min = 0; tm.tm_sec = 0; 
	tm.tm_isdst = -1;
	t = mktime(&tm);
	printf("isdst=-1 -> %d, isdst=%d\n", t, tm.tm_isdst);

	memset(&t, 0, sizeof(t));
	tm.tm_year = 94; tm.tm_mon = 9; tm.tm_mday = 29; tm.tm_hour = 1; tm.tm_min = 0; tm.tm_sec = 0; 
	tm.tm_isdst = 1;
	t = mktime(&tm);
	printf("isdst=1  -> %d, isdst=%d\n", t, tm.tm_isdst);

	printf("Testing 1994-10-30 01:00:00 (could be either)\n");

	memset(&t, 0, sizeof(t));
	tm.tm_year = 94; tm.tm_mon = 9; tm.tm_mday = 30; tm.tm_hour = 1; tm.tm_min = 0; tm.tm_sec = 0; 
	tm.tm_isdst = 0;
	t = mktime(&tm);
	printf("isdst=0  -> %d, isdst=%d\n", t, tm.tm_isdst);

	memset(&t, 0, sizeof(t));
	tm.tm_year = 94; tm.tm_mon = 9; tm.tm_mday = 30; tm.tm_hour = 1; tm.tm_min = 0; tm.tm_sec = 0; 
	tm.tm_isdst = -1;
	t = mktime(&tm);
	printf("isdst=-1 -> %d, isdst=%d\n", t, tm.tm_isdst);

	memset(&t, 0, sizeof(t));
	tm.tm_year = 94; tm.tm_mon = 9; tm.tm_mday = 30; tm.tm_hour = 1; tm.tm_min = 0; tm.tm_sec = 0; 
	tm.tm_isdst = 1;
	t = mktime(&tm);

	printf("isdst=1  -> %d, isdst=%d\n", t, tm.tm_isdst);

	printf("Testing 1994-11-01 01:00:00 (not DST)\n");

	memset(&t, 0, sizeof(t));
	tm.tm_year = 94; tm.tm_mon = 10; tm.tm_mday = 01; tm.tm_hour = 1; tm.tm_min = 0; tm.tm_sec = 0; 
	tm.tm_isdst = 0;
	t = mktime(&tm);
	printf("isdst=0  -> %d, isdst=%d\n", t, tm.tm_isdst);

	memset(&t, 0, sizeof(t));
	tm.tm_year = 94; tm.tm_mon = 10; tm.tm_mday = 01; tm.tm_hour = 1; tm.tm_min = 0; tm.tm_sec = 0; 
	tm.tm_isdst = -1;
	t = mktime(&tm);
	printf("isdst=-1 -> %d, isdst=%d\n", t, tm.tm_isdst);

	memset(&t, 0, sizeof(t));
	tm.tm_year = 94; tm.tm_mon = 10; tm.tm_mday = 01; tm.tm_hour = 1; tm.tm_min = 0; tm.tm_sec = 0; 
	tm.tm_isdst = 1;
	t = mktime(&tm);
	printf("isdst=1  -> %d, isdst=%d\n", t, tm.tm_isdst);

	return 0;
}


More information about the freebsd-standards mailing list