[tz] question about mktime_tzname()

Arthur David Olson arthurdavidolson at gmail.com
Wed Jan 11 19:39:48 UTC 2017


So it looks as if this has nothing to do with non-normalized values and,
actually, nothing to do with mktime but everything with to do with how the
TZ variable is being handled. At the bottom of this message there's output
from "zdump."
It shows that, for TZ=EST5EDT,M4.1.0/02:00,M10.5.0/02:00, the first
detectable transition is on 1970-10-25, from EDT to EST; that means that
daylight saving is applied to all instants before 1970-10-25, leading to
the reported results.

The small fix is to ensure that a transition to DST shows up in the table
that's generated at run time when the given TZ environment variable is used.

The philosophical question: for such environment variables, in what year
should application of daylight saving start (or should it apply to all
years, no matter how far in the past)?

    @dashdashado

Script started on Wed, Jan 11, 2017  2:24:59 PM
$ zdump -v EST5EDT,M4.1.0/02:00,M10.5.0/02:00 | head
EST5EDT,M4.1.0/02:00,M10.5.0/02:00  -9223372036854775808 = NULL
EST5EDT,M4.1.0/02:00,M10.5.0/02:00  -9223372036854689408 = NULL
EST5EDT,M4.1.0/02:00,M10.5.0/02:00  Sun Oct 25 05:59:59 1970 UT = Sun Oct
25 01:59:59 1970 EDT isdst=1 gmtoff=-14400
EST5EDT,M4.1.0/02:00,M10.5.0/02:00  Sun Oct 25 06:00:00 1970 UT = Sun Oct
25 01:00:00 1970 EST isdst=0 gmtoff=-18000
EST5EDT,M4.1.0/02:00,M10.5.0/02:00  Sun Apr  4 06:59:59 1971 UT = Sun Apr
4 01:59:59 1971 EST isdst=0 gmtoff=-18000
EST5EDT,M4.1.0/02:00,M10.5.0/02:00  Sun Apr  4 07:00:00 1971 UT = Sun Apr
4 03:00:00 1971 EDT isdst=1 gmtoff=-14400
EST5EDT,M4.1.0/02:00,M10.5.0/02:00  Sun Oct 31 05:59:59 1971 UT = Sun Oct
31 01:59:59 1971 EDT isdst=1 gmtoff=-14400
EST5EDT,M4.1.0/02:00,M10.5.0/02:00  Sun Oct 31 06:00:00 1971 UT = Sun Oct
31 01:00:00 1971 EST isdst=0 gmtoff=-18000
EST5EDT,M4.1.0/02:00,M10.5.0/02:00  Sun Apr  2 06:59:59 1972 UT = Sun Apr
2 01:59:59 1972 EST isdst=0 gmtoff=-18000
EST5EDT,M4.1.0/02:00,M10.5.0/02:00  Sun Apr  2 07:00:00 1972 UT = Sun Apr
2 03:00:00 1972 EDT isdst=1 gmtoff=-14400
$ exit
exit

Script done on Wed, Jan 11, 2017  2:25:31 PM

On Wed, Jan 11, 2017 at 11:27 AM, Kees Dekker <Kees.Dekker at infor.com> wrote:

