2
0

timezone.inc 6.7 KB

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