[RESENT] TIME_GetBias

Rein Klazes rklazes at xs4all.nl
Wed Mar 17 02:45:03 CST 2004


On Tue, 16 Mar 2004 20:45:01 +0100, you wrote:

> >>>>> "Alexandre" == Alexandre Julliard <julliard at winehq.org> writes:
> 
>     Alexandre> Uwe Bonnes <bon at elektron.ikp.physik.tu-darmstadt.de> writes:
>     >> ptm = localtime(&utc); ptm = gmtime(&utc); ret = last_bias =
>     >> (int)(utc-mktime(ptm));
>     >> 
>     >> I my understanding mktime(gmtime(time(NULL))) == time(NULL)
> 
>     Alexandre> No, mktime takes local time, it's the reverse of localtime(),
>     Alexandre> not gmtime().
> 
> But then, what is wrong with
> bias = int(time(NULL) - mktime(localtime(mktime(NULL).

parsing error.

> 
> like I suppose with my patch
> 
> At present, we do 
> bias = int(time(NULL) - mktime((gmtime(mktime(NULL)||changes tm_isdst)))
> 
> which is diffuse at least and at make the quickworks/synplicity/flexlm combo
> stop.
> 
> Don't count the hours, I have hunted that bug. Any help is appreciated.

Uwe,

I am responsible for that diffuse computation, and there were IMHO good
reasons for it. If you still have the messages, it was discussed on
wine-devel 6-9 June 1999 in a thread "GetTimeZoneInformation patch". The
final conclusion is attached to this message.

First thing to notice is that one of the reasons for choosing this
computation are changes in glibc that broke another more obvious way.

Next this computation was at that time part of the
GetTimeZoneInformation API function only, if you change it you
immediately break the function and the time displayed in my mail reader
is wrong. 

Now the function is called in more places, this may simply be done
wrong. I cannot remember what API function(s) are causing your
application to fail.

Your algorithm:

        ptm = localtime(&utc);
	ret = last_bias = (int)(utc-mktime(ptm));

is in short:
        bias = utc - mktime(localtime(&utc))

As Alexandre already said mktime and localtime are each others opposite,
so:
	mktime(localtime(&utc) == utc

which leaves:
	
	bias = utc - utc

which makes bias always zero, and tested on my system it surely makes it
return zero. Is that different on your system?
If that is not the case then our assumptions are wrong. Can there be a
buggy libc involved (mine is 2.3.2)?

Hope this helped.

Rein.
-- 
Rein Klazes
rklazes at xs4all.nl
-------------- next part --------------
On 08 Jun 1999 11:10:53 +0200, you wrote:

> rklazes at casema.net (Rein Klazes) writes:
> 
> > Well the previous code was mine as well. It returned the wrong answer
> > on one of my machines since summer tiem started, gmttime() returned
> > only a one hour difference with local time, ignoring the daylight
> > saving time. The affected program is Agent 32bit.
> > 
> > This is the only solution that I could come up with that works on both
> > my machines: one Linux Debian 2.0 bios time is UTC and one with Debian
> > 2.1 with libc upgraded to 2.1 with bios time is local time (the one
> > that failed the previous code).
> 
> Strange, it seems to work fine for me, both with libc 2.0 and 2.1.

Cannot explain this, unless you have libc 2.1.0, libc 2.1.1 fixes a
number of problems with timezones.

I upgraded this morning to the latest glibc (debian 2.1.1-10, was
2.1.1-5), and still the problem exists. So I looked at the code again,
and now I think I can explain why it doesn't work here.

time(NULL) returns UTC as seconds since the epoch. localtime() breaks
this down and returns the local time taking into account timezone and
daylight. mktime() does exactly the inverse this means that:

mktime(localtime(x)) = x for all x;

Now the code doesn't use localtime(), but gmtime() instead. At this
time gmtime(time(NULL)) returns a tm structure with tm_isdst = 0. This
is perfectly reasonable to me. tm_hour differs of course two hours in
my timezone (Europe/Amsterdam).

mktime() in glibc-2.1.1 takes the tm_isdst into account, adding an
hour to the effective time when daylight time is in effect. Nett
result is that:

mktime(gmtime(x)) = x - 3600 for current x values;

mktime() in previous versions calculated tm_isdst according to the
time zone rules, and filled it in the tm structure. The extra hour is
not added so we have:

mktime(gmtime(x)) = x - 7200 for current x values;

The changed mktime() behaviour is discussed here:

http://www-gnats.gnu.org:8080/cgi-bin/wwwgnats.pl/full/1098

The old behaviour can be reproduced using tm_isdst<0, but I think it
is better to set it to the same state as the local time, this should
work even when the daylight is making a change.

> 
> > Of course the assumption of 60 minutes difference is ugly, I haven't
> > found a  way to get the actual value. Yet note that the function still
> > returns the correct total difference between GMT and local time even
> > when the actual daylight saving time diffence is not 60 minutes. This
> > by the also hard coded 60 minutes difference in tzinfo->DayLightBias.
> > The current solution relies on the program to do something sensible
> > with TIME_ZONE_ID_UNKNOWN.
> 
> I'm afraid there is no way around that, at least according to the
> doc. If we return something else than TIME_ZONE_ID_UNKNOWN, we also
> have to set StandardDate and DaylightDate, and I don't know of any
> portable way to retrieve this info under Unix.

You could do some binary search using localtime() to find the dates.
Yet I do not know any program that is even interested in daylight, so
I leave that out. 

New patch in wine-patches, tested on glibc-2.0.7 and glibc-2.1.1.

Rein.
-- 
Rein Klazes
rklazes at casema.net



More information about the wine-devel mailing list