mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-16 16:39:19 +02:00
* thread-safe time zone info read/write
git-svn-id: trunk@47309 -
This commit is contained in:
parent
c64429cdd0
commit
7fbceaac21
@ -41,10 +41,6 @@ var
|
|||||||
ucal_inDaylightTime: function (cal: UCalendar; var status: UErrorCode): UBool; cdecl;
|
ucal_inDaylightTime: function (cal: UCalendar; var status: UErrorCode): UBool; cdecl;
|
||||||
ucal_get: function (cal: UCalendar; field: UCalendarDateFields; var status: UErrorCode): int32_t; cdecl;
|
ucal_get: function (cal: UCalendar; field: UCalendarDateFields; var status: UErrorCode): int32_t; cdecl;
|
||||||
|
|
||||||
var
|
|
||||||
TZStandardName: utf8string;
|
|
||||||
TZDaylightName: utf8string;
|
|
||||||
|
|
||||||
GetIcuProc: function (const Name: AnsiString; var ProcPtr; libId: longint): boolean; external name 'ANDROID_GET_ICU_PROC';
|
GetIcuProc: function (const Name: AnsiString; var ProcPtr; libId: longint): boolean; external name 'ANDROID_GET_ICU_PROC';
|
||||||
|
|
||||||
procedure ReadTimeZoneFromICU;
|
procedure ReadTimeZoneFromICU;
|
||||||
@ -52,8 +48,12 @@ var
|
|||||||
locale: utf8string;
|
locale: utf8string;
|
||||||
tz: unicodestring;
|
tz: unicodestring;
|
||||||
res: unicodestring;
|
res: unicodestring;
|
||||||
|
TZStandardName: utf8string;
|
||||||
|
TZDaylightName: utf8string;
|
||||||
err: UErrorCode;
|
err: UErrorCode;
|
||||||
cal: UCalendar;
|
cal: UCalendar;
|
||||||
|
lTZInfo: TTZInfo;
|
||||||
|
lTZInfoEx: TTZInfo;
|
||||||
begin
|
begin
|
||||||
if not Assigned(GetIcuProc) then exit;
|
if not Assigned(GetIcuProc) then exit;
|
||||||
if not GetIcuProc('ucal_open', ucal_open, 1) then exit;
|
if not GetIcuProc('ucal_open', ucal_open, 1) then exit;
|
||||||
@ -68,25 +68,30 @@ begin
|
|||||||
cal:=ucal_open(PUnicodeChar(tz), Length(tz), PAnsiChar(locale), 0, err);
|
cal:=ucal_open(PUnicodeChar(tz), Length(tz), PAnsiChar(locale), 0, err);
|
||||||
if cal = nil then
|
if cal = nil then
|
||||||
exit;
|
exit;
|
||||||
Tzinfo.daylight:=ucal_inDaylightTime(cal, err);
|
lTzinfo.daylight:=ucal_inDaylightTime(cal, err);
|
||||||
|
|
||||||
SetLength(res, 200);
|
SetLength(res, 200);
|
||||||
SetLength(res, ucal_getTimeZoneDisplayName(cal, UCAL_SHORT_STANDARD, PAnsiChar(locale), PUnicodeChar(res), Length(res), err));
|
SetLength(res, ucal_getTimeZoneDisplayName(cal, UCAL_SHORT_STANDARD, PAnsiChar(locale), PUnicodeChar(res), Length(res), err));
|
||||||
TZStandardName:=utf8string(res);
|
TZStandardName:=utf8string(res);
|
||||||
Tzinfo.name[False]:=PAnsiChar(TZStandardName);
|
lTZInfoEx.name[False]:=TZStandardName;
|
||||||
|
|
||||||
SetLength(res, 200);
|
SetLength(res, 200);
|
||||||
SetLength(res, ucal_getTimeZoneDisplayName(cal, UCAL_SHORT_DST, PAnsiChar(locale), PUnicodeChar(res), Length(res), err));
|
SetLength(res, ucal_getTimeZoneDisplayName(cal, UCAL_SHORT_DST, PAnsiChar(locale), PUnicodeChar(res), Length(res), err));
|
||||||
TZDaylightName:=utf8string(res);
|
TZDaylightName:=utf8string(res);
|
||||||
Tzinfo.name[True]:=PAnsiChar(TZDaylightName);
|
lTZInfoEx.name[True]:=TZDaylightName;
|
||||||
|
|
||||||
Tzinfo.seconds:=ucal_get(cal, UCAL_ZONE_OFFSET, err) div 1000;
|
lTZInfoEx.leap_correct:=0;
|
||||||
if Tzinfo.daylight then
|
lTZInfoEx.leap_hit:=0;
|
||||||
Tzinfo.seconds:=Tzinfo.seconds + ucal_get(cal, UCAL_DST_OFFSET, err) div 1000;
|
|
||||||
|
lTZInfo.seconds:=ucal_get(cal, UCAL_ZONE_OFFSET, err) div 1000;
|
||||||
|
if lTZInfo.daylight then
|
||||||
|
lTZInfo.seconds:=Tzinfo.seconds + ucal_get(cal, UCAL_DST_OFFSET, err) div 1000;
|
||||||
|
|
||||||
// ToDo: correct validsince/validuntil values
|
// ToDo: correct validsince/validuntil values
|
||||||
Tzinfo.validsince:=low(Tzinfo.validsince);
|
lTZInfo.validsince:=low(lTZInfo.validsince);
|
||||||
Tzinfo.validuntil:=high(Tzinfo.validuntil);
|
lTZInfo.validuntil:=high(lTZInfo.validuntil);
|
||||||
|
|
||||||
|
SetTZInfo(lTZInfo, lTZInfoEx);
|
||||||
|
|
||||||
ucal_close(cal);
|
ucal_close(cal);
|
||||||
end;
|
end;
|
||||||
|
@ -1653,13 +1653,14 @@ begin
|
|||||||
else
|
else
|
||||||
UnixTime:=LocalToEpoch(Year, Month, Day, Hour, Minute, Second);
|
UnixTime:=LocalToEpoch(Year, Month, Day, Hour, Minute, Second);
|
||||||
{ check if time is in current global Tzinfo }
|
{ check if time is in current global Tzinfo }
|
||||||
if (Tzinfo.validsince<UnixTime) and (UnixTime<Tzinfo.validuntil) then
|
lTzinfo:=Tzinfo;
|
||||||
|
if (lTzinfo.validsince<=UnixTime) and (UnixTime<lTzinfo.validuntil) then
|
||||||
begin
|
begin
|
||||||
Result:=True;
|
Result:=True;
|
||||||
Offset:=-TZInfo.seconds div 60;
|
Offset:=-lTZInfo.seconds div 60;
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
Result:=GetLocalTimezone(UnixTime,True,lTZInfo,False);
|
Result:=GetLocalTimezone(UnixTime,True,lTZInfo);
|
||||||
if Result then
|
if Result then
|
||||||
Offset:=-lTZInfo.seconds div 60;
|
Offset:=-lTZInfo.seconds div 60;
|
||||||
end;
|
end;
|
||||||
|
@ -75,64 +75,93 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function GetLocalTimezone(timer:cint;timerIsUTC:Boolean;var ATZInfo:TTZInfo;FullInfo:Boolean):Boolean;
|
procedure DoGetLocalTimezone(info:pttinfo;const trans_start,trans_end:longint;var ATZInfo:TTZInfo);
|
||||||
var
|
|
||||||
info : pttinfo;
|
|
||||||
i,trans_start,trans_end : longint;
|
|
||||||
begin
|
begin
|
||||||
{ reset }
|
|
||||||
ATZInfo.Daylight:=false;
|
|
||||||
ATZInfo.Seconds:=0;
|
|
||||||
ATZInfo.Name[false]:=nil;
|
|
||||||
ATZInfo.Name[true]:=nil;
|
|
||||||
ATZInfo.validsince:=0;
|
|
||||||
ATZInfo.validuntil:=0;
|
|
||||||
ATZInfo.leap_correct:=0;
|
|
||||||
ATZInfo.leap_hit:=0;
|
|
||||||
{ get info }
|
|
||||||
info:=find_transition(timer,timerIsUTC,trans_start,trans_end);
|
|
||||||
GetLocalTimezone:=assigned(info);
|
|
||||||
if not GetLocalTimezone then
|
|
||||||
exit;
|
|
||||||
ATZInfo.validsince:=trans_start;
|
ATZInfo.validsince:=trans_start;
|
||||||
ATZInfo.validuntil:=trans_end;
|
ATZInfo.validuntil:=trans_end;
|
||||||
ATZInfo.Daylight:=info^.isdst;
|
ATZInfo.Daylight:=info^.isdst;
|
||||||
ATZInfo.Seconds:=info^.offset;
|
ATZInfo.Seconds:=info^.offset;
|
||||||
if not FullInfo then
|
end;
|
||||||
Exit;
|
|
||||||
|
procedure DoGetLocalTimezoneEx(timer:cint;info:pttinfo;var ATZInfoEx:TTZInfoEx);
|
||||||
|
var
|
||||||
|
i : longint;
|
||||||
|
names: array[Boolean] of pchar;
|
||||||
|
begin
|
||||||
|
names[true]:=nil;
|
||||||
|
names[false]:=nil;
|
||||||
|
ATZInfoEx.leap_hit:=0;
|
||||||
|
ATZInfoEx.leap_correct:=0;
|
||||||
|
|
||||||
i:=0;
|
i:=0;
|
||||||
while (i<num_types) do
|
while (i<num_types) do
|
||||||
begin
|
begin
|
||||||
ATZInfo.name[types[i].isdst]:=@zone_names[types[i].idx];
|
names[types[i].isdst]:=@zone_names[types[i].idx];
|
||||||
inc(i);
|
inc(i);
|
||||||
end;
|
end;
|
||||||
ATZInfo.name[info^.isdst]:=@zone_names[info^.idx];
|
names[info^.isdst]:=@zone_names[info^.idx];
|
||||||
|
ATZInfoEx.name[true]:=names[true];
|
||||||
|
ATZInfoEx.name[false]:=names[false];
|
||||||
i:=num_leaps;
|
i:=num_leaps;
|
||||||
repeat
|
repeat
|
||||||
if i=0 then
|
if i=0 then
|
||||||
exit;
|
exit;
|
||||||
dec(i);
|
dec(i);
|
||||||
until (timer>leaps[i].transition);
|
until (timer>leaps[i].transition);
|
||||||
ATZInfo.leap_correct:=leaps[i].change;
|
ATZInfoEx.leap_correct:=leaps[i].change;
|
||||||
if (timer=leaps[i].transition) and
|
if (timer=leaps[i].transition) and
|
||||||
(((i=0) and (leaps[i].change>0)) or
|
(((i=0) and (leaps[i].change>0)) or
|
||||||
(leaps[i].change>leaps[i-1].change)) then
|
(leaps[i].change>leaps[i-1].change)) then
|
||||||
begin
|
begin
|
||||||
ATZInfo.leap_hit:=1;
|
ATZInfoEx.leap_hit:=1;
|
||||||
while (i>0) and
|
while (i>0) and
|
||||||
(leaps[i].transition=leaps[i-1].transition+1) and
|
(leaps[i].transition=leaps[i-1].transition+1) and
|
||||||
(leaps[i].change=leaps[i-1].change+1) do
|
(leaps[i].change=leaps[i-1].change+1) do
|
||||||
begin
|
begin
|
||||||
inc(ATZInfo.leap_hit);
|
inc(ATZInfoEx.leap_hit);
|
||||||
dec(i);
|
dec(i);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function GetLocalTimezone(timer:cint;timerIsUTC:Boolean;var ATZInfo:TTZInfo):Boolean;
|
||||||
procedure GetLocalTimezone(timer:cint;timerIsUTC:Boolean);
|
var
|
||||||
|
info: pttinfo;
|
||||||
|
trans_start,trans_end: longint;
|
||||||
begin
|
begin
|
||||||
GetLocalTimezone(timer,timerIsUTC,Tzinfo,true);
|
LockTZInfo;
|
||||||
|
info:=find_transition(timer,timerIsUTC,trans_start,trans_end);
|
||||||
|
GetLocalTimezone:=assigned(info);
|
||||||
|
if GetLocalTimezone then
|
||||||
|
DoGetLocalTimezone(info,trans_start,trans_end,ATZInfo);
|
||||||
|
UnlockTZInfo;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetLocalTimezone(timer:cint;timerIsUTC:Boolean;var ATZInfo:TTZInfo;var ATZInfoEx:TTZInfoEx):Boolean;
|
||||||
|
var
|
||||||
|
info: pttinfo;
|
||||||
|
trans_start,trans_end: longint;
|
||||||
|
begin
|
||||||
|
LockTZInfo;
|
||||||
|
info:=find_transition(timer,timerIsUTC,trans_start,trans_end);
|
||||||
|
GetLocalTimezone:=assigned(info);
|
||||||
|
if GetLocalTimezone then
|
||||||
|
begin
|
||||||
|
DoGetLocalTimezone(info,trans_start,trans_end,ATZInfo);
|
||||||
|
DoGetLocalTimezoneEx(timer,info,ATZInfoEx);
|
||||||
|
end;
|
||||||
|
UnlockTZInfo;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure RefreshTZInfo;
|
||||||
|
var
|
||||||
|
NewTZInfo: TTZInfo;
|
||||||
|
NewTZInfoEx: TTZInfoEx;
|
||||||
|
begin
|
||||||
|
LockTZInfo;
|
||||||
|
if GetLocalTimezone(fptime,false,NewTZInfo,NewTZInfoEx) then
|
||||||
|
SetTZInfo(NewTZInfo,NewTZInfoEx);
|
||||||
|
UnlockTZInfo;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Const
|
Const
|
||||||
@ -352,7 +381,7 @@ end;
|
|||||||
procedure InitLocalTime;
|
procedure InitLocalTime;
|
||||||
begin
|
begin
|
||||||
ReadTimezoneFile(GetTimezoneFile);
|
ReadTimezoneFile(GetTimezoneFile);
|
||||||
GetLocalTimezone(fptime,false);
|
RefreshTZInfo;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -381,6 +410,8 @@ end;
|
|||||||
Procedure ReReadLocalTime;
|
Procedure ReReadLocalTime;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
LockTZInfo;
|
||||||
DoneLocalTime;
|
DoneLocalTime;
|
||||||
InitLocalTime;
|
InitLocalTime;
|
||||||
|
UnlockTZInfo;
|
||||||
end;
|
end;
|
||||||
|
137
rtl/unix/unix.pp
137
rtl/unix/unix.pp
@ -56,23 +56,27 @@ Const
|
|||||||
type
|
type
|
||||||
TTZInfo = record
|
TTZInfo = record
|
||||||
daylight : boolean;
|
daylight : boolean;
|
||||||
name : array[boolean] of pchar;
|
|
||||||
seconds : Longint; // difference from UTC
|
seconds : Longint; // difference from UTC
|
||||||
validsince : int64; // UTC timestamp
|
validsince : int64; // UTC timestamp
|
||||||
validuntil : int64; // UTC timestamp
|
validuntil : int64; // UTC timestamp
|
||||||
|
end;
|
||||||
|
TTZInfoEx = record
|
||||||
|
name : array[boolean] of RawByteString; { False = StandardName, True = DaylightName }
|
||||||
leap_correct : longint;
|
leap_correct : longint;
|
||||||
leap_hit : longint;
|
leap_hit : longint;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
|
||||||
Tzinfo : TTZInfo;
|
|
||||||
|
|
||||||
Function GetTzseconds : Longint;
|
Function GetTzseconds : Longint;
|
||||||
property Tzseconds : Longint read GetTzseconds;
|
property Tzseconds : Longint read GetTzseconds;
|
||||||
function Gettzdaylight : boolean;
|
function Gettzdaylight : boolean;
|
||||||
function Gettzname(const b : boolean) : pchar;
|
|
||||||
property tzdaylight : boolean read Gettzdaylight;
|
property tzdaylight : boolean read Gettzdaylight;
|
||||||
property tzname[b : boolean] : pchar read Gettzname;
|
function Gettzname(const b : boolean) : string;
|
||||||
|
property tzname[b : boolean] : string read Gettzname;
|
||||||
|
function GetTZInfo : TTZInfo;
|
||||||
|
property TZInfo : TTZInfo read GetTZInfo;
|
||||||
|
function GetTZInfoEx : TTZInfoEx;
|
||||||
|
property TZInfoEx : TTZInfoEx read GetTZInfoEx;
|
||||||
|
procedure SetTZInfo(const ATZInfo: TTZInfo; const ATZInfoEx: TTZInfoEx);
|
||||||
|
|
||||||
{************ Procedure/Functions ************}
|
{************ Procedure/Functions ************}
|
||||||
|
|
||||||
@ -84,14 +88,14 @@ var
|
|||||||
// it doesn't (yet) work for.
|
// it doesn't (yet) work for.
|
||||||
|
|
||||||
{ timezone support }
|
{ timezone support }
|
||||||
function GetLocalTimezone(timer:cint;timerIsUTC:Boolean;var ATZInfo:TTZInfo;FullInfo:Boolean):Boolean;
|
function GetLocalTimezone(timer:cint;timerIsUTC:Boolean;var ATZInfo:TTZInfo;var ATZInfoEx:TTZInfoEx):Boolean;
|
||||||
procedure GetLocalTimezone(timer:cint;timerIsUTC:Boolean);
|
function GetLocalTimezone(timer:cint;timerIsUTC:Boolean;var ATZInfo:TTZInfo):Boolean;
|
||||||
|
procedure RefreshTZInfo;
|
||||||
procedure ReadTimezoneFile(fn:string);
|
procedure ReadTimezoneFile(fn:string);
|
||||||
function GetTimezoneFile:string;
|
function GetTimezoneFile:string;
|
||||||
Procedure ReReadLocalTime;
|
Procedure ReReadLocalTime;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
Procedure RefreshTZInfoIfNeeded;
|
|
||||||
Function UniversalToEpoch(year,month,day,hour,minute,second:Word):int64; // use DateUtils.DateTimeToUnix for cross-platform applications
|
Function UniversalToEpoch(year,month,day,hour,minute,second:Word):int64; // use DateUtils.DateTimeToUnix for cross-platform applications
|
||||||
Function LocalToEpoch(year,month,day,hour,minute,second:Word):int64; // use DateUtils.DateTimeToUnix for cross-platform applications
|
Function LocalToEpoch(year,month,day,hour,minute,second:Word):int64; // use DateUtils.DateTimeToUnix for cross-platform applications
|
||||||
Procedure EpochToLocal(epoch:int64;var year,month,day,hour,minute,second:Word); // use DateUtils.UnixToDateTime for cross-platform applications
|
Procedure EpochToLocal(epoch:int64;var year,month,day,hour,minute,second:Word); // use DateUtils.UnixToDateTime for cross-platform applications
|
||||||
@ -187,6 +191,31 @@ Function getenv(name:string):Pchar; external name 'FPC_SYSC_FPGETENV';
|
|||||||
timezone support
|
timezone support
|
||||||
******************************************************************************}
|
******************************************************************************}
|
||||||
|
|
||||||
|
var
|
||||||
|
CurrentTZinfo : array [0..1] of TTZInfo;
|
||||||
|
CurrentTzinfoEx : array [0..1] of TTZInfoEx;
|
||||||
|
CurrentTZindex : LongInt = 0; // current index for CurrentTZinfo/CurrentTZinfoEx - can be only 0 or 1
|
||||||
|
{$ifdef FPC_HAS_FEATURE_THREADING}
|
||||||
|
UseTZThreading: Boolean = false;
|
||||||
|
TZInfoCS: TRTLCriticalSection;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
|
procedure LockTZInfo;
|
||||||
|
begin
|
||||||
|
{$if declared(UseTZThreading)}
|
||||||
|
if UseTZThreading then
|
||||||
|
EnterCriticalSection(TZInfoCS);
|
||||||
|
{$endif}
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure UnlockTZInfo;
|
||||||
|
begin
|
||||||
|
{$if declared(UseTZThreading)}
|
||||||
|
if UseTZThreading then
|
||||||
|
LeaveCriticalSection(TZInfoCS);
|
||||||
|
{$endif}
|
||||||
|
end;
|
||||||
|
|
||||||
Function GetTzseconds : Longint;
|
Function GetTzseconds : Longint;
|
||||||
begin
|
begin
|
||||||
GetTzseconds:=Tzinfo.seconds;
|
GetTzseconds:=Tzinfo.seconds;
|
||||||
@ -197,9 +226,43 @@ begin
|
|||||||
Gettzdaylight:=Tzinfo.daylight;
|
Gettzdaylight:=Tzinfo.daylight;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function Gettzname(const b : boolean) : pchar;
|
function Gettzname(const b : boolean) : string;
|
||||||
begin
|
begin
|
||||||
Gettzname:=Tzinfo.name[b];
|
Gettzname:=TzinfoEx.name[b];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetTZInfo : TTZInfo;
|
||||||
|
var
|
||||||
|
curtime: time_t;
|
||||||
|
begin
|
||||||
|
GetTZInfo:=CurrentTZinfo[InterlockedExchangeAdd(CurrentTZindex, 0)];
|
||||||
|
curtime:=fptime;
|
||||||
|
if not((GetTZInfo.validsince+GetTZInfo.seconds<=curtime) and (curtime<GetTZInfo.validuntil+GetTZInfo.seconds)) then
|
||||||
|
begin
|
||||||
|
RefreshTZInfo;
|
||||||
|
GetTZInfo:=CurrentTZinfo[InterlockedExchangeAdd(CurrentTZindex, 0)];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetTZInfoEx : TTZInfoEx;
|
||||||
|
begin
|
||||||
|
GetTZInfoEx:=CurrentTzinfoEx[InterlockedExchangeAdd(CurrentTZindex, 0)];
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure SetTZInfo(const ATZInfo: TTZInfo; const ATZInfoEx: TTZInfoEx);
|
||||||
|
var
|
||||||
|
OldTZindex,NewTZindex: longint;
|
||||||
|
begin
|
||||||
|
LockTZInfo;
|
||||||
|
OldTZindex:=InterlockedExchangeAdd(CurrentTZindex,0);
|
||||||
|
if OldTZindex=0 then
|
||||||
|
NewTZindex:=1
|
||||||
|
else
|
||||||
|
NewTZindex:=0;
|
||||||
|
CurrentTzinfo[NewTZindex]:=ATZInfo;
|
||||||
|
CurrentTzinfoEx[NewTZindex]:=ATZInfoEx;
|
||||||
|
InterlockedExchangeAdd(CurrentTZindex,NewTZindex-OldTZindex);
|
||||||
|
UnlockTZInfo;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Const
|
Const
|
||||||
@ -235,20 +298,22 @@ Procedure EpochToLocal(epoch:Int64;var year,month,day,hour,minute,second:Word);
|
|||||||
Transforms Epoch time into local time (hour, minute,seconds)
|
Transforms Epoch time into local time (hour, minute,seconds)
|
||||||
}
|
}
|
||||||
Var
|
Var
|
||||||
DateNum: LongInt;
|
|
||||||
lTZInfo: TTZInfo;
|
lTZInfo: TTZInfo;
|
||||||
|
lseconds: LongInt;
|
||||||
Begin
|
Begin
|
||||||
{ check if time is in current global Tzinfo }
|
{ check if time is in current global Tzinfo }
|
||||||
if (Tzinfo.validsince<epoch) and (epoch<Tzinfo.validuntil) then
|
lTZInfo:=TZInfo;
|
||||||
inc(Epoch,TZInfo.seconds)
|
lseconds:=lTZInfo.seconds;
|
||||||
|
if (lTZInfo.validsince<=epoch) and (epoch<lTZInfo.validuntil) then
|
||||||
|
inc(Epoch,lseconds)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
{$if declared(GetLocalTimezone)}
|
{$if declared(GetLocalTimezone)}
|
||||||
if GetLocalTimezone(epoch,true,lTZInfo,false) then
|
if GetLocalTimezone(epoch,true,lTZInfo) then
|
||||||
inc(Epoch,lTZInfo.seconds)
|
inc(Epoch,lTZInfo.seconds)
|
||||||
else { fallback }
|
else { fallback }
|
||||||
{$endif}
|
{$endif}
|
||||||
inc(Epoch,TZInfo.seconds);
|
inc(Epoch,lseconds);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
EpochToUniversal(epoch,year,month,day,hour,minute,second);
|
EpochToUniversal(epoch,year,month,day,hour,minute,second);
|
||||||
@ -278,19 +343,22 @@ Function LocalToEpoch(year,month,day,hour,minute,second:Word):Int64;
|
|||||||
Var
|
Var
|
||||||
lTZInfo: TTZInfo;
|
lTZInfo: TTZInfo;
|
||||||
UniversalEpoch: Int64;
|
UniversalEpoch: Int64;
|
||||||
|
lseconds: LongInt;
|
||||||
Begin
|
Begin
|
||||||
UniversalEpoch:=UniversalToEpoch(year,month,day,hour,minute,second);
|
UniversalEpoch:=UniversalToEpoch(year,month,day,hour,minute,second);
|
||||||
{ check if time is in current global Tzinfo }
|
{ check if time is in current global Tzinfo }
|
||||||
if (Tzinfo.validsince<UniversalEpoch-Tzinfo.seconds) and (UniversalEpoch-Tzinfo.seconds<Tzinfo.validuntil) then
|
lTZInfo:=TZInfo;
|
||||||
LocalToEpoch:=UniversalEpoch-TZInfo.seconds
|
lseconds:=lTZInfo.seconds;
|
||||||
|
if (lTZInfo.validsince<=UniversalEpoch-lTZInfo.seconds) and (UniversalEpoch-lTZInfo.seconds<lTZInfo.validuntil) then
|
||||||
|
LocalToEpoch:=UniversalEpoch-lseconds
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
{$if declared(GetLocalTimezone)}
|
{$if declared(GetLocalTimezone)}
|
||||||
if GetLocalTimezone(UniversalEpoch,false,lTZInfo,false) then
|
if GetLocalTimezone(UniversalEpoch,false,lTZInfo) then
|
||||||
LocalToEpoch:=UniversalEpoch-lTZInfo.seconds
|
LocalToEpoch:=UniversalEpoch-lTZInfo.seconds
|
||||||
else { fallback }
|
else { fallback }
|
||||||
{$endif}
|
{$endif}
|
||||||
LocalToEpoch:=UniversalEpoch-TZInfo.seconds
|
LocalToEpoch:=UniversalEpoch-lseconds;
|
||||||
end;
|
end;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
@ -319,20 +387,6 @@ Begin
|
|||||||
GregorianToJulian:=((((Month*153)+2) div 5)+Day)+D2+XYear+Century;
|
GregorianToJulian:=((((Month*153)+2) div 5)+Day)+D2+XYear+Century;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Procedure RefreshTZInfoIfNeeded;
|
|
||||||
{$if declared(ReReadLocalTime)}
|
|
||||||
var
|
|
||||||
curtime: time_t;
|
|
||||||
begin
|
|
||||||
curtime:=fptime;
|
|
||||||
if ((curtime<Tzinfo.validsince+Tzinfo.seconds) or (curtime>Tzinfo.validuntil+Tzinfo.seconds)) then
|
|
||||||
GetLocalTimezone(fptime,false);
|
|
||||||
end;
|
|
||||||
{$else}
|
|
||||||
begin
|
|
||||||
end;
|
|
||||||
{$endif}
|
|
||||||
|
|
||||||
{******************************************************************************
|
{******************************************************************************
|
||||||
Process related calls
|
Process related calls
|
||||||
******************************************************************************}
|
******************************************************************************}
|
||||||
@ -1408,7 +1462,18 @@ end;
|
|||||||
{$I unixandroid.inc}
|
{$I unixandroid.inc}
|
||||||
{$endif android}
|
{$endif android}
|
||||||
|
|
||||||
|
{$if declared(UseTZThreading)}
|
||||||
|
procedure InitTZThreading;
|
||||||
|
begin
|
||||||
|
UseTZThreading:=True;
|
||||||
|
InitCriticalSection(TZInfoCS);
|
||||||
|
end;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
Initialization
|
Initialization
|
||||||
|
{$if declared(UseTZThreading)}
|
||||||
|
RegisterLazyInitThreadingProc(@InitTZThreading);
|
||||||
|
{$endif}
|
||||||
{$IFNDEF DONT_READ_TIMEZONE}
|
{$IFNDEF DONT_READ_TIMEZONE}
|
||||||
InitLocalTime;
|
InitLocalTime;
|
||||||
{$endif}
|
{$endif}
|
||||||
@ -1420,4 +1485,8 @@ finalization
|
|||||||
{$IFNDEF DONT_READ_TIMEZONE}
|
{$IFNDEF DONT_READ_TIMEZONE}
|
||||||
DoneLocalTime;
|
DoneLocalTime;
|
||||||
{$endif}
|
{$endif}
|
||||||
|
{$if declared(UseTZThreading)}
|
||||||
|
if UseTZThreading then
|
||||||
|
DoneCriticalSection(TZInfoCS);
|
||||||
|
{$endif}
|
||||||
End.
|
End.
|
||||||
|
Loading…
Reference in New Issue
Block a user