Recent

Author Topic: Use UNIX function (localtime)  (Read 3107 times)

DevilDevil

  • New Member
  • *
  • Posts: 49
Use UNIX function (localtime)
« on: April 01, 2020, 12:02:54 am »
Unfortunately, I do not understand how to use the standard UNIX function localtime

Code: Pascal  [Select][+][-]
  1. function localtime(var time: time_t): PTm; cdecl;

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Use UNIX function (localtime)
« Reply #1 on: April 01, 2020, 12:26:23 am »
Hi!

Do you need the local time or do you want to dive in the Unix jungle?

The first is easy:

Code: Pascal  [Select][+][-]
  1. function Now : TDateTime;

gives you the local time.

Code: Pascal  [Select][+][-]
  1. function NowUTC: TDateTime;

gives you the international universal time.

The first is in unit sysutils, the later in LazSysutils.

To get your local timeoffset there is

Code: Pascal  [Select][+][-]
  1. GetLocalTimeOffset

which returns the Timezone in minutes.


Or do you prefer to fool around with imported C functions?
It is already there - as you can see.

Winni

DevilDevil

  • New Member
  • *
  • Posts: 49
Re: Use UNIX function (localtime)
« Reply #2 on: April 02, 2020, 03:34:58 pm »
winni,

Hi!

I need to call exactly UNIX (POSIX) functions. For example, in Delphi, this function is contained in the Posix.Time unit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Use UNIX function (localtime)
« Reply #3 on: April 02, 2020, 04:35:40 pm »
I need to call exactly UNIX (POSIX) functions. For example, in Delphi, this function is contained in the Posix.Time unit.

Then declare the relevant functions and use them.  Delphi Linux units are not supported, since Delphi Linux support is still quite new (and FPC's dates from 1995)

DevilDevil

  • New Member
  • *
  • Posts: 49
Re: Use UNIX function (localtime)
« Reply #4 on: April 03, 2020, 01:34:47 pm »
Thanks

I am developing a low-level unit, I can not use SysUtils in it. Yes, I need to know the difference in seconds between local time and UTC. Similarly, I did this using the localtime function. But now, for some reason, time returns local time, not UTC. Does anyone know how to fix this?

Code: Pascal  [Select][+][-]
  1. {$if Defined(FPC) and Defined(UNIX)}
  2. const
  3.   libc = 'libc.so';
  4.  
  5. type
  6.   tm = packed record
  7.     tm_sec: Integer;            // Seconds. [0-60] (1 leap second)
  8.     tm_min: Integer;            // Minutes. [0-59]
  9.     tm_hour: Integer;           // Hours.[0-23]
  10.     tm_mday: Integer;           // Day.[1-31]
  11.     tm_mon: Integer;            // Month.[0-11]
  12.     tm_year: Integer;           // Year since 1900
  13.     tm_wday: Integer;           // Day of week [0-6] (Sunday = 0)
  14.     tm_yday: Integer;           // Days of year [0-365]
  15.     tm_isdst: Integer;          // Daylight Savings flag [-1/0/1]
  16.     tm_gmtoff: Integer;         // Seconds east of UTC
  17.     tm_zone: PAnsiChar;         // Timezone abbreviation
  18.   end;
  19.   Ptm = ^tm;
  20.  
  21. function time(var Timer: time_t): time_t; cdecl; external libc name 'time';
  22. function gmtime(var Timer: time_t): Ptm; cdecl; external libc name 'gmtime';
  23. function localtime(var Timer: time_t): Ptm; cdecl; external libc name 'localtime';
  24. {$ifend}
  25.  
  26. class function TOSTime.UpdateLocalDelta: Int64;
  27. {$ifdef MSWINDOWS}
  28. var
  29.   LUTCTime: TFileTime;
  30.   LLocalTime: TFileTime;
  31. begin
  32.   GetSystemTimeAsFileTime(LUTCTime);
  33.   FileTimeToLocalFileTime(LUTCTime, LLocalTime);
  34.   Result := Int64(LLocalTime) - Int64(LUTCTime);
  35.   TIMESTAMP_LOCAL_DELTA := Result;
  36. end;
  37. {$else .POSIX}
  38. var
  39.   LUtcTime: {$ifdef FPC}time_t{$else .DELPHI}Posix.SysTypes.time_t{$endif};
  40.   LTime, LLocalTime: {$ifdef FPC}Ptm{$else .DELPHI}Posix.Time.Ptm{$endif};
  41. begin
  42.   {$ifdef FPC}
  43.   time(LUtcTime);
  44.   LTime := gmtime(LUtcTime);
  45.   LLocalTime := localtime(LUtcTime); // LTime^ = LLocalTime^ !!!
  46.   {$else .DELPHI}
  47.   Posix.Time.time(@LUtcTime);
  48.   LTime := gmtime(LUtcTime);
  49.   LLocalTime := Posix.Time.localtime(LUtcTime);
  50.   {$endif}
  51.  
  52.   if (Assigned(LTime)) and (Assigned(LLocalTime)) then
  53.   begin
  54.     Result := LLocalTime.tm_gmtoff * TIMESTAMP_SECOND;
  55.   end else
  56.   begin
  57.     Result := 0;
  58.   end;
  59.  
  60.   TIMESTAMP_LOCAL_DELTA := Result;
  61. end;
  62. {$endif}  
     

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Use UNIX function (localtime)
« Reply #5 on: April 03, 2020, 01:49:11 pm »
Did you test unixutils.tzseconds ? Though this is formally not supported (it is an Unix rtl internal unit)

Afaik time gives system clock, and it is a per system config if that is UTC or local.

DevilDevil

  • New Member
  • *
  • Posts: 49
Re: Use UNIX function (localtime)
« Reply #6 on: April 03, 2020, 01:57:07 pm »
marcov,

Yep. But this variable is initialized inside SysUtils. If the unit is not used, the variable is 0.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Use UNIX function (localtime)
« Reply #7 on: April 03, 2020, 02:10:31 pm »
marcov,

Yep. But this variable is initialized inside SysUtils. If the unit is not used, the variable is 0.

But is it correct if you do use sysutils just to test ? Then you can copy the way it is calculated (environment variable TZ iirc)

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Use UNIX function (localtime)
« Reply #8 on: April 03, 2020, 02:35:31 pm »
There is support for the - Kylix compatibility - localtime in libc which is disabled by default. It has all the right declarations. See time.pas and timeh.inc.
(I would not call Kylix relatively recent...)
« Last Edit: April 03, 2020, 02:42:01 pm by Thaddy »
Specialize a type, not a var.

DevilDevil

  • New Member
  • *
  • Posts: 49
Re: Use UNIX function (localtime)
« Reply #9 on: April 03, 2020, 06:28:51 pm »
marcov

tzseconds is initialized in the GetLocalTimezone function of the timezone.inc file. Maybe it would be possible to copy the implementation, but the memory manager is used there, which I need to avoid (my unit, for example, can be used inside an alternative manager, so these functions cannot be used). I want to find a simple alternative way.

As far as I understand, the problem is that the time function returns local time, not UTC.

DevilDevil

  • New Member
  • *
  • Posts: 49
Re: Use UNIX function (localtime)
« Reply #10 on: April 03, 2020, 06:34:52 pm »
Thaddy,

The timeh.inc file is used inside the libc.pp unit, not time.pas. I don’t understand yet how to connect the libc.pp unit)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Use UNIX function (localtime)
« Reply #11 on: April 03, 2020, 06:56:34 pm »
Thaddy,

