|
@@ -6,7 +6,9 @@
|
|
type
|
|
type
|
|
|
|
|
|
ttzhead=packed record
|
|
ttzhead=packed record
|
|
- tzh_reserved : array[0..19] of byte;
|
|
|
|
|
|
+ tzh_identifier : array[0..3] of AnsiChar;
|
|
|
|
+ tzh_version : AnsiChar;
|
|
|
|
+ tzh_reserved : array[0..14] of byte;
|
|
tzh_ttisgmtcnt,
|
|
tzh_ttisgmtcnt,
|
|
tzh_ttisstdcnt,
|
|
tzh_ttisstdcnt,
|
|
tzh_leapcnt,
|
|
tzh_leapcnt,
|
|
@@ -26,8 +28,8 @@ type
|
|
|
|
|
|
pleap=^tleap;
|
|
pleap=^tleap;
|
|
tleap=record
|
|
tleap=record
|
|
- transition : longint;
|
|
|
|
- change : longint;
|
|
|
|
|
|
+ transition : int64;
|
|
|
|
+ change : int64;
|
|
end;
|
|
end;
|
|
|
|
|
|
var
|
|
var
|
|
@@ -35,19 +37,20 @@ var
|
|
num_leaps,
|
|
num_leaps,
|
|
num_types : longint;
|
|
num_types : longint;
|
|
|
|
|
|
- transitions : plongint = nil;
|
|
|
|
|
|
+ transitions : PInt64 = nil;
|
|
type_idxs : pbyte = Nil;
|
|
type_idxs : pbyte = Nil;
|
|
types : pttinfo = Nil;
|
|
types : pttinfo = Nil;
|
|
zone_names : pchar = Nil;
|
|
zone_names : pchar = Nil;
|
|
leaps : pleap = Nil;
|
|
leaps : pleap = Nil;
|
|
|
|
|
|
-function find_transition(timer:longint;timerIsUTC:Boolean;var trans_start,trans_end:longint):pttinfo;
|
|
|
|
|
|
+function find_transition(timer:int64;timerIsUTC:Boolean;var trans_start,trans_end:int64):pttinfo;
|
|
var
|
|
var
|
|
i,L,R,CompareRes : longint;
|
|
i,L,R,CompareRes : longint;
|
|
|
|
+ found : boolean;
|
|
|
|
|
|
function DoCompare: longint;
|
|
function DoCompare: longint;
|
|
var
|
|
var
|
|
- timerUTC: LongInt;
|
|
|
|
|
|
+ timerUTC: int64;
|
|
begin
|
|
begin
|
|
if not timerIsUTC then
|
|
if not timerIsUTC then
|
|
timerUTC:=timer-types[type_idxs[i-1]].offset
|
|
timerUTC:=timer-types[type_idxs[i-1]].offset
|
|
@@ -78,7 +81,8 @@ begin
|
|
// Use binary search.
|
|
// Use binary search.
|
|
L := 1;
|
|
L := 1;
|
|
R := num_transitions-1;
|
|
R := num_transitions-1;
|
|
- while (L<=R) do
|
|
|
|
|
|
+ found := false;
|
|
|
|
+ while not found and (L<=R) do
|
|
begin
|
|
begin
|
|
I := L + (R - L) div 2;
|
|
I := L + (R - L) div 2;
|
|
CompareRes := DoCompare;
|
|
CompareRes := DoCompare;
|
|
@@ -87,10 +91,11 @@ begin
|
|
else begin
|
|
else begin
|
|
R := I-1;
|
|
R := I-1;
|
|
if (CompareRes=0) then
|
|
if (CompareRes=0) then
|
|
- L:=I; // break cycle
|
|
|
|
|
|
+ found:=true; // break cycle
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
|
|
+ if not found then
|
|
|
|
+ Exit(nil);
|
|
trans_start:=transitions[i-1];
|
|
trans_start:=transitions[i-1];
|
|
trans_end:=transitions[i];
|
|
trans_end:=transitions[i];
|
|
i:=type_idxs[i-1];
|
|
i:=type_idxs[i-1];
|
|
@@ -148,11 +153,10 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function GetLocalTimezone(timer:cint;timerIsUTC:Boolean;var ATZInfo:TTZInfo):Boolean;
|
|
|
|
|
|
+function GetLocalTimezone(timer:int64;timerIsUTC:Boolean;var ATZInfo:TTZInfo):Boolean;
|
|
var
|
|
var
|
|
info: pttinfo;
|
|
info: pttinfo;
|
|
- trans_start,trans_end: longint;
|
|
|
|
- timerUTC: cint;
|
|
|
|
|
|
+ trans_start,trans_end,timerUTC: int64;
|
|
begin
|
|
begin
|
|
{ check if time is in current global Tzinfo }
|
|
{ check if time is in current global Tzinfo }
|
|
ATZInfo:=CurrentTZinfo[InterlockedExchangeAdd(CurrentTZindex, 0)];
|
|
ATZInfo:=CurrentTZinfo[InterlockedExchangeAdd(CurrentTZindex, 0)];
|
|
@@ -171,11 +175,10 @@ begin
|
|
UnlockTZInfo;
|
|
UnlockTZInfo;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function GetLocalTimezone(timer:cint;timerIsUTC:Boolean;var ATZInfo:TTZInfo;var ATZInfoEx:TTZInfoEx):Boolean;
|
|
|
|
|
|
+function GetLocalTimezone(timer:int64;timerIsUTC:Boolean;var ATZInfo:TTZInfo;var ATZInfoEx:TTZInfoEx):Boolean;
|
|
var
|
|
var
|
|
info: pttinfo;
|
|
info: pttinfo;
|
|
- trans_start,trans_end: longint;
|
|
|
|
- timerUTC: cint;
|
|
|
|
|
|
+ trans_start,trans_end,timerUTC: int64;
|
|
begin
|
|
begin
|
|
{ check if time is in current global Tzinfo }
|
|
{ check if time is in current global Tzinfo }
|
|
ATZInfo:=CurrentTZinfo[InterlockedExchangeAdd(CurrentTZindex, 0)];
|
|
ATZInfo:=CurrentTZinfo[InterlockedExchangeAdd(CurrentTZindex, 0)];
|
|
@@ -228,21 +231,22 @@ end;
|
|
|
|
|
|
function ReadTimezoneFile(fn:string) : Boolean;
|
|
function ReadTimezoneFile(fn:string) : Boolean;
|
|
|
|
|
|
- procedure decode(var l:longint);
|
|
|
|
- var
|
|
|
|
- k : longint;
|
|
|
|
- p : pbyte;
|
|
|
|
|
|
+ function decode(const l:longint):longint;
|
|
begin
|
|
begin
|
|
- p:=pbyte(@l);
|
|
|
|
- if (p[0] and (1 shl 7))<>0 then
|
|
|
|
- k:=not 0
|
|
|
|
- else
|
|
|
|
- k:=0;
|
|
|
|
- k:=(k shl 8) or p[0];
|
|
|
|
- k:=(k shl 8) or p[1];
|
|
|
|
- k:=(k shl 8) or p[2];
|
|
|
|
- k:=(k shl 8) or p[3];
|
|
|
|
- l:=k;
|
|
|
|
|
|
+ {$IFDEF ENDIAN_LITTLE}
|
|
|
|
+ decode:=SwapEndian(l);
|
|
|
|
+ {$ELSE}
|
|
|
|
+ decode:=l;
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ function decode(const l:int64):int64;
|
|
|
|
+ begin
|
|
|
|
+ {$IFDEF ENDIAN_LITTLE}
|
|
|
|
+ decode:=SwapEndian(l);
|
|
|
|
+ {$ELSE}
|
|
|
|
+ decode:=l;
|
|
|
|
+ {$ENDIF}
|
|
end;
|
|
end;
|
|
|
|
|
|
const
|
|
const
|
|
@@ -251,6 +255,7 @@ var
|
|
buf : array[0..bufsize-1] of byte;
|
|
buf : array[0..bufsize-1] of byte;
|
|
bufptr : pbyte;
|
|
bufptr : pbyte;
|
|
f : longint;
|
|
f : longint;
|
|
|
|
+ tzhead : ttzhead;
|
|
|
|
|
|
procedure readfilebuf;
|
|
procedure readfilebuf;
|
|
begin
|
|
begin
|
|
@@ -266,7 +271,7 @@ var
|
|
inc(bufptr);
|
|
inc(bufptr);
|
|
end;
|
|
end;
|
|
|
|
|
|
- function readbuf(var dest; count: integer): integer;
|
|
|
|
|
|
+ function readbuf(dest:pointer; count: integer): integer;
|
|
var
|
|
var
|
|
numbytes: integer;
|
|
numbytes: integer;
|
|
begin
|
|
begin
|
|
@@ -277,10 +282,12 @@ var
|
|
numbytes := count;
|
|
numbytes := count;
|
|
if numbytes > 0 then
|
|
if numbytes > 0 then
|
|
begin
|
|
begin
|
|
- move(bufptr^, dest, numbytes);
|
|
|
|
|
|
+ if assigned(dest) then
|
|
|
|
+ move(bufptr^, dest^, numbytes);
|
|
inc(bufptr, numbytes);
|
|
inc(bufptr, numbytes);
|
|
dec(count, numbytes);
|
|
dec(count, numbytes);
|
|
inc(readbuf, numbytes);
|
|
inc(readbuf, numbytes);
|
|
|
|
+ inc(dest, numbytes);
|
|
end;
|
|
end;
|
|
if count > 0 then
|
|
if count > 0 then
|
|
readfilebuf
|
|
readfilebuf
|
|
@@ -289,82 +296,134 @@ var
|
|
until false;
|
|
until false;
|
|
end;
|
|
end;
|
|
|
|
|
|
-var
|
|
|
|
- tzdir : shortstring;
|
|
|
|
- tzhead : ttzhead;
|
|
|
|
- i : longint;
|
|
|
|
- chars : longint;
|
|
|
|
-begin
|
|
|
|
- LockTZInfo;
|
|
|
|
- if fn='' then
|
|
|
|
- fn:='localtime';
|
|
|
|
- if fn[1]<>'/' then
|
|
|
|
- fn:=TimeZoneDir+fn;
|
|
|
|
- f:=fpopen(fn,Open_RdOnly);
|
|
|
|
- if f<0 then
|
|
|
|
|
|
+ function readheader: boolean;
|
|
|
|
+ var
|
|
|
|
+ i : longint;
|
|
begin
|
|
begin
|
|
- UnlockTZInfo;
|
|
|
|
- exit(False);
|
|
|
|
|
|
+ i:=readbuf(@tzhead,sizeof(tzhead));
|
|
|
|
+ if i<>sizeof(tzhead) then
|
|
|
|
+ exit(False);
|
|
|
|
+ tzhead.tzh_timecnt:=decode(tzhead.tzh_timecnt);
|
|
|
|
+ tzhead.tzh_typecnt:=decode(tzhead.tzh_typecnt);
|
|
|
|
+ tzhead.tzh_charcnt:=decode(tzhead.tzh_charcnt);
|
|
|
|
+ tzhead.tzh_leapcnt:=decode(tzhead.tzh_leapcnt);
|
|
|
|
+ tzhead.tzh_ttisstdcnt:=decode(tzhead.tzh_ttisstdcnt);
|
|
|
|
+ tzhead.tzh_ttisgmtcnt:=decode(tzhead.tzh_ttisgmtcnt);
|
|
|
|
+ readheader:=(tzhead.tzh_identifier[0]='T') and (tzhead.tzh_identifier[1]='Z')
|
|
|
|
+ and (tzhead.tzh_identifier[2]='i') and (tzhead.tzh_identifier[3]='f');
|
|
end;
|
|
end;
|
|
- bufptr := @buf[bufsize-1]+1;
|
|
|
|
- i:=readbuf(tzhead,sizeof(tzhead));
|
|
|
|
- if i<>sizeof(tzhead) then
|
|
|
|
|
|
+
|
|
|
|
+ procedure AllocFields;
|
|
begin
|
|
begin
|
|
- UnlockTZInfo;
|
|
|
|
- exit(False);
|
|
|
|
|
|
+ num_transitions:=tzhead.tzh_timecnt;
|
|
|
|
+ num_types:=tzhead.tzh_typecnt;
|
|
|
|
+ num_leaps:=tzhead.tzh_leapcnt;
|
|
|
|
+ reallocmem(transitions,num_transitions*sizeof(int64));
|
|
|
|
+ reallocmem(type_idxs,num_transitions);
|
|
|
|
+ reallocmem(types,num_types*sizeof(tttinfo));
|
|
|
|
+ reallocmem(zone_names,tzhead.tzh_charcnt);
|
|
|
|
+ reallocmem(leaps,num_leaps*sizeof(tleap));
|
|
end;
|
|
end;
|
|
- decode(tzhead.tzh_timecnt);
|
|
|
|
- decode(tzhead.tzh_typecnt);
|
|
|
|
- decode(tzhead.tzh_charcnt);
|
|
|
|
- decode(tzhead.tzh_leapcnt);
|
|
|
|
- decode(tzhead.tzh_ttisstdcnt);
|
|
|
|
- decode(tzhead.tzh_ttisgmtcnt);
|
|
|
|
-
|
|
|
|
- num_transitions:=tzhead.tzh_timecnt;
|
|
|
|
- num_types:=tzhead.tzh_typecnt;
|
|
|
|
- chars:=tzhead.tzh_charcnt;
|
|
|
|
- num_leaps:=tzhead.tzh_leapcnt;
|
|
|
|
- reallocmem(transitions,num_transitions*sizeof(longint));
|
|
|
|
- reallocmem(type_idxs,num_transitions);
|
|
|
|
- reallocmem(types,num_types*sizeof(tttinfo));
|
|
|
|
- reallocmem(zone_names,chars);
|
|
|
|
- reallocmem(leaps,num_leaps*sizeof(tleap));
|
|
|
|
-
|
|
|
|
- readbuf(transitions^,num_transitions*4);
|
|
|
|
- readbuf(type_idxs^,num_transitions);
|
|
|
|
-
|
|
|
|
- for i:=0 to num_transitions-1 do
|
|
|
|
- decode(transitions[i]);
|
|
|
|
-
|
|
|
|
- for i:=0 to num_types-1 do
|
|
|
|
- begin
|
|
|
|
- readbuf(types[i].offset,4);
|
|
|
|
- readbuf(types[i].isdst,1);
|
|
|
|
- readbuf(types[i].idx,1);
|
|
|
|
- decode(types[i].offset);
|
|
|
|
- types[i].isstd:=0;
|
|
|
|
- types[i].isgmt:=0;
|
|
|
|
- end;
|
|
|
|
|
|
|
|
- readbuf(zone_names^,chars);
|
|
|
|
|
|
+ function readdata: boolean;
|
|
|
|
+ var
|
|
|
|
+ i : longint;
|
|
|
|
+ longval: longint;
|
|
|
|
+ version: longint;
|
|
|
|
+ begin
|
|
|
|
+ if tzhead.tzh_version='2' then
|
|
|
|
+ begin
|
|
|
|
+ version:=2;
|
|
|
|
+ // skip version 0
|
|
|
|
+ readbuf(nil,
|
|
|
|
+ tzhead.tzh_timecnt*4 // transitions
|
|
|
|
+ +tzhead.tzh_timecnt // type_idxs
|
|
|
|
+ +tzhead.tzh_typecnt*6 // types
|
|
|
|
+ +tzhead.tzh_charcnt // zone_names
|
|
|
|
+ +tzhead.tzh_leapcnt*8 // leaps
|
|
|
|
+ +tzhead.tzh_ttisstdcnt // isstd
|
|
|
|
+ +tzhead.tzh_ttisgmtcnt // isgmt
|
|
|
|
+ );
|
|
|
|
+ readheader; // read version 2 header
|
|
|
|
+ if tzhead.tzh_version<>'2' then
|
|
|
|
+ Exit(False);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ version:=0;
|
|
|
|
|
|
- for i:=0 to num_leaps-1 do
|
|
|
|
- begin
|
|
|
|
- readbuf(leaps[i].transition,4);
|
|
|
|
- readbuf(leaps[i].change,4);
|
|
|
|
- decode(leaps[i].transition);
|
|
|
|
- decode(leaps[i].change);
|
|
|
|
- end;
|
|
|
|
|
|
+ AllocFields;
|
|
|
|
+
|
|
|
|
+ if version=2 then
|
|
|
|
+ begin // read 64bit values
|
|
|
|
+ readbuf(transitions,num_transitions*sizeof(int64));
|
|
|
|
+ for i:=0 to num_transitions-1 do
|
|
|
|
+ transitions[i]:=decode(transitions[i]);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin // read 32bit values
|
|
|
|
+ for i:=0 to num_transitions-1 do
|
|
|
|
+ begin
|
|
|
|
+ readbuf(@longval,sizeof(longval));
|
|
|
|
+ transitions[i]:=decode(longval);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ readbuf(type_idxs,num_transitions);
|
|
|
|
+
|
|
|
|
+ for i:=0 to num_types-1 do
|
|
|
|
+ begin
|
|
|
|
+ readbuf(@types[i].offset,sizeof(LongInt));
|
|
|
|
+ types[i].offset:=decode(types[i].offset);
|
|
|
|
+ readbuf(@types[i].isdst,1);
|
|
|
|
+ readbuf(@types[i].idx,1);
|
|
|
|
+ types[i].isstd:=0;
|
|
|
|
+ types[i].isgmt:=0;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ readbuf(zone_names,tzhead.tzh_charcnt);
|
|
|
|
+
|
|
|
|
+ if version=2 then
|
|
|
|
+ begin // read 64bit values
|
|
|
|
+ for i:=0 to num_leaps-1 do
|
|
|
|
+ begin
|
|
|
|
+ readbuf(@leaps[i].transition,sizeof(int64));
|
|
|
|
+ readbuf(@leaps[i].change,sizeof(int64));
|
|
|
|
+ leaps[i].transition:=decode(leaps[i].transition);
|
|
|
|
+ leaps[i].change:=decode(leaps[i].change);
|
|
|
|
+ end;
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ for i:=0 to num_leaps-1 do
|
|
|
|
+ begin
|
|
|
|
+ readbuf(@longval,sizeof(longval));
|
|
|
|
+ leaps[i].transition:=decode(longval);
|
|
|
|
+ readbuf(@longval,sizeof(longval));
|
|
|
|
+ leaps[i].change:=decode(longval);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
|
|
- for i:=0 to tzhead.tzh_ttisstdcnt-1 do
|
|
|
|
- types[i].isstd:=byte(readbufbyte<>0);
|
|
|
|
|
|
+ for i:=0 to tzhead.tzh_ttisstdcnt-1 do
|
|
|
|
+ types[i].isstd:=byte(readbufbyte<>0);
|
|
|
|
|
|
- for i:=0 to tzhead.tzh_ttisgmtcnt-1 do
|
|
|
|
- types[i].isgmt:=byte(readbufbyte<>0);
|
|
|
|
|
|
+ for i:=0 to tzhead.tzh_ttisgmtcnt-1 do
|
|
|
|
+ types[i].isgmt:=byte(readbufbyte<>0);
|
|
|
|
|
|
- fpclose(f);
|
|
|
|
- ReadTimezoneFile:=True;
|
|
|
|
|
|
+ readdata:=true;
|
|
|
|
+ end;
|
|
|
|
+begin
|
|
|
|
+ if fn='' then
|
|
|
|
+ fn:='localtime';
|
|
|
|
+ if fn[1]<>'/' then
|
|
|
|
+ fn:='/usr/share/zoneinfo/'+fn;
|
|
|
|
+ f:=fpopen(fn,Open_RdOnly);
|
|
|
|
+ if f<0 then
|
|
|
|
+ exit(False);
|
|
|
|
+ bufptr := @buf[bufsize-1]+1;
|
|
|
|
+ tzhead:=default(ttzhead);
|
|
|
|
+ LockTZInfo;
|
|
|
|
+ ReadTimezoneFile:=(readheader() and readdata());
|
|
UnlockTZInfo;
|
|
UnlockTZInfo;
|
|
|
|
+ fpclose(f);
|
|
end;
|
|
end;
|
|
|
|
|
|
Const
|
|
Const
|
|
@@ -398,9 +457,9 @@ begin
|
|
Delete(fn,1,1);
|
|
Delete(fn,1,1);
|
|
if (fn<>'') then
|
|
if (fn<>'') then
|
|
begin
|
|
begin
|
|
- if (fn[1]<>'/') then
|
|
|
|
|
|
+ if (fn[1]<>'/') then
|
|
Exit(TimeZoneDir+fn);
|
|
Exit(TimeZoneDir+fn);
|
|
- Exit(fn);
|
|
|
|
|
|
+ Exit(fn);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
if (fn='') then
|
|
if (fn='') then
|