Subject: Re: mktime(3) fails to convert a time in the "spring forward gap"
To: NetBSD Userlevel Technical Discussion List <tech-userlevel@netbsd.org>
From: Greg A. Woods <woods@weird.com>
List: tech-userlevel
Date: 10/15/2002 22:15:15
[ On Wednesday, October 16, 2002 at 01:40:55 (+0200), der Mouse wrote: ]
> Subject: Re: mktime(3) fails to convert a time in the "spring forward gap"
>
> >> But how could something HAVE those times as local time-of-day on
> >> those dates?
> > It doesn't have them -- it tries to create them by doing arithmetic
> > on the struct tm fields to try and calculate wall-clock time for some
> > offset from some other time which it does "have".
> 
> Any program which works this way *must* be prepared to encounter
> nonexistent times - or else be prepared to fall over when used in
> timezones and at times such that nonexistent times can occur.

Ah yes, that's indeed what we're arguing about.  The GNU Autoconf test
which raised this issue, Paul Eggert, all those who approved of his fix
to his mktime() implementation (including myself), and most importantly
perhaps the key reference implementation of mktime(), do not agree with
such a limitation and we all consider its existance to be an
implementation bug.

> That's not pretty, but it's a fact that's approximately inescapable
> given how the world's current timekeeping systems work.

It's not only not pretty, it's impossible to recover from such a
mktime() failure in any sane way given that the timezone rules are
currently hidden internally in the implementation of mktime() et al.
That's why mktime() must gracefully give as sane an answer as it can so
long as the values it has been fed are all within the appropriate ranges
and limits for their respective fields.

> if you want "the same hh:mm next
> day", you have to decide what you want to have happen if "next day" has
> other than exactly one "the same hh:mm" (none, in a spring-forward gap;
> two, in a fall-back overlap), and then implement that.

Yes, that's often what's wanted.  Unfortunately such an implementation
is impossible outside of mktime() itself given the currently available
standard APIs.  The information necessary to make such decisions is
necessarily hidden from the applications programmer.

> > They're not broken in non-DST timezones.
> 
> This is like writing code that assumes a month has >=30 days and then
> protesting "it's not broken in non-February months". 

No, it's not at all.  Your analogy is false and misleading.  DST rules
are locally-specific political meanderings that still come and go at
almost any local whim while most of the world (indeed I believe all of
the so-called "Western World") have lived with the current rules giving
the number of days in a month for much longer than digital computers
have ever existed on this planet.  I.e. the number of days in a month
does not change no matter where you are the planet, or what time of day
it is.  Only the length of one month changes on certain years, and the
rules for that change are also very well defined and universal.

However read on below about how some (all?) the mktime() implementations
I've known treat these rules.

> DST-using
> timezones _do_ occur, just as do Februarys, however inconvenient they
> may be for application authors.

Indeed -- the problem is that the DST rules are _necessarily_ hidden
from the applications programmer so cannot be used to recover from the
error you would have them be faced with.

One might even go so far as to argue that some values like these:

        tm.tm_year = 98;
        tm.tm_mon = 1;
        tm.tm_mday = 31;
        tm.tm_hour = 10;
        tm.tm_min = 10;
        tm.tm_sec = 30;

should be converted without error to a time (if converted to text in the
C locale by ctime(3)) of "Tue Mar  3 10:10:30 1998".  Indeed that's
exactly how the one key reference implementation of mktime() works.
Even the NetBSD implementation does as I show.  I think I would agree
the rationale for doing so has much less sway than that for handling
times in DST gaps, but there it is none the less, and if anything the
fact that this works in some (all?) known implementations only bolsters
the rationale for not allowing failures in the spring-forward gap.

-- 
								Greg A. Woods

+1 416 218-0098;            <g.a.woods@ieee.org>;           <woods@robohack.ca>
Planix, Inc. <woods@planix.com>; VE3TCP; Secrets of the Weird <woods@weird.com>