The timeh.inc file is used inside the libc.pp unit, not time.pas. I don’t understand yet how to connect the libc.pp unit)

The libc unit are just old (2005) header translations, and 32-bit x86 only. If you persist in this better roll your own.

DevilDevil

  • New Member
  • *
  • Posts: 49
Re: Use UNIX function (localtime)
« Reply #12 on: April 03, 2020, 10:29:16 pm »
Maybe after all someone knows how to make the time function return UTC?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Use UNIX function (localtime)
« Reply #13 on: April 03, 2020, 10:39:08 pm »
Maybe after all someone knows how to make the time function return UTC?

Configure your Linux to set your hardware clock to UTC?  Usually that is a question during installation.


winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Use UNIX function (localtime)
« Reply #14 on: April 03, 2020, 11:11:09 pm »
Hi!

Then have a look inside of nowUTC:


Code: Pascal  [Select][+][-]
  1. function NowUTC: TDateTime;
  2. var
  3.   tz:timeval;
  4.   SystemTime: TSystemTime;
  5. begin
  6.   fpgettimeofday(@tz,nil);
  7.   EpochToLocal(tz.tv_sec,SystemTime.year,SystemTime.month,SystemTime.day,  
  8.    SystemTime.hour,SystemTime.Minute,SystemTime.Second);
  9.   SystemTime.MilliSecond:=tz.tv_usec div 1000;
  10.   result := systemTimeToDateTime(SystemTime);
  11. end;        
  12.  

As you dont want to use Sysutils and LazSysutils let us discuss the single steps:

* fpgettimeofday is a built in fpc procedure
* EpochToLocal  is not so big and tricky - you can copy it from LazSysutils
* EpochToLocal uses JulianToGregorian which is only 20 lines with the old formula from Gauß.
*systemTimeToDateTime: you will not use it because it collects all values to build a TDateTime=Double. The values exist all in the record TSystemTime (hour, minute, ......)

So with let's say 2 screens you get the UTCtime.

Winni
« Last Edit: April 03, 2020, 11:23:41 pm by winni »

 

TinyPortal © 2005-2018