Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
FpGetTimeOfDay gives no timezone
#1
I try to use Indy objects for sending e-mail in a Linux system (Debian 9, Lazarus 2.0.0.RC3, Indy 10).
The time of the message received by the recepients is wrong. I debuged what Indy does and it uses FpGetTimeOfDay to format an internet datetime string, e.g. in LocalDateTimeToGMT(), ultimately using OffsetFromUTC. According to the manual of GetTimeOfDay (http://man7.org/linux/man-pages/man2/get...day.2.html) the timezone parameter is obsolate and always returns 0 in Linux. This is indeed what I see.
Is there a workaround known, or shall I try to fix it myself (rewriting OffsetFromUTC in IdGlobal)?
Thanks,
Reply
#2
(01-04-2019, 03:59 PM)jollytall Wrote: Is there a workaround known, or shall I try to fix it myself (rewriting OffsetFromUTC in IdGlobal)?

I was not aware of that issue. That is probably why localtime_r() is used instead on Delphi, and FPC in Kylix-compat mode. You could try applying that same logic to the BaseUnix branch and see if it works as well.

Reply
#3
Thanks rlebeau.

What I did now (and it works!) is the following:

Removed lines 7356 and 7357 from IdGlobal.
// timeval: TTimeVal;
// timezone: TTimeZone;
Added a new line:
NowDT:tDateTime;

Removed original lines 7412, 7413 (after the insert of the above 7413, 7414):
// fpGetTimeOfDay (@TimeVal, @TimeZone);
// Result := -1 * (timezone.tz_minuteswest / 60 / 24);
And added two new lines (using DateUtils that is included in this set-up already):
NowDT:=Now;
result:=NowDT-LocalTimeToUniversal(NowDT);

Recompiled indylaz. Works perfekt.

It would be nice to have it fixed in the official IdGlobal as well somehow.

One more point, I have not inverstigated deeper:
DateUtils uses GetLocalTimeOffset to get the LocalTimeToUniversal conversion, so theoretically it would be enough to have:
result:=-GetLocalTimeOffset/60;
Still if I do that in IdGlobal, it gives 0, not the real Offset. Either IdGlobal accesses another version of GetLocalTimeOffset from another library or TZSeconds is not yet initialised if called directly.
Reply
#4
(01-13-2019, 01:16 PM)jollytall Wrote: What I did now (and it works!) is the following:

Interesting, you took a completely different approach than what I was thinking. I was not aware of the LocalTimeToUniversal() and GetLocalTimeOffset() functions.

(01-13-2019, 01:16 PM)jollytall Wrote: DateUtils uses GetLocalTimeOffset to get the LocalTimeToUniversal conversion, so theoretically it would be enough to  have:
result:=-GetLocalTimeOffset/60;

I like that better, but since it returns minutes, I think it needs to be dividing by 24 as well, to make it a proper TDateTime:

Code:
Result := -(GetLocalTimeOffset / 60 / 24);

Or:

Code:
Result := -1 * (GetLocalTimeOffset / 60 / 24);

That would be more inline with the existing USE_BASEUNIX code that divides tz_minuteswest from gettimeofday() by 1440 when converting to TDateTime.

Also, note FreePascal's documentation about GetLocalTimeOffset():

https://www.freepascal.org/docs-html/rtl...ffset.html

Quote:Note that on Linux/Unix, this information may be inaccurate around the DST time changes (for optimization). In that case, the unix.ReReadLocalTime unit must be used to re-initialize the timezone information.

So I would be worried about OffsetFromUTC() returning a bad value from stale data during a DST transition.

(01-13-2019, 01:16 PM)jollytall Wrote: Still if I do that in IdGlobal, it gives 0, not the real Offset. Either IdGlobal accesses another version of GetLocalTimeOffset from another library

It does not.

(01-13-2019, 01:16 PM)jollytall Wrote: or TZSeconds is not yet initialised if called directly.

I wouldn't know. Something to take up with the FreePascal community. However, I did just now find the following:

found bug on GetLocalTimeOffset

Why is LocalTimeToUniversal(Now) two hours later with Lazarus 1.6 / FPC 3.0?

UniversalTimeToLocal(UT: TDateTime) / LocalTimeToUniversal(LT: TDateTime)

0029176: LocalTimeToUniversal returns wrong value

So, now I'm a little hesitant to use FreePascal's functions, rather than using the Nix system calls as before.

Reply
#5
Thanks again.

Indeed, I missed the /24 part. This is why putting that directly to IdGlobal did not work. Now it does. So the fix I have now is easy and simple:
Removed 7355-7357
// var
// timeval: TTimeVal;
// timezone: TTimeZone;
And also 7412-13, but added the corrected new line:
// fpGetTimeOfDay (@TimeVal, @TimeZone);
// Result := -1 * (timezone.tz_minuteswest / 60 / 24);
Result:=-1 * (GetLocalTimeOffset/60/24);

I am aware of the problem, that if daylight saving changes, the bias is not updated automatically. It is not good, but I can live with it for the time being.

As you first suggested, I tried, but could not make it work with localtime_r() as it keeps missing declarations, localtime_r(), TUnixTime. If understood correctly they should be in LibC (deprecated), but could not link it. I did not find it in my platform in RTL. If you can help me, how to do it, I will try again. If we want to use localtime_r(), best would be to declare it in an easily available unit centrally.

The old bugs you mentioned were fixed in FPC, The confusion is always whether bias should be added to or deducted from localtime to get UTC.

Just for curiosity. You wrote (and now I also did):
Result:=-1 * (GetLocalTimeOffset/60/24);
Normally I would write:
Result:=-GetLocalTimeOffset/60/24; // (no -1* just - and no brackets)
Is it a convention or good programming practice, or why? Obviously the other works as well, just the same.

Thanks again,
Reply
#6
(01-15-2019, 07:25 AM)jollytall Wrote: As you first suggested, I tried, but could not make it work with localtime_r() as it keeps missing declarations, localtime_r(), TUnixTime. If understood correctly they should be in LibC (deprecated), but could not link it. I did not find it in my platform in RTL.

Sorry, I can't help with that. I am not a FreePascal user. I know localtime_r() is declared in timeh.inc, but I don't know what unit uses that include file.

(01-15-2019, 07:25 AM)jollytall Wrote: The old bugs you mentioned were fixed in FPC

OK, good to know.

Reply
#7
I have opened a ticket in Indy's issue tracker so I don't forget about this:

#245: OffsetFromUTC() does not work on all Linux systems

Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)