> Hi,
>
>
>
> Can anyone help me?
>
>
>
> In short, I set TZ to EST5EDT,M4.1.0/02:00,M10.5.0/02:00, which means
> daylight saving for EST (=GMT-5 or GMT-4 if DST is active), with switching
> DST at first Sunday of April and move to standard time at the last Sunday
> of October.
>
>
>
> The input to mktime is (See also attached source code) 1-1-1970, 19:00h
> (tm_min=1140 = 1140/60 = 19h) local EST time and tm_isdst set to -1.
> Because of this value, the tz code should figure out that 1-1-1970 is not
> in DST so the time difference with GMT/UTC is 5 hours. I would exect then
> mktime() to return 0. This is true if I use the system functions, but
> mktime() returns -3600 when using the tz library.
>
>
>
> The output of running the test case with system libraries is:
>
> ./tztestcase
>
> enter mktime with: 1970/Jan/00 00:1140:00, week day: -858993460, year day:
> -858993460, dst: -1
>
> the return value of mktime is: 0
>
> normalized times: 1969/Dec/31 19:00:00, week day: Wed, year day: 364, dst:
> 0
>
>
>
> The output of the test case with the tz lib is:
>
> ./tztestcase2016j
>
> enter mktime with: 1970/Jan/00 00:1140:00, week day: -858993460, year day:
> -858993460, dst: -1
>
> the return value of mktime is: -3600
>
> normalized times: 1969/Dec/31 19:00:00, week day: Wed, year day: 364, dst:
> 1
>
>
>
> Please correct me if I’m wrong. Is this a bug in the tz code? Please note
> the differences.
>
>
>
> *From:* Kees Dekker
> *Sent:* Thursday, January 05, 2017 15:03
> *To:* 'tz at iana.org' <tz at iana.org>
> *Subject:* question about mktime_tzname()
>
>
>
> Hi,
>
>
>
> I’m running into a potential bug. Please also see the attached C-source
> file for a reproduction.
>
>
>
> Reproduction steps:
>
> 1.       Build tz code, in such way that a libtz.a exists
>
> 2.       Compile attached source with (e.g. on Linux): gcc -g -o
> tztestcase2016j tztestcase.c -L <tzlibdir> -ltz
>
> 3.       Checking the same test case source code with a system library
> (instead of IANA libtz.a) can be achieved by omitting -L and -l flags in
> previous command (see #2).
>
>
>
> It does not make much sense which version of tzcode is used, I tried 2013i
> and 2016j and both show the same behavior.
>
>
>
> The mktime() code returns -3600, while I expect 0. Because the TZ zone is
> explicitly specified, EST5EDT is GMT-5. So the provided time stamp
> (31-Jan-1969, 19:00) is exactly the same as UTC value 0 (1-Jan-1970, 00:00
> GMT). Both Linux and Windows with system libraries return 0 in this
> specific case (I used these for reference).
>
>
>
> The remainder of this email is based on the tzcode2016j source code (e.g.
> for used line numbers).
>
>
>
> The provided TZ value is parsed in tzparse() and results in sp->ttis[0]
> set as DST value, and sp->ttis[1] as standard time value. This is at least
> contrary to in the else part of the if (*name == ',' || *name == ';') block
> (there DST is saved in sp->ttis[1]). Just grep on init_ttinfo() calls in
> localtime.c. However, in localsub(), around line 1428, the i becomes
> sp->defaulttype (which is zero), i.e. points to the DST value of
> sp->ttis[], which is assigned to ttisp. As result, because t is below
> sp->ats[0], DST takes into effect, which is incorrect, as everything after
> the last Sunday in October and before the first Sunday in April (see
> attachment, TZ=”EST5EDT,M4.1.0/02:00,M10.5.0/02:00”) is assumed to be
> standard time.
>
>
>
> I’m not sure whether I draw the right conclusion, but because the
> incorrect assumption of using DST, mktime() returns -3600 (on hour off)
> instead of the expected 0. Is this conclusion correct?
>
>
>
> I’m not sure how to fix it. When changing the call to init_ttinfo() and
> effectively swapping DST and standard time (also for symmetry with the else
> part) in sp-ttis[] (0 to 1 and 1 to 0) + keeping sp->defaulttype = 0 solved
> this problem, but introduces other conversion errors around DSTchanges (I
> don’t have yet an reproduction, but can make one if needed). The
> sp->default type is used (in localsub ()) when if (sp->timecnt == 0 || t <
> sp->ats[0]). The other approach is to assign sp->defaulttype = 1 when the
> init_ttinfo() calls are not swapped. Anyhow, there is a tight relationship
> between the value of sp->defaulttype and the order in which DST/standard
> times are written in sp->ttis[].
>
>
>
> If the previous idea is incorrect (and I guess it is), additional code may
> be needed in time2sub() if yourtm.tm_isdst == -1. In that case, the
> provided data in yourtm should be checked whether DST is (or is not) into
> effect. The found mytm struct should match. Otherwise a DST correction is
> needed (one-hour shift). The current code mistakenly uses DST, and that is
> why (if I understand all well) mktime() now returns -3600.
>
>
>
> If I was not able to explain the issue correctly, please let me know. I’m
> not sure to understand what’s going wrong now, but may be, the provided
> attachment will help in giving better understanding. Because the provided
> date is near 1970, quite few steps are needed to see what’s happing in
> localtime.c.
>
>
>
> Regards,
>
> Kees Dekker
>
>
>
> PS. This email has been sent assuming that attachments will not get lost.
> Otherwise, just copy paste the code below and save to e.g. tztestcase.c.
>
>
>
>
>
> #ifdef _WIN32
>
> #define _CRT_SECURE_NO_WARNINGS
>
> #endif
>
>
>
> #include <time.h>
>
> #include <stdio.h>
>
> #include <stdlib.h>
>
>
>
> int main(void)
>
> {
>
>                 int ret = 0;
>
>                 const char *months[] = { "Jan", "Feb", "Mar", "April",
> "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec" };
>
>                 const char *days[] = { "Sun", "Mon", "Tue", "Wed", "Tur",
> "Fri", "Sat" };
>
>
>
>                 /* DST switch in April in first Sunday and October, last
> Sunday */
>
>                 putenv("TZ=EST5EDT,M4.1.0/02:00,M10.5.0/02:00");
>
>
>
>                 /* January, 1970, invalid input for tm_mday (0 instead
> 1..31) */
>
>                 /* non-normalized input for minutes: 1140/60 = 19, so
> 19:00 EST5EDT time, which is 5 hours before GMT, and should result in t ==
> 0 below */
>
>                 /* let system figure out whether DST is effect */
>
>                 struct tm tmp = { 0, 1140, 0, 0, 0, 70, -858993460,
> -858993460, -1};
>
>
>
>                 printf("enter mktime with: %04d/%s/%02d %02d:%02d:%02d,
> week day: %d, year day: %d, dst: %d\n",
>
>
> tmp.tm_year + 1900, months[tmp.tm_mon], tmp.tm_mday,
>
>
> tmp.tm_hour, tmp.tm_min, tmp.tm_sec,
>
>
> tmp.tm_wday, tmp.tm_yday, tmp.tm_isdst);
>
>
>
>                 time_t t = mktime(&tmp);
>
>
>
>                 /* expect: t == 0, DST is off, time is exactly at the
> boundary of lowest possible UTC value */
>
>                 printf("the return value of mktime is: %lld\n", (long
> long)t);
>
>                 printf("normalized times: %04d/%s/%02d %02d:%02d:%02d,
> week day: %s, year day: %d, dst: %d\n",
>
>
> tmp.tm_year + 1900, months[tmp.tm_mon], tmp.tm_mday,
>
>
> tmp.tm_hour, tmp.tm_min, tmp.tm_sec,
>
>
> days[tmp.tm_wday], tmp.tm_yday, tmp.tm_isdst);
>
>
>
>                 if (t >= 0) {
>
>                                 printf("tz=%s, %s\n", tzname[0],
> tzname[1]);
>
>                 }
>
>
>
>                 return 0;
>
> }
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mm.icann.org/pipermail/tz/attachments/20170111/ba883b90/attachment-0001.html>


More information about the tz mailing list