timezone.inc 6.7 KB

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