dati.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. {
  2. *********************************************************************
  3. $Id$
  4. Copyright (C) 1997, 1998 Gertjan Schouten
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. *********************************************************************
  17. System Utilities For Free Pascal
  18. }
  19. {==============================================================================}
  20. { internal functions }
  21. {==============================================================================}
  22. const
  23. DayTable: array[Boolean, 1..12] of longint =
  24. ((0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334),
  25. (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335));
  26. Procedure GetLocalTime(var SystemTime: TSystemTime);
  27. {$IFDEF GO32V2}
  28. var Regs: Registers;
  29. begin
  30. Regs.ah := $2C;
  31. RealIntr($21, Regs);
  32. SystemTime.Hour := Regs.Ch;
  33. SystemTime.Minute := Regs.Cl;
  34. SystemTime.Second := Regs.Dh;
  35. SystemTime.MilliSecond := Regs.Dl;
  36. Regs.ah := $2A;
  37. RealIntr($21, Regs);
  38. SystemTime.Year := Regs.Cx;
  39. SystemTime.Month := Regs.Dh;
  40. SystemTime.Day := Regs.Dl;
  41. end ;
  42. {$ELSE}
  43. {$IFDEF LINUX}
  44. begin
  45. linux.GetTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second);
  46. linux.GetDate(SystemTime.Year, SystemTime.Month, SystemTime.Day);
  47. SystemTime.MilliSecond := 0;
  48. end ;
  49. {$ELSE}
  50. begin
  51. end ;
  52. {$ENDIF}
  53. {$ENDIF}
  54. function DoEncodeDate(Year, Month, Day: Word): longint;
  55. var i: longint;
  56. begin
  57. Result := 0;
  58. if (Year >= 1) and (Year <= 9999) and (Month >= 1) and (Month <= 12) and
  59. (Day >= 1) and (Day <= 31) then begin
  60. Day := Day + DayTable[IsLeapYear(Year), Month] - 1;
  61. I := Year - 1;
  62. result := I * 365 + I div 4 - I div 100 + I div 400 + Day - DateDelta;
  63. end ;
  64. end ;
  65. function DoEncodeTime(Hour, Minute, Second, MilliSecond: word): longint;
  66. begin
  67. result := (Hour * 3600000 + Minute * 60000 + Second * 1000 + MilliSecond) { div MSecsPerDay} ;
  68. end ;
  69. {==============================================================================}
  70. { Public functions }
  71. {==============================================================================}
  72. { DateTimeToTimeStamp converts DateTime to a TTimeStamp }
  73. function DateTimeToTimeStamp(DateTime: TDateTime): TTimeStamp;
  74. begin
  75. result.Time := Trunc(Frac(DateTime) * MSecsPerDay);
  76. result.Date := 1 + DateDelta + Trunc(Int(DateTime));
  77. end ;
  78. { TimeStampToDateTime converts TimeStamp to a TDateTime value }
  79. function TimeStampToDateTime(const TimeStamp: TTimeStamp): TDateTime;
  80. begin
  81. result := (TimeStamp.Date - DateDelta - 1) + (TimeStamp.Time / MSecsPerDay);
  82. end ;
  83. { MSecsToTimeStamp }
  84. function MSecsToTimeStamp(MSecs: comp): TTimeStamp;
  85. begin
  86. result.Time := Trunc(MSecs);
  87. result.Date := 0;
  88. end ;
  89. { TimeStampToMSecs }
  90. function TimeStampToMSecs(const TimeStamp: TTimeStamp): comp;
  91. begin
  92. result := TimeStamp.Time;
  93. end ;
  94. { EncodeDate packs three variables Year, Month and Day into a
  95. TDateTime value the result is the number of days since 12/30/1899 }
  96. function EncodeDate(Year, Month, Day: word): TDateTime;
  97. begin
  98. result := DoEncodeDate(Year, Month, Day);
  99. end ;
  100. { EncodeTime packs four variables Hour, Minute, Second and MilliSecond into
  101. a TDateTime value }
  102. function EncodeTime(Hour, Minute, Second, MilliSecond:word):TDateTime;
  103. begin
  104. Result := DoEncodeTime(hour, minute, second, millisecond) / MSecsPerDay;
  105. end ;
  106. { DecodeDate unpacks the value Date into three values:
  107. Year, Month and Day }
  108. procedure DecodeDate(Date: TDateTime; var Year, Month, Day: word);
  109. const
  110. D1 = 365; { number of days in 1 year }
  111. D4 = D1 * 4 + 1; { number of days in 4 years }
  112. D100 = D4 * 25 - 1; { number of days in 100 years }
  113. D400 = D100 * 4 + 1; { number of days in 400 years }
  114. var
  115. i:Longint;
  116. l:longint;
  117. ly:boolean;
  118. begin
  119. l := Trunc(Int(Date)) + DateDelta;
  120. year := 1 + 400 * (l div D400); l := (l mod D400);
  121. year := year + 100 * (l div D100);l := (l mod D100);
  122. year := year + 4 * (l div D4);l := (l mod D4);
  123. year := year + (l div D1);l := 1 + (l mod D1);
  124. month := 0;
  125. ly := IsLeapYear(Year);
  126. while (month < 12) and (l > DayTable[ly, month + 1]) do
  127. inc(month);
  128. day := l - DayTable[ly, month];
  129. end ;
  130. { DecodeTime unpacks Time into four values:
  131. Hour, Minute, Second and MilliSecond }
  132. procedure DecodeTime(Time: TDateTime; var Hour, Minute, Second, MilliSecond: word);
  133. var l:longint;
  134. begin
  135. l := Trunc(Frac(time) * MSecsPerDay);
  136. Hour := l div 3600000;l := l mod 3600000;
  137. Minute := l div 60000;l := l mod 60000;
  138. Second := l div 1000;l := l mod 1000;
  139. MilliSecond := l;
  140. end ;
  141. { DateTimeToSystemTime converts DateTime value to SystemTime }
  142. procedure DateTimeToSystemTime(DateTime: TDateTime; var SystemTime: TSystemTime);
  143. begin
  144. DecodeDate(DateTime, SystemTime.Year, SystemTime.Month, SystemTime.Day);
  145. DecodeTime(DateTime, SystemTime.Hour, SystemTime.Minute, SystemTime.Second, SystemTime.MilliSecond);
  146. end ;
  147. { SystemTimeToDateTime converts SystemTime to a TDateTime value }
  148. function SystemTimeToDateTime(const SystemTime: TSystemTime): TDateTime;
  149. begin
  150. result := DoEncodeDate(SystemTime.Year,
  151. SystemTime.Month,
  152. SystemTime.Day) +
  153. DoEncodeTime(SystemTime.Hour,
  154. SystemTime.Minute,
  155. SystemTime.Second,
  156. SystemTime.MilliSecond) / MSecsPerDay;
  157. end ;
  158. { DayOfWeek returns the Day of the week (sunday is day 1) }
  159. function DayOfWeek(DateTime: TDateTime): integer;
  160. begin
  161. Result := 1 + (Trunc(DateTime) mod 7);
  162. end ;
  163. { Date returns the current Date }
  164. function Date: TDateTime;
  165. var SystemTime: TSystemTime;
  166. begin
  167. GetLocalTime(SystemTime);
  168. result := DoEncodeDate(SystemTime.Year,
  169. SystemTime.Month,
  170. SystemTime.Day);
  171. end ;
  172. { Time returns the current Time }
  173. function Time: TDateTime;
  174. var SystemTime: TSystemTime;
  175. begin
  176. GetLocalTime(SystemTime);
  177. Result := DoEncodeTime(SystemTime.Hour,
  178. SystemTime.Minute,
  179. SystemTime.Second,
  180. SystemTime.MilliSecond) / MSecsPerDay;
  181. end ;
  182. { Now returns the current Date and Time }
  183. function Now: TDateTime;
  184. var SystemTime: TSystemTime;
  185. begin
  186. GetLocalTime(SystemTime);
  187. result := DoEncodeDate(SystemTime.Year,
  188. SystemTime.Month,
  189. SystemTime.Day) +
  190. DoEncodeTime(SystemTime.Hour,
  191. SystemTime.Minute,
  192. SystemTime.Second,
  193. SystemTime.MilliSecond) / MSecsPerDay;
  194. end ;
  195. { IncMonth increments DateTime with NumberOfMonths months,
  196. NumberOfMonths can be less than zero }
  197. function IncMonth(const DateTime: TDateTime; NumberOfMonths: integer): TDateTime;
  198. var Year, Month, Day: word;
  199. begin
  200. DecodeDate(DateTime, Year, Month, Day);
  201. Month := Month - 1 + NumberOfMonths; { Months from 0 to 11 }
  202. Year := Year + (NumberOfMonths div 12);
  203. Month := Month mod 12;
  204. if Month < 0 then begin
  205. Inc(Month, 12);
  206. Inc(Year, 1);
  207. end ;
  208. Inc(Month, 1); { Months from 1 to 12 }
  209. if (Month = 2) and (IsLeapYear(Year)) and (Day > 28) then
  210. Day := 28;
  211. result := Frac(DateTime) + DoEncodeDate(Year, Month, Day);
  212. end ;
  213. { IsLeapYear returns true if Year is a leap year }
  214. function IsLeapYear(Year: Word): boolean;
  215. begin
  216. Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));
  217. end;
  218. { DateToStr returns a string representation of Date using ShortDateFormat }
  219. function DateToStr(Date: TDateTime): string;
  220. begin
  221. result := FormatDateTime('ddddd', Date);
  222. end ;
  223. { TimeToStr returns a string representation of Time using ShortTimeFormat }
  224. function TimeToStr(Time: TDateTime): string;
  225. begin
  226. result := FormatDateTime('t', Time);
  227. end ;
  228. { DateTimeToStr returns a string representation of DateTime using ShortDateTimeFormat }
  229. function DateTimeToStr(DateTime: TDateTime): string;
  230. begin
  231. result := FormatDateTime('c', DateTime);
  232. end ;
  233. { StrToDate converts the string S to a TDateTime value
  234. if S does not represent a valid date value
  235. an EConvertError will be raised }
  236. function StrToDate(const S: string): TDateTime;
  237. var
  238. df:string;
  239. d,m,y:word;n,i:longint;c:word;
  240. s1:string[4];
  241. values:array[0..2] of longint;
  242. LocalTime:tsystemtime;
  243. begin
  244. df := UpperCase(ShortDateFormat);
  245. d := 0;m := 0;y := 0;
  246. for i := 0 to 2 do values[i] := 0;
  247. s1 := '';
  248. n := 0;
  249. for i := 1 to length(s) do begin
  250. if (s[i] in ['0'..'9']) then s1 := s1 + s[i];
  251. if (s[i] in [dateseparator,' ']) or (i = length(s)) then begin
  252. val(s1, values[n], c);
  253. s1 := '';
  254. inc(n);
  255. end ;
  256. end ;
  257. if (df = 'D/M/Y') then begin
  258. d := values[0];
  259. m := values[1];
  260. y := values[2];
  261. end
  262. else if (df = 'M/D/Y') then begin
  263. if (n > 1) then begin
  264. m := values[0];
  265. d := values[1];
  266. y := values[2];
  267. end
  268. else { if there is just one value, it is the day of the month }
  269. d := values[0];
  270. end
  271. else if (df = 'Y/M/D') then begin
  272. if (n = 3) then begin
  273. y := values[0];
  274. m := values[1];
  275. d := values[2];
  276. end
  277. else if (n = 2) then begin
  278. m := values[0];
  279. d := values[1];
  280. end
  281. else if (n = 1) then
  282. d := values[0];
  283. end ;
  284. if (n < 3) then begin
  285. getLocalTime(LocalTime);
  286. y := LocalTime.Year;
  287. if (n < 2) then
  288. m := LocalTime.Month;
  289. end ;
  290. if (y >= 0) and (y < 100) then y := 1900 + y;
  291. Result := DoEncodeDate(y, m, d);
  292. end ;
  293. { StrToTime converts the string S to a TDateTime value
  294. if S does not represent a valid time value an
  295. EConvertError will be raised }
  296. function StrToTime(const s: string): TDateTime;
  297. var
  298. Len, Current: integer; PM: boolean;
  299. function GetElement: integer;
  300. var i, j: integer; c: word;
  301. begin
  302. result := -1;
  303. Inc(Current);
  304. while (result = -1) and (Current < Len) do begin
  305. if S[Current] in ['0'..'9'] then begin
  306. j := Current;
  307. while (Current < Len) and (s[Current + 1] in ['0'..'9']) do
  308. Inc(Current);
  309. val(copy(S, j, 1 + Current - j), result, c);
  310. end
  311. else if (S[Current] = TimeAMString[1]) or (S[Current] in ['a', 'A']) then begin
  312. Current := 1 + Len;
  313. end
  314. else if (S[Current] = TimePMString[1]) or (S[Current] in ['p', 'P']) then begin
  315. Current := 1 + Len;
  316. PM := True;
  317. end
  318. else if (S[Current] = TimeSeparator) or (S[Current] = ' ') then
  319. Inc(Current)
  320. else exit; // raise EConvertError.Create();
  321. end ;
  322. end ;
  323. var
  324. i: integer;
  325. TimeValues: array[0..4] of integer;
  326. begin
  327. Current := 0;
  328. Len := length(s);
  329. PM := False;
  330. i := 0;
  331. TimeValues[i] := GetElement;
  332. while (i < 5) and (TimeValues[i] <> -1) do begin
  333. i := i + 1;
  334. TimeValues[i] := GetElement;
  335. end ;
  336. if PM then Inc(TimeValues[0], 12);
  337. result := EncodeTime(TimeValues[0], TimeValues[1], TimeValues[2], TimeValues[3]);
  338. end ;
  339. { StrToDateTime converts the string S to a TDateTime value
  340. if S does not represent a valid date and time value
  341. an EConvertError will be raised }
  342. function StrToDateTime(const s: string): TDateTime;
  343. var i: integer;
  344. begin
  345. i := pos(' ', s);
  346. if i > 0 then result := StrToDate(Copy(S, 1, i - 1)) + StrToTime(Copy(S, i + 1, length(S)))
  347. else result := StrToDate(S);
  348. end ;
  349. { FormatDateTime formats DateTime to the given format string FormatStr }
  350. function FormatDateTime(FormatStr: string; DateTime: TDateTime):string;
  351. type
  352. pstring = ^string;
  353. const
  354. AP: array[0..1] of char = 'ap';
  355. TimeAMPMStrings: array[0..1] of pstring = (@TimeAMString, @TimePMString);
  356. var
  357. i: longint;
  358. current: string;
  359. ch: char;
  360. e: longint;
  361. y, m, d, h, n, s, ms: word;
  362. mDate, mTime: double; Clock12: boolean;
  363. begin
  364. mDate := Int(DateTime);
  365. mTime := Frac(DateTime);
  366. DecodeDate(mDate, y, m, d);
  367. DecodeTime(mTime, h, n, s, ms);
  368. result := '';
  369. Clock12 := False;
  370. i := 0;
  371. while i < length(FormatStr) do begin
  372. i := i + 1;
  373. if FormatStr[i] = '"' then begin
  374. i := i + 1;
  375. while (i < length(FormatStr)) and (FormatStr[i] <> '"') do
  376. i := i + 1;
  377. end
  378. else if FormatStr[i] = '''' then begin
  379. i := i + 1;
  380. while (i < length(FormatStr)) and (FormatStr[i] <> '''') do
  381. i := i + 1;
  382. end
  383. else if (copy(FormatStr, i, 3) = 'a/p') then begin
  384. FormatStr[i] := '"';
  385. FormatStr[i + 1] := AP[h div 12];
  386. FormatStr[i + 2] := '"';
  387. Clock12 := True;
  388. i := i + 2;
  389. end
  390. else if (copy(FormatStr, i, 5) = 'am/pm') then begin
  391. Delete(FormatStr, i, 5);
  392. if h < 12 then insert('"' + 'am' + '"', FormatStr, i)
  393. else insert('"' + 'pm' + '"', FormatStr, i);
  394. Clock12 := True;
  395. i := i + 3;
  396. end
  397. else if (copy(FormatStr, i, 4) = 'ampm') then begin
  398. Delete(FormatStr, i, 4);
  399. current := TimeAMPMStrings[h div 12]^;
  400. Insert('"' + current + '"', FormatStr, i);
  401. Clock12 := True;
  402. i := i + length(current) + 1;
  403. end
  404. else if copy(FormatStr, i, 2) = 'tt' then begin
  405. Delete(FormatStr, i, 2);
  406. Insert(LongTimeFormat, FormatStr, i);
  407. i := i - 1;
  408. end
  409. else if FormatStr[i] = 't' then begin
  410. Delete(FormatStr, i, 1);
  411. Insert(ShortTimeFormat, FormatStr, i);
  412. i := i - 1;
  413. end
  414. else if FormatStr[i] = 'c' then begin
  415. Delete(FormatStr, i, 1);
  416. Insert(ShortDateFormat + ' ' + ShortTimeFormat, FormatStr, i);
  417. i := i - 1;
  418. end
  419. else if copy(FormatStr, i, 5) = 'ddddd' then begin
  420. Delete(FormatStr, i, 5);
  421. Insert(ShortDateFormat, FormatStr, i);
  422. i := i - 1;
  423. end
  424. else if copy(FormatStr, i, 6) = 'dddddd' then begin
  425. Delete(FormatStr, i, 6);
  426. Insert(LongDateFormat, FormatStr, i);
  427. i := i - 1;
  428. end ;
  429. end ;
  430. current := '';
  431. i := 1;
  432. e := 0;
  433. while not(i > length(FormatStr)) do begin
  434. while not(FormatStr[i] in [' ','"','/',':','''']) and not(i > length(FormatStr)) do begin
  435. current := current + FormatStr[i];
  436. inc(i);
  437. end ;
  438. if (current <> '') then begin
  439. if (mTime <> 0) then begin
  440. if (current = 'h') then begin
  441. if clock12 then result := result + IntToStr(h mod 12)
  442. else result := result + IntToStr(h);
  443. end
  444. else if (current = 'hh') then begin
  445. if clock12 then result := result + RightStr('0' + IntToStr(h mod 12), 2)
  446. else result := result + RightStr('0' + IntToStr(h), 2);
  447. end
  448. else if (current = 'n') then result := result + IntToStr(n)
  449. else if (current = 'nn') then result := result + RightStr('0' + IntToStr(n), 2)
  450. else if (current = 's') then result := result + IntToStr(s)
  451. else if (current = 'ss') then result := result + RightStr('0' + IntToStr(s), 2);
  452. end ;
  453. if (mDate <> 0) then begin
  454. if (current = 'd') then result := result + IntToStr(d)
  455. else if (current = 'dd') then result := result + RightStr('0' + IntToStr(d), 2)
  456. else if (current = 'ddd') then result := result + ShortDayNames[DayOfWeek(DateTime)]
  457. else if (current = 'dddd') then result := result + LongDayNames[DayOfWeek(DateTime)]
  458. else if (current = 'm') then result := result + IntToStr(m)
  459. else if (current = 'mm') then result := result + RightStr('0' + IntToStr(m), 2)
  460. else if (current = 'mmm') then result := result + ShortMonthNames[m]
  461. else if (current = 'mmmm') then result := result + LongMonthNames[m]
  462. else if (current = 'y') then result := result + IntToStr(y)
  463. else if (current = 'yy') then result := result + RightStr(IntToStr(y), 2)
  464. else if (current = 'yyyy') or (current = 'yyy') then result := result + IntToStr(y);
  465. end ;
  466. current := '';
  467. end ;
  468. if FormatStr[i] = ' ' then result := result + ' '
  469. else if (FormatStr[i] = '/') and (mDate <> 0) then result := result + DateSeparator
  470. else if (FormatStr[i] = ':') and (mTime <> 0) then result := result + TimeSeparator
  471. else if (FormatStr[i] in ['"', '''']) then begin
  472. ch := FormatStr[i];
  473. inc(i);
  474. while (i <= length(FormatStr)) and (FormatStr[i] <> ch) do begin
  475. result := result + FormatStr[i];
  476. inc(i);
  477. end ;
  478. end ;
  479. inc(i);
  480. end ;
  481. end ;
  482. { DateTimeToString formats DateTime to the given format in FormatStr }
  483. procedure DateTimeToString(var Result: string; const FormatStr: string; const DateTime: TDateTime);
  484. begin
  485. Result := FormatDateTime(FormatStr, DateTime);
  486. end ;
  487. Function DateTimeToFileDate(DateTime : TDateTime) : Longint;
  488. Var YY,MM,DD,H,m,s,msec : Word;
  489. begin
  490. Decodedate (DateTime,YY,MM,DD);
  491. If (YY<1980) or (YY>2099) then
  492. Result:=0
  493. else
  494. begin
  495. DecodeTime (DateTime,h,m,s,msec);
  496. Result:=(s shr 1) or (m shl 5) or (h shl 11);
  497. Result:=Result or DD shl 16 or (MM shl 21) or ((YY-1980) shl 25);
  498. end;
  499. end;
  500. Function FileDateToDateTime (Filedate : Longint) : TDateTime;
  501. Var Date,Time : Word;
  502. begin
  503. Date:=FileDate shl 16;
  504. Time:=FileDate and $ffff;
  505. Result:=EncodeDate((Date shr 9) + 1980,(Date shr 5) and 15, Date and 31) +
  506. EncodeTime(Time shr 11, (Time shr 5) and 63, (Time and 31) shl 1,0);
  507. end;
  508. {
  509. $Log$
  510. Revision 1.4 1998-10-11 13:40:52 michael
  511. + Added Conversion TDateTime <-> file date and time
  512. Revision 1.3 1998/09/16 08:28:36 michael
  513. Update from gertjan Schouten, plus small fix for linux
  514. Revision 1.1 1998/04/10 15:17:46 michael
  515. + Initial implementation; Donated by Gertjan Schouten
  516. His file was split into several files, to keep it a little bit structured.
  517. 1998/08/25 Gertjan
  518. + uses Go32 instead of Dos unit
  519. GetLocalTime
  520. DayOfWeek
  521. DoDecodeDate
  522. DoEncodeDate
  523. FormatDateTime
  524. }