[tz] mktime() during the the DST gap

Christos Zoulas christos at zoulas.com
Fri Oct 14 15:28:48 UTC 2011


I am sure that this has been discussed before, but I think that if
we decide to keep the current behavior, we should document it in
the manual page explicitly.

As you probably know calling mktime() in during the DST gap with
tm_isdst == -1, returns -1 in this tzcode() implementation. The
glibc one at least, adds the difference between the non-DST and
the DST time. Both behaviors are justifyable.

	- We are returning -1 because this time cannot be represented.
	- We are returning the time you meant, since you cannot
	  easily fix it by yourself by deducing the dst offset.

I am suggesting that we explicitly document the chosen behavior in
the manual page and if we choose to return -1, we set errno which
is currently not set. I have appended a patch that changes the
behavior to return the closest time as glibc does (if we choose to
do that) as well as a test program that demonstrates that mktime()
fails and does not set errno now.

christos

-------------
#include <stdio.h>
#include <unistd.h>
#include <err.h>
#include <time.h>

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

	setenv("TZ", "America/New_York");
	memset(&tm, 0, sizeof(tm));
	tm.tm_hour = 2;
	tm.tm_min = 30;
	tm.tm_mday = 14;
	tm.tm_mon = 2;
	tm.tm_year = 110;
	tm.tm_isdst = -1; 
	t = mktime(&tm);
	if (t == -1)
		err(1, "mktime");
	printf("%s", ctime(&t));
	return 0;
}

-------------------
diff -u -r1.8 localtime.c
--- localtime.c	14 Dec 2010 19:08:54 -0000	1.8
+++ localtime.c	14 Oct 2011 15:17:58 -0000
@@ -1787,6 +1787,25 @@
 					return WRONG;
 				--hi;
 			}
+			if (lo - 1 == hi && yourtm.tm_isdst < 0) {
+				time_t off = 0;
+				for (i = sp->typecnt - 1; i >= 0; --i) {
+					for (j = sp->typecnt - 1; j >= 0; --j) {
+						if (sp->ttis[j].tt_isdst ==
+						    sp->ttis[i].tt_isdst)
+							continue;
+						off = sp->ttis[j].tt_gmtoff -
+						    sp->ttis[i].tt_gmtoff;
+						break;
+					}
+					if (j >= 0)
+						break;
+				}
+				if (off) {
+					t = hi + off;
+					break;
+				}
+			}
 			if (lo > hi)
 				return WRONG;
 			if (dir > 0)



More information about the tz mailing list