timezone.inc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. {
  2. Support for timezone info in /usr/share/timezone
  3. }
  4. type
  5. ttzhead=packed record
  6. tzh_reserved : array[0..19] of byte;
  7. tzh_ttisgmtcnt,
  8. tzh_ttisstdcnt,
  9. tzh_leapcnt,
  10. tzh_timecnt,
  11. tzh_typecnt,
  12. tzh_charcnt : longint;
  13. end;
  14. pttinfo=^tttinfo;
  15. tttinfo=packed record
  16. offset : longint;
  17. isdst : boolean;
  18. idx : byte;
  19. isstd : byte;
  20. isgmt : byte;
  21. end;
  22. pleap=^tleap;
  23. tleap=record
  24. transition : longint;
  25. change : longint;
  26. end;
  27. var
  28. num_transitions,
  29. num_leaps,
  30. num_types : longint;
  31. transitions : plongint;
  32. type_idxs : pbyte;
  33. types : pttinfo;
  34. zone_names : pchar;
  35. leaps : pleap;
  36. function find_transition(timer:longint):pttinfo;
  37. var
  38. i : longint;
  39. begin
  40. if (num_transitions=0) or (timer<transitions[0]) then
  41. begin
  42. i:=0;
  43. while (i<num_types) and (types[i].isdst) do
  44. inc(i);
  45. if (i=num_types) then
  46. i:=0;
  47. end
  48. else
  49. begin
  50. for i:=1 to num_transitions do
  51. if (timer<transitions[i]) then
  52. break;
  53. i:=type_idxs[i-1];
  54. end;
  55. find_transition:=@types[i];
  56. end;
  57. procedure GetLocalTimezone(timer:longint;var leap_correct,leap_hit:longint);
  58. var
  59. info : pttinfo;
  60. i : longint;
  61. begin
  62. { reset }
  63. TZDaylight:=false;
  64. TZSeconds:=0;
  65. TZName[false]:=nil;
  66. TZName[true]:=nil;
  67. leap_correct:=0;
  68. leap_hit:=0;
  69. { get info }
  70. info:=find_transition(timer);
  71. if not assigned(info) then
  72. exit;
  73. TZDaylight:=info^.isdst;
  74. TZSeconds:=info^.offset;
  75. i:=0;
  76. while (i<num_types) do
  77. begin
  78. tzname[types[i].isdst]:=@zone_names[types[i].idx];
  79. inc(i);
  80. end;
  81. tzname[info^.isdst]:=@zone_names[info^.idx];
  82. i:=num_leaps;
  83. repeat
  84. if i=0 then
  85. exit;
  86. dec(i);
  87. until (timer>leaps[i].transition);
  88. leap_correct:=leaps[i].change;
  89. if (timer=leaps[i].transition) and
  90. (((i=0) and (leaps[i].change>0)) or
  91. (leaps[i].change>leaps[i-1].change)) then
  92. begin
  93. leap_hit:=1;
  94. while (i>0) and
  95. (leaps[i].transition=leaps[i-1].transition+1) and
  96. (leaps[i].change=leaps[i-1].change+1) do
  97. begin
  98. inc(leap_hit);
  99. dec(i);
  100. end;
  101. end;
  102. end;
  103. procedure GetLocalTimezone(timer:longint);
  104. var
  105. lc,lh : longint;
  106. begin
  107. GetLocalTimezone(timer,lc,lh);
  108. end;
  109. procedure ReadTimezoneFile(fn:shortstring);
  110. procedure decode(var l:longint);
  111. var
  112. k : longint;
  113. p : pbyte;
  114. begin
  115. p:=pbyte(@l);
  116. if (p[0] and (1 shl 7))<>0 then
  117. k:=not 0
  118. else
  119. k:=0;
  120. k:=(k shl 8) or p[0];
  121. k:=(k shl 8) or p[1];
  122. k:=(k shl 8) or p[2];
  123. k:=(k shl 8) or p[3];
  124. l:=k;
  125. end;
  126. var
  127. f : longint;
  128. tzdir : shortstring;
  129. tzhead : ttzhead;
  130. i : longint;
  131. chars : longint;
  132. buf : pbyte;
  133. begin
  134. if fn='' then
  135. fn:='localtime';
  136. if fn[1]<>'/' then
  137. begin
  138. tzdir:=fpgetenv('TZDIR');
  139. if tzdir='' then
  140. tzdir:='/usr/share/zoneinfo';
  141. if tzdir[length(tzdir)]<>'/' then
  142. tzdir:=tzdir+'/';
  143. fn:=tzdir+fn;
  144. end;
  145. f:=fpopen(fn,Open_RdOnly);
  146. if f<0 then
  147. exit;
  148. i:=fpread(f,tzhead,sizeof(tzhead));
  149. if i<>sizeof(tzhead) then
  150. exit;
  151. decode(tzhead.tzh_timecnt);
  152. decode(tzhead.tzh_typecnt);
  153. decode(tzhead.tzh_charcnt);
  154. decode(tzhead.tzh_leapcnt);
  155. decode(tzhead.tzh_ttisstdcnt);
  156. decode(tzhead.tzh_ttisgmtcnt);
  157. num_transitions:=tzhead.tzh_timecnt;
  158. num_types:=tzhead.tzh_typecnt;
  159. chars:=tzhead.tzh_charcnt;
  160. reallocmem(transitions,num_transitions*sizeof(longint));
  161. reallocmem(type_idxs,num_transitions);
  162. reallocmem(types,num_types*sizeof(tttinfo));
  163. reallocmem(zone_names,chars);
  164. reallocmem(leaps,num_leaps*sizeof(tleap));
  165. fpread(f,transitions^,num_transitions*4);
  166. fpread(f,type_idxs^,num_transitions);
  167. for i:=0 to num_transitions-1 do
  168. decode(transitions[i]);
  169. for i:=0 to num_types-1 do
  170. begin
  171. fpread(f,types[i].offset,4);
  172. fpread(f,types[i].isdst,1);
  173. fpread(f,types[i].idx,1);
  174. decode(types[i].offset);
  175. types[i].isstd:=0;
  176. types[i].isgmt:=0;
  177. end;
  178. fpread(f,zone_names^,chars);
  179. for i:=0 to num_leaps-1 do
  180. begin
  181. fpread(f,leaps[i].transition,4);
  182. fpread(f,leaps[i].change,4);
  183. decode(leaps[i].transition);
  184. decode(leaps[i].change);
  185. end;
  186. getmem(buf,tzhead.tzh_ttisstdcnt);
  187. fpread(f,buf^,tzhead.tzh_ttisstdcnt);
  188. for i:=0 to tzhead.tzh_ttisstdcnt-1 do
  189. types[i].isstd:=byte(buf[i]<>0);
  190. freemem(buf);
  191. getmem(buf,tzhead.tzh_ttisgmtcnt);
  192. fpread(f,buf^,tzhead.tzh_ttisgmtcnt);
  193. for i:=0 to tzhead.tzh_ttisgmtcnt-1 do
  194. types[i].isgmt:=byte(buf[i]<>0);
  195. freemem(buf);
  196. fpclose(f);
  197. end;
  198. Const
  199. // Debian system; contains location of timezone file.
  200. TimeZoneLocationFile = '/etc/timezone';
  201. // SuSE has link in /usr/lib/zoneinfo/localtime to /etc/localtime
  202. // RedHat uses /etc/localtime
  203. TimeZoneFile = '/etc/localtime'; // POSIX
  204. AltTimeZoneFile = '/usr/lib/zoneinfo/localtime'; // Other
  205. {$ifdef BSD}
  206. BSDTimeZonefile = '/usr/share/zoneinfo'; // BSD usually is POSIX
  207. // compliant though
  208. {$ENDIF}
  209. function GetTimezoneFile:shortstring;
  210. var
  211. f,len : longint;
  212. s : shortstring;
  213. info : stat;
  214. begin
  215. GetTimezoneFile:='';
  216. f:=fpopen(TimeZoneLocationFile,Open_RdOnly);
  217. if f>0 then
  218. begin
  219. len:=fpread(f,s[1],high(s));
  220. s[0]:=chr(len);
  221. len:=pos(#10,s);
  222. if len<>0 then
  223. s[0]:=chr(len-1);
  224. fpclose(f);
  225. GetTimezoneFile:=s;
  226. end
  227. // Try SuSE
  228. else if fpstat(TimeZoneFile,{$ifdef oldlinuxstat}baseunix.stat(info){$else}info{$endif})>=0 then
  229. GetTimeZoneFile:=TimeZoneFile
  230. // Try RedHat
  231. else If fpstat(AltTimeZoneFile,{$ifdef oldlinuxstat}baseunix.stat(info){$else}info{$endif})>=0 then
  232. GetTimeZoneFile:=AltTimeZoneFile
  233. {$ifdef BSD}
  234. // else
  235. // If fpstat(BSDTimeZoneFile,{$ifdef oldlinuxstat}baseunix.stat(info){$else}info{$endif})>=0 then
  236. // GetTimeZoneFile:=BSDTimeZoneFile
  237. {$ENDIF}
  238. end;
  239. procedure InitLocalTime;
  240. begin
  241. ReadTimezoneFile(GetTimezoneFile);
  242. GetLocalTimezone(fptime);
  243. end;
  244. procedure DoneLocalTime;
  245. begin
  246. if assigned(transitions) then
  247. freemem(transitions);
  248. if assigned(type_idxs) then
  249. freemem(type_idxs);
  250. if assigned(types) then
  251. freemem(types);
  252. if assigned(zone_names) then
  253. freemem(zone_names);
  254. if assigned(leaps) then
  255. freemem(leaps);
  256. num_transitions:=0;
  257. num_leaps:=0;
  258. num_types:=0;
  259. end;