mirror of
https://frontier.innolan.net/rainlance/amiga-tz.git
synced 2026-03-21 08:14:16 +00:00
mktime: guess better near transitions where tm_isdst does not change
* localtime.c (SMALLEST): New macro. (time2sub) [TM_GMTOFF && !UNINIT_TRAP]: If the UTC offset doesn't match the request, try the requested offset. This catches a problem caught by -DTYPECHECK with a time stamp near a transition from LMT to standard time, where both sides of the transition have tm_isdst == 0. If !defined TM_GMTOFF || UNINIT_TRAP you're out of luck: mktime will still conform to its spec but it'll be more likely to guess wrong on these ambiguous inputs. * private.h (UNINIT_TRAP): New macro that defaults to 0. * Makefile, NEWS: Document this.
This commit is contained in:
2
Makefile
2
Makefile
@ -134,6 +134,8 @@ LDLIBS=
|
||||
# the default is system-supplied, typically "/usr/lib/locale"
|
||||
# -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified
|
||||
# DST transitions if the time zone files cannot be accessed
|
||||
# -DUNINIT_TRAP=1 if reading uninitialized storage can cause problems
|
||||
# other than simply getting garbage data
|
||||
# -DZIC_MAX_ABBR_LEN_WO_WARN=3
|
||||
# (or some other number) to set the maximum time zone abbreviation length
|
||||
# that zic will accept without a warning (the default is 6)
|
||||
|
||||
8
NEWS
8
NEWS
@ -59,6 +59,14 @@ Unreleased, experimental changes
|
||||
already defined, to make it easier to configure on common platforms.
|
||||
Define NO_TM_GMTOFF and NO_TM_ZONE to suppress this.
|
||||
|
||||
Unless the new macro UNINIT_TRAP is defined to 0, the tz code now
|
||||
assumes that reading uninitialized memory yields garbage values
|
||||
but does not cause other problems such as traps.
|
||||
|
||||
If TM_GMTOFF is defined and UNINIT_TRAP is not 0, mktime is now
|
||||
more likely to guess right for ambiguous time stamps near
|
||||
transitions where tm_isdst does not change.
|
||||
|
||||
tzselect -c now uses a hybrid distance measure that works better
|
||||
in Africa. (Thanks to Alan Barrett for noting the problem.)
|
||||
|
||||
|
||||
30
localtime.c
30
localtime.c
@ -103,6 +103,7 @@ struct lsinfo { /* leap second information */
|
||||
int_fast64_t ls_corr; /* correction to apply */
|
||||
};
|
||||
|
||||
#define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#ifdef TZNAME_MAX
|
||||
@ -1817,6 +1818,35 @@ time2sub(struct tm *const tmp,
|
||||
else lo = t;
|
||||
continue;
|
||||
}
|
||||
#if defined TM_GMTOFF && ! UNINIT_TRAP
|
||||
if (mytm.TM_GMTOFF != yourtm.TM_GMTOFF
|
||||
&& (yourtm.TM_GMTOFF < 0
|
||||
? (-SECSPERDAY <= yourtm.TM_GMTOFF
|
||||
&& (mytm.TM_GMTOFF <=
|
||||
(SMALLEST (INT_FAST32_MAX, LONG_MAX)
|
||||
+ yourtm.TM_GMTOFF)))
|
||||
: (yourtm.TM_GMTOFF <= SECSPERDAY
|
||||
&& ((BIGGEST (INT_FAST32_MIN, LONG_MIN)
|
||||
+ yourtm.TM_GMTOFF)
|
||||
<= mytm.TM_GMTOFF)))) {
|
||||
/* MYTM matches YOURTM except with the wrong UTC offset.
|
||||
YOURTM.TM_GMTOFF is plausible, so try it instead.
|
||||
It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
|
||||
since the guess gets checked. */
|
||||
time_t altt = t;
|
||||
int_fast32_t diff = mytm.TM_GMTOFF - yourtm.TM_GMTOFF;
|
||||
if (!increment_overflow_time(&altt, diff)) {
|
||||
struct tm alttm;
|
||||
if (funcp(&altt, offset, &alttm)
|
||||
&& alttm.tm_isdst == mytm.tm_isdst
|
||||
&& alttm.TM_GMTOFF == yourtm.TM_GMTOFF
|
||||
&& tmcomp(&alttm, &yourtm) == 0) {
|
||||
t = altt;
|
||||
mytm = alttm;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
|
||||
break;
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user