Re: mktime problems when adjusting tm_isdst
We could run through the transition times from future to past (rather than from past to future as is done now); this doesn't solve the deep problem, but does get the "TZ=Europe/Paris 1996-01-01 00:00:00 tm_isdt=1" case right. It does have the advantage of being a fairly minimal change to the code. --ado *************** *** 1458,1467 **** if (sp == NULL) return WRONG; #endif /* defined ALL_STATE */ ! for (samei = 0; samei < sp->typecnt; ++samei) { if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) continue; ! for (otheri = 0; otheri < sp->typecnt; ++otheri) { if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) continue; tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - --- 1458,1467 ---- if (sp == NULL) return WRONG; #endif /* defined ALL_STATE */ ! for (samei = sp->typecnt - 1; samei >= 0; --samei) { if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) continue; ! for (otheri = sp->typecnt - 1; otheri >= 0; --otheri) { if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) continue; tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
I doubt that any patch can reasonably help here, the tm_isdst flag as input to mktime() is simply absurdly badly broken as defined. In anything other than the simplest cases, there is no rational way to make it work as defined, it would probably be better for mktime() to either simply ignore it (not great), or return an error ((time_t)-1) or ((time_t)0) if tm_isdst is set to the "wrong" value. The only reason this brain damage exists at all is because of the silly desire to make arithmetic on times be done by doing arithmetic on the fields of a struct tm. OK, it is not a good idea to assume that a time_t is always an arithmetic type, but a bunch of macro/function definitions for addition/subtraction of time_t's from each other, and integers to/from time_t's would have been a much more rational choice, and much easier to use. Its all great that one should attempt to support the standardised interfaces, however brain dead they actually are, but having attempted that, and discovered that there is simply no way to implement it correctly, there comes a time when the right answer is simply to abandon the attempt, and not continue to pretend that it can be done, and rely on people not finding the hard cases where it can't. The case where tm_isdst == 1, and summer time is not actually in effect, is basically asking mktime() to invent policy. The request to it is "If daylight saving had been in effect at this time I am telling you, the time would have been this. So, what is it really?" This is meaningless, it requires knowledge as to what the non-existant daylight time shift would have been, had it existed. One can invent any offset at all for that, for all anyone knows for sure, the answer Paul originally sent for the conversion that "went wrong" might be perfectly correct. Note however that the other way (tm_isdst == 0) can be handled, as that is saying "this time is standard time for the zone, correct it for any DST that might have been in effect", and as long as the time is one in the past, or very near future, it is possible (times in the far future, where far is anything beyond about 3 months, are always going to be impossible). If any patch is needed, simply make it be an error - or if you want to allow a little more latitude, you may be willing to assume that when the nearest DST before the time involved, and the nearest after the time involved are the same, then it is acceptable to assume that the same offset is what would have applied in the gap between, had there been DST then, and only return the error in cases where the offset was not the same in the two cases. kre
participants (2)
-
ado -
Robert Elz