dati.inc 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  1. {
  2. *********************************************************************
  3. Copyright (C) 1997, 1998 Gertjan Schouten
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************
  10. System Utilities For Free Pascal
  11. }
  12. {==============================================================================}
  13. { internal functions }
  14. {==============================================================================}
  15. Function DoEncodeDate(Year, Month, Day: Word): longint;
  16. Var
  17. D : TDateTime;
  18. begin
  19. If TryEncodeDate(Year,Month,Day,D) then
  20. Result:=Trunc(D)
  21. else
  22. Result:=0;
  23. end;
  24. function DoEncodeTime(Hour, Minute, Second, MilliSecond: word): TDateTime;
  25. begin
  26. If not TryEncodeTime(Hour,Minute,Second,MilliSecond,Result) then
  27. Result:=0;
  28. end;
  29. {==============================================================================}
  30. { Public functions }
  31. {==============================================================================}
  32. { ComposeDateTime converts a Date and a Time into one TDateTime }
  33. function ComposeDateTime(Date,Time : TDateTime) : TDateTime;
  34. begin
  35. if Date < 0 then Result := trunc(Date) - Abs(frac(Time))
  36. else Result := trunc(Date) + Abs(frac(Time));
  37. end;
  38. { DateTimeToTimeStamp converts DateTime to a TTimeStamp }
  39. function DateTimeToTimeStamp(DateTime: TDateTime): TTimeStamp;
  40. Var
  41. D : Double;
  42. begin
  43. D:=DateTime * Single(MSecsPerDay);
  44. if D<0 then
  45. D:=D-0.5
  46. else
  47. D:=D+0.5;
  48. result.Time := Abs(Trunc(D)) Mod MSecsPerDay;
  49. result.Date := DateDelta + Trunc(D) div MSecsPerDay;
  50. end;
  51. { TimeStampToDateTime converts TimeStamp to a TDateTime value }
  52. function TimeStampToDateTime(const TimeStamp: TTimeStamp): TDateTime;
  53. begin
  54. Result := ComposeDateTime(TimeStamp.Date - DateDelta,TimeStamp.Time / MSecsPerDay)
  55. end;
  56. { MSecsToTimeStamp }
  57. function MSecsToTimeStamp(MSecs: comp): TTimeStamp;
  58. begin
  59. result.Date := Trunc(msecs / msecsperday);
  60. msecs:= msecs-comp(result.date)*msecsperday;
  61. result.Time := Round(MSecs);
  62. end ;
  63. { TimeStampToMSecs }
  64. function TimeStampToMSecs(const TimeStamp: TTimeStamp): comp;
  65. begin
  66. result := TimeStamp.Time + comp(timestamp.date)*msecsperday;
  67. end ;
  68. Function TryEncodeDate(Year,Month,Day : Word; Out Date : TDateTime) : Boolean;
  69. var
  70. c, ya: cardinal;
  71. begin
  72. Result:=(Year>0) and (Year<10000) and
  73. (Month in [1..12]) and
  74. (Day>0) and (Day<=MonthDays[IsleapYear(Year),Month]);
  75. If Result then
  76. begin
  77. if month > 2 then
  78. Dec(Month,3)
  79. else
  80. begin
  81. Inc(Month,9);
  82. Dec(Year);
  83. end;
  84. c:= Year DIV 100;
  85. ya:= Year - 100*c;
  86. Date := (146097*c) SHR 2 + (1461*ya) SHR 2 + (153*cardinal(Month)+2) DIV 5 + cardinal(Day);
  87. // Note that this line can't be part of the line above, since TDateTime is
  88. // signed and c and ya are not
  89. Date := Date - 693900;
  90. end
  91. end;
  92. function TryEncodeTime(Hour, Min, Sec, MSec:word; Out Time : TDateTime) : boolean;
  93. begin
  94. Result:=(Hour<24) and (Min<60) and (Sec<60) and (MSec<1000);
  95. If Result then
  96. Time:=TDateTime(cardinal(Hour)*3600000+cardinal(Min)*60000+cardinal(Sec)*1000+MSec)/MSecsPerDay;
  97. end;
  98. { EncodeDate packs three variables Year, Month and Day into a
  99. TDateTime value the result is the number of days since 12/30/1899 }
  100. function EncodeDate(Year, Month, Day: word): TDateTime;
  101. begin
  102. If Not TryEncodeDate(Year,Month,Day,Result) then
  103. Raise EConvertError.CreateFmt('%d-%d-%d is not a valid date specification',
  104. [Year,Month,Day]);
  105. end;
  106. { EncodeTime packs four variables Hour, Minute, Second and MilliSecond into
  107. a TDateTime value }
  108. function EncodeTime(Hour, Minute, Second, MilliSecond:word):TDateTime;
  109. begin
  110. If not TryEncodeTime(Hour,Minute,Second,MilliSecond,Result) then
  111. Raise EConvertError.CreateFmt('%d:%d:%d.%d is not a valid time specification',
  112. [Hour,Minute,Second,MilliSecond]);
  113. end;
  114. { DecodeDate unpacks the value Date into three values:
  115. Year, Month and Day }
  116. procedure DecodeDate(Date: TDateTime; out Year, Month, Day: word);
  117. var
  118. ly,ld,lm,j : cardinal;
  119. begin
  120. if Date <= -datedelta then // If Date is before 1-1-1 then return 0-0-0
  121. begin
  122. Year := 0;
  123. Month := 0;
  124. Day := 0;
  125. end
  126. else
  127. begin
  128. if Date>0 then
  129. Date:=Date+1/(msecsperday*2)
  130. else
  131. Date:=Date-1/(msecsperday*2);
  132. j := pred((Trunc(System.Int(Date)) + 693900) SHL 2);
  133. ly:= j DIV 146097;
  134. j:= j - 146097 * cardinal(ly);
  135. ld := j SHR 2;
  136. j:=(ld SHL 2 + 3) DIV 1461;
  137. ld:= (cardinal(ld) SHL 2 + 7 - 1461*j) SHR 2;
  138. lm:=(5 * ld-3) DIV 153;
  139. ld:= (5 * ld +2 - 153*lm) DIV 5;
  140. ly:= 100 * cardinal(ly) + j;
  141. if lm < 10 then
  142. inc(lm,3)
  143. else
  144. begin
  145. dec(lm,9);
  146. inc(ly);
  147. end;
  148. year:=ly;
  149. month:=lm;
  150. day:=ld;
  151. end;
  152. end;
  153. function DecodeDateFully(const DateTime: TDateTime; out Year, Month, Day, DOW: Word): Boolean;
  154. begin
  155. DecodeDate(DateTime,Year,Month,Day);
  156. DOW:=DayOfWeek(DateTime);
  157. Result:=IsLeapYear(Year);
  158. end;
  159. { DecodeTime unpacks Time into four values:
  160. Hour, Minute, Second and MilliSecond }
  161. procedure DecodeTime(Time: TDateTime; out Hour, Minute, Second, MilliSecond: word);
  162. Var
  163. l : cardinal;
  164. begin
  165. l := DateTimeToTimeStamp(Time).Time;
  166. Hour := l div 3600000;
  167. l := l mod 3600000;
  168. Minute := l div 60000;
  169. l := l mod 60000;
  170. Second := l div 1000;
  171. l := l mod 1000;
  172. MilliSecond := l;
  173. end;
  174. { DateTimeToSystemTime converts DateTime value to SystemTime }
  175. procedure DateTimeToSystemTime(DateTime: TDateTime; out SystemTime: TSystemTime);
  176. begin
  177. DecodeDate(DateTime, SystemTime.Year, SystemTime.Month, SystemTime.Day);
  178. DecodeTime(DateTime, SystemTime.Hour, SystemTime.Minute, SystemTime.Second, SystemTime.MilliSecond);
  179. end ;
  180. { SystemTimeToDateTime converts SystemTime to a TDateTime value }
  181. function SystemTimeToDateTime(const SystemTime: TSystemTime): TDateTime;
  182. begin
  183. result := ComposeDateTime(DoEncodeDate(SystemTime.Year, SystemTime.Month, SystemTime.Day),
  184. DoEncodeTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second, SystemTime.MilliSecond));
  185. end ;
  186. { DayOfWeek returns the Day of the week (sunday is day 1) }
  187. function DayOfWeek(DateTime: TDateTime): integer;
  188. begin
  189. Result := 1 + ((Trunc(DateTime) - 1) mod 7);
  190. If (Result<=0) then
  191. Inc(Result,7);
  192. end;
  193. { Date returns the current Date }
  194. function Date: TDateTime;
  195. var
  196. SystemTime: TSystemTime;
  197. begin
  198. GetLocalTime(SystemTime);
  199. result := DoEncodeDate(SystemTime.Year, SystemTime.Month, SystemTime.Day);
  200. end ;
  201. { Time returns the current Time }
  202. function Time: TDateTime;
  203. var
  204. SystemTime: TSystemTime;
  205. begin
  206. GetLocalTime(SystemTime);
  207. Result := DoEncodeTime(SystemTime.Hour,SystemTime.Minute,SystemTime.Second,SystemTime.MilliSecond);
  208. end ;
  209. { Now returns the current Date and Time }
  210. function Now: TDateTime;
  211. var
  212. SystemTime: TSystemTime;
  213. begin
  214. GetLocalTime(SystemTime);
  215. result := systemTimeToDateTime(SystemTime);
  216. end;
  217. { IncMonth increments DateTime with NumberOfMonths months,
  218. NumberOfMonths can be less than zero }
  219. function IncMonth(const DateTime: TDateTime; NumberOfMonths: integer = 1 ): TDateTime;
  220. var
  221. Year, Month, Day : word;
  222. begin
  223. DecodeDate(DateTime, Year, Month, Day);
  224. IncAMonth(Year, Month, Day, NumberOfMonths);
  225. result := ComposeDateTime(DoEncodeDate(Year, Month, Day), DateTime);
  226. end ;
  227. { IncAMonth is the same as IncMonth, but operates on decoded date }
  228. procedure IncAMonth(var Year, Month, Day: Word; NumberOfMonths: Integer = 1);
  229. var
  230. TempMonth, S: Integer;
  231. begin
  232. If NumberOfMonths>=0 then
  233. s:=1
  234. else
  235. s:=-1;
  236. inc(Year,(NumberOfMonths div 12));
  237. TempMonth:=Month+(NumberOfMonths mod 12)-1;
  238. if (TempMonth>11) or
  239. (TempMonth<0) then
  240. begin
  241. Dec(TempMonth, S*12);
  242. Inc(Year, S);
  243. end;
  244. Month:=TempMonth+1; { Months from 1 to 12 }
  245. If (Day>MonthDays[IsLeapYear(Year)][Month]) then
  246. Day:=MonthDays[IsLeapYear(Year)][Month];
  247. end;
  248. { IsLeapYear returns true if Year is a leap year }
  249. function IsLeapYear(Year: Word): boolean;
  250. begin
  251. Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));
  252. end;
  253. { DateToStr returns a string representation of Date using ShortDateFormat }
  254. function DateToStr(Date: TDateTime): string;
  255. begin
  256. DateTimeToString(Result, 'ddddd', Date);
  257. end ;
  258. function DateToStr(Date: TDateTime; const FormatSettings: TFormatSettings): string;
  259. begin
  260. DateTimeToString(result, FormatSettings.ShortDateFormat, Date, FormatSettings);
  261. end;
  262. { TimeToStr returns a string representation of Time using LongTimeFormat }
  263. function TimeToStr(Time: TDateTime): string;
  264. begin
  265. DateTimeToString(Result, 'tt', Time);
  266. end ;
  267. function TimeToStr(Time: TDateTime; const FormatSettings: TFormatSettings): string;
  268. begin
  269. DateTimeToString(Result, FormatSettings.LongTimeFormat, Time, FormatSettings);
  270. end;
  271. { DateTimeToStr returns a string representation of DateTime using LongDateTimeFormat }
  272. function DateTimeToStr(DateTime: TDateTime): string;
  273. begin
  274. DateTimeToString(Result, 'c', DateTime);
  275. end ;
  276. function DateTimeToStr(DateTime: TDateTime; const FormatSettings: TFormatSettings): string;
  277. begin
  278. DateTimeToString(Result, 'c', DateTime ,FormatSettings);
  279. end;
  280. { StrToDate converts the string S to a TDateTime value
  281. if S does not represent a valid date value
  282. an EConvertError will be raised }
  283. function IntStrToDate(Out ErrorMsg : AnsiString; const S: PChar; Len : integer; const useformat : string; const defs:TFormatSettings; separator : char = #0): TDateTime;
  284. const SInvalidDateFormat = '"%s" is not a valid date format';
  285. procedure FixErrorMsg(const errm :ansistring;const errmarg : ansistring);
  286. begin
  287. errormsg:=format(errm,[errmarg]);
  288. end;
  289. var
  290. df:string;
  291. d,m,y,ly:word;
  292. n,i:longint;
  293. c:word;
  294. dp,mp,yp,which : Byte;
  295. s1:string[4];
  296. values:array[0..3] of longint;
  297. LocalTime:tsystemtime;
  298. YearMoreThenTwoDigits : boolean;
  299. begin
  300. ErrorMsg:=''; Result:=0;
  301. While (Len>0) and (S[Len-1] in [' ',#8,#9,#10,#12,#13]) do
  302. Dec(len);
  303. if (Len=0) then
  304. begin
  305. FixErrorMsg(SInvalidDateFormat,'');
  306. exit;
  307. end;
  308. YearMoreThenTwoDigits := False;
  309. if separator = #0 then
  310. separator := defs.DateSeparator;
  311. df := UpperCase(useFormat);
  312. { Determine order of D,M,Y }
  313. yp:=0;
  314. mp:=0;
  315. dp:=0;
  316. Which:=0;
  317. i:=0;
  318. while (i<Length(df)) and (Which<3) do
  319. begin
  320. inc(i);
  321. Case df[i] of
  322. 'Y' :
  323. if yp=0 then
  324. begin
  325. Inc(Which);
  326. yp:=which;
  327. end;
  328. 'M' :
  329. if mp=0 then
  330. begin
  331. Inc(Which);
  332. mp:=which;
  333. end;
  334. 'D' :
  335. if dp=0 then
  336. begin
  337. Inc(Which);
  338. dp:=which;
  339. end;
  340. end;
  341. end;
  342. for i := 1 to 3 do
  343. values[i] := 0;
  344. s1 := '';
  345. n := 0;
  346. dec(len);
  347. for i := 0 to len do
  348. begin
  349. if s[i] in ['0'..'9'] then
  350. s1 := s1 + s[i];
  351. { space can be part of the shortdateformat, and is defaultly in slovak
  352. windows, therefor it shouldn't be taken as separator (unless so specified)
  353. and ignored }
  354. if (Separator <> ' ') and (s[i] = ' ') then
  355. Continue;
  356. if (s[i] = separator) or ((i = len) and (s[i] in ['0'..'9'])) then
  357. begin
  358. inc(n);
  359. if n>3 then
  360. begin
  361. FixErrorMsg(SInvalidDateFormat,s);
  362. exit;
  363. end;
  364. // Check if the year has more then two digits (if n=yp, then we are evaluating the year.)
  365. if (n=yp) and (length(s1)>2) then YearMoreThenTwoDigits := True;
  366. val(s1, values[n], c);
  367. if c<>0 then
  368. begin
  369. FixErrorMsg(SInvalidDateFormat,s);
  370. Exit;
  371. end;
  372. s1 := '';
  373. end
  374. else if not (s[i] in ['0'..'9']) then
  375. begin
  376. FixErrorMsg(SInvalidDateFormat,s);
  377. Exit;
  378. end;
  379. end ;
  380. if (Which<3) and (N>Which) then
  381. begin
  382. FixErrorMsg(SInvalidDateFormat,s);
  383. Exit;
  384. end;
  385. // Fill in values.
  386. getLocalTime(LocalTime);
  387. ly := LocalTime.Year;
  388. If N=3 then
  389. begin
  390. y:=values[yp];
  391. m:=values[mp];
  392. d:=values[dp];
  393. end
  394. Else
  395. begin
  396. Y:=ly;
  397. If n<2 then
  398. begin
  399. d:=values[1];
  400. m := LocalTime.Month;
  401. end
  402. else
  403. If dp<mp then
  404. begin
  405. d:=values[1];
  406. m:=values[2];
  407. end
  408. else
  409. begin
  410. d:=values[2];
  411. m:=values[1];
  412. end;
  413. end;
  414. if (y >= 0) and (y < 100) and not YearMoreThenTwoDigits then
  415. begin
  416. ly := ly - defs.TwoDigitYearCenturyWindow;
  417. Inc(Y, ly div 100 * 100);
  418. if (defs.TwoDigitYearCenturyWindow > 0) and (Y < ly) then
  419. Inc(Y, 100);
  420. end;
  421. if not TryEncodeDate(y, m, d, result) then
  422. errormsg:='Invalid date';
  423. end;
  424. function StrToDate(const S: PChar; Len : integer; const useformat : string; separator : char = #0): TDateTime;
  425. Var
  426. MSg : AnsiString;
  427. begin
  428. Result:=IntStrToDate(Msg,S,Len,useFormat,DefaultFormatSettings,Separator);
  429. If (Msg<>'') then
  430. Raise EConvertError.Create(Msg);
  431. end;
  432. function StrToDate(const S: string; FormatSettings: TFormatSettings): TDateTime;
  433. var
  434. Msg: AnsiString;
  435. begin
  436. Result:=IntStrToDate(Msg,@S[1],Length(S),FormatSettings.ShortDateFormat,FormatSettings);
  437. if Msg<>'' then
  438. raise EConvertError.Create(Msg);
  439. end;
  440. function StrToDate(const S: ShortString; const useformat : string; separator : char = #0): TDateTime;
  441. begin
  442. result := StrToDate(@S[1],Length(s),UseFormat,separator);
  443. end;
  444. function StrToDate(const S: AnsiString; const useformat : string; separator : char = #0): TDateTime;
  445. begin
  446. result := StrToDate(@S[1],Length(s),UseFormat,separator);
  447. end;
  448. function StrToDate(const S: ShortString; separator : char): TDateTime;
  449. begin
  450. result := StrToDate(@S[1],Length(s),DefaultFormatSettings.ShortDateFormat,separator)
  451. end;
  452. function StrToDate(const S: ShortString): TDateTime;
  453. begin
  454. result := StrToDate(@S[1],Length(s),DefaultFormatSettings.ShortDateFormat,#0);
  455. end;
  456. function StrToDate(const S: AnsiString; separator : char): TDateTime;
  457. begin
  458. result := StrToDate(@S[1],Length(s),DefaultFormatSettings.ShortDateFormat,separator)
  459. end;
  460. function StrToDate(const S: AnsiString): TDateTime;
  461. begin
  462. result := StrToDate(@S[1],Length(s),DefaultFormatSettings.ShortDateFormat,#0);
  463. end;
  464. { StrToTime converts the string S to a TDateTime value
  465. if S does not represent a valid time value an
  466. EConvertError will be raised }
  467. function IntStrToTime(Out ErrorMsg : AnsiString; const S: PChar; Len : integer;const defs:TFormatSettings; separator : char = #0): TDateTime;
  468. const
  469. AMPM_None = 0;
  470. AMPM_AM = 1;
  471. AMPM_PM = 2;
  472. tiHour = 0;
  473. tiMin = 1;
  474. tiSec = 2;
  475. tiMSec = 3;
  476. type
  477. TTimeValues = array[tiHour..tiMSec] of Word;
  478. var
  479. AmPm: integer;
  480. TimeValues: TTimeValues;
  481. function StrPas(Src : PChar; len: integer = 0) : ShortString;
  482. begin
  483. //this is unsafe for len > 255, it will trash memory (I tested this)
  484. //reducing it is safe, since whenever we use this a string > 255 is invalid anyway
  485. if len > 255 then len := 255;
  486. SetLength(Result, len);
  487. move(src[0],result[1],len);
  488. end;
  489. function SplitElements(out TimeValues: TTimeValues; out AmPm: Integer): Boolean;
  490. //Strict version. It does not allow #32 as Separator, it will treat it as whitespace always
  491. const
  492. Digits = ['0'..'9'];
  493. var
  494. Cur, Offset, ElemLen, Err, TimeIndex, FirstSignificantDigit: Integer;
  495. Value: Word;
  496. DigitPending, MSecPending: Boolean;
  497. AmPmStr: ShortString;
  498. CurChar: Char;
  499. begin
  500. Result := False;
  501. AmPm := AMPM_None; //No Am or PM in string found yet
  502. MSecPending := False;
  503. TimeIndex := 0; //indicating which TTimeValue must be filled next
  504. FillChar(TimeValues, SizeOf(TTimeValues), 0);
  505. Cur := 0;
  506. //skip leading blanks
  507. While (Cur < Len) and (S[Cur] =#32) do Inc(Cur);
  508. Offset := Cur;
  509. //First non-blank cannot be Separator or DecimalSeparator
  510. if (Cur > Len - 1) or (S[Cur] = Separator) or (S[Cur] = defs.Decimalseparator) then Exit;
  511. DigitPending := (S[Cur] in Digits);
  512. While (Cur < Len) do
  513. begin
  514. //writeln;
  515. //writeln('Main While loop: Cur = ',Cur,' S[Cur] = "',S[Cur],'" Len = ',Len);
  516. CurChar := S[Cur];
  517. if CurChar in Digits then
  518. begin//Digits
  519. //HH, MM, SS, or Msec?
  520. //writeln('Digit');
  521. //Digits are only allowed after starting Am/PM or at beginning of string or after Separator
  522. //and TimeIndex must be <= tiMSec
  523. //Uncomment "or (#32 = Separator)" and it will allllow #32 as separator
  524. if (not (DigitPending {or (#32 = Separator)})) or (TimeIndex > tiMSec) then Exit;
  525. OffSet := Cur;
  526. if (CurChar <> '0') then FirstSignificantDigit := OffSet else FirstSignificantDigit := -1;
  527. while (Cur < Len -1) and (S[Cur + 1] in Digits) do
  528. begin
  529. //Mark first Digit that is not '0'
  530. if (FirstSignificantDigit = -1) and (S[Cur] <> '0') then FirstSignificantDigit := Cur;
  531. Inc(Cur);
  532. end;
  533. if (FirstSignificantDigit = -1) then FirstSignificantDigit := Cur;
  534. ElemLen := 1 + Cur - FirstSignificantDigit;
  535. //writeln(' S[FirstSignificantDigit] = ',S[FirstSignificantDigit], ' S[Cur] = ',S[Cur],' ElemLen = ',ElemLen,' -> ', StrPas(S + Offset, ElemLen));
  536. //writeln(' Cur = ',Cur);
  537. //this way we know that Val() will never overflow Value !
  538. if (ElemLen <= 2) or ((ElemLen <= 3) and (TimeIndex = tiMSec) ) then
  539. begin
  540. Val(StrPas(S + FirstSignificantDigit, ElemLen), Value, Err);
  541. //writeln(' Value = ',Value,' HH = ',TimeValues[0],' MM = ',TimeValues[1],' SS = ',TimeValues[2],' MSec = ',Timevalues[3]);
  542. //This is safe now, because we know Value < High(Word)
  543. TimeValues[TimeIndex] := Value;
  544. Inc(TimeIndex);
  545. DigitPending := False;
  546. end
  547. else Exit; //Value to big, so it must be a wrong timestring
  548. end//Digits
  549. else if (CurChar = #32) then
  550. begin
  551. //writeln('#32');
  552. //just skip, but we must adress this, or it will be parsed by either AM/PM or Separator
  553. end
  554. else if (CurChar = Separator) then
  555. begin
  556. //writeln('Separator');
  557. if DigitPending or (TimeIndex > tiSec) then Exit;
  558. DigitPending := True;
  559. MSecPending := False;
  560. end
  561. else if (CurChar = defs.DecimalSeparator) then
  562. begin
  563. //writeln('DecimalSeparator');
  564. if DigitPending or MSecPending or (TimeIndex <> tiMSec) then Exit;
  565. DigitPending := True;
  566. MSecPending := True;
  567. end
  568. else
  569. begin//AM/PM?
  570. //None of the above, so this char _must_ be the start of AM/PM string
  571. //If we already have found AM/PM or we expect a digit then then timestring must be wrong at this point
  572. //writeln('AM/PM?');
  573. if (AmPm <> AMPM_None) or DigitPending then Exit;
  574. OffSet := Cur;
  575. while (Cur < Len -1) and (not (S[Cur + 1] in [Separator, #32, defs.DecimalSeparator]))
  576. and not (S[Cur + 1] in Digits) do Inc(Cur);
  577. ElemLen := 1 + Cur - OffSet;
  578. //writeln(' S[Offset] = ',S[Offset], ' S[Cur] = ',S[Cur],' ElemLen = ',ElemLen,' -> ', StrPas(S + Offset, ElemLen));
  579. //writeln(' Cur = ',Cur);
  580. AmPmStr := StrPas(S + OffSet, ElemLen);
  581. //writeln('AmPmStr = ',ampmstr,' (',length(ampmstr),')');
  582. //We must compare to TimeAMString before hardcoded 'AM' for delphi compatibility
  583. //Also it is perfectly legal, though insane to have TimeAMString = 'PM' and vice versa
  584. if (AnsiCompareText(AmPmStr, defs.TimeAMString) = 0) then AmPm := AMPM_AM
  585. else if (AnsiCompareText(AmPmStr, defs.TimePMString) = 0) then AmPm := AMPM_PM
  586. else if (CompareText(AmPmStr, 'AM') = 0) then AmPm := AMPM_AM
  587. else if (CompareText(AmPmStr, 'PM') = 0) then AmPm := AMPM_PM
  588. else Exit; //If text does not match any of these, timestring must be wrong;
  589. //if AM/PM is at beginning of string, then a digit is mandatory after it
  590. if (TimeIndex = tiHour) then
  591. begin
  592. DigitPending := True;
  593. end
  594. //otherwise, no more TimeValues allowed after this
  595. else
  596. begin
  597. TimeIndex := tiMSec + 1;
  598. DigitPending := False;
  599. end;
  600. end;//AM/PM
  601. Inc(Cur)
  602. end;//while
  603. //If we arrive here, parsing the elements has been successfull
  604. //if not at least Hours specified then input is not valid
  605. //when am/pm is specified Hour must be <= 12 and not 0
  606. if (TimeIndex = tiHour) or ((AmPm <> AMPM_None) and ((TimeValues[tiHour] > 12) or (TimeValues[tiHour] = 0))) or DigitPending then Exit;
  607. Result := True;
  608. end;
  609. begin
  610. if separator = #0 then
  611. separator := defs.TimeSeparator;
  612. AmPm := AMPM_None;
  613. if not SplitElements(TimeValues, AmPm) then
  614. begin
  615. ErrorMsg:=Format(SErrInvalidTimeFormat,[StrPas(S, Len)]);
  616. Exit;
  617. end;
  618. if (AmPm=AMPM_PM) and (TimeValues[tiHour]<>12) then Inc(TimeValues[tiHour], 12)
  619. else if (AmPm=AMPM_AM) and (TimeValues[tiHour]=12) then TimeValues[tiHour]:=0;
  620. if not TryEncodeTime(TimeValues[tiHour], TimeValues[tiMin], TimeValues[tiSec], TimeValues[tiMSec], result) Then
  621. //errormsg:='Invalid time.';
  622. ErrorMsg:=Format(SErrInvalidTimeFormat,[StrPas(S, Len)]);
  623. end ;
  624. function StrToTime(const S: PChar; Len : integer; separator : char = #0): TDateTime;
  625. Var
  626. Msg : AnsiString;
  627. begin
  628. Result:=IntStrToTime(Msg,S,Len,DefaultFormatSettings,Separator);
  629. If (Msg<>'') then
  630. Raise EConvertError.Create(Msg);
  631. end;
  632. function StrToTime(const S: string; FormatSettings : TFormatSettings): TDateTime;
  633. Var
  634. Msg : AnsiString;
  635. begin
  636. Result:=IntStrToTime(Msg, @S[1], length(S), FormatSettings, #0);
  637. If (Msg<>'') then
  638. Raise EConvertError.Create(Msg);
  639. end;
  640. function StrToTime(const s: ShortString; separator : char): TDateTime;
  641. begin
  642. result := StrToTime(@s[1], length(s), separator);
  643. end;
  644. function StrToTime(const s: AnsiString; separator : char): TDateTime;
  645. begin
  646. result := StrToTime(@s[1], length(s), separator);
  647. end;
  648. function StrToTime(const s: ShortString): TDateTime;
  649. begin
  650. result := StrToTime(@s[1], length(s), #0);
  651. end;
  652. function StrToTime(const s: AnsiString): TDateTime;
  653. begin
  654. result := StrToTime(@s[1], length(s), #0);
  655. end;
  656. { StrToDateTime converts the string S to a TDateTime value
  657. if S does not represent a valid date and/or time value
  658. an EConvertError will be raised }
  659. function SplitDateTimeStr(DateTimeStr: AnsiString; const FS: TFormatSettings; out DateStr, TimeStr: AnsiString): Integer;
  660. { Helper function for StrToDateTime
  661. Pre-condition
  662. Date is before Time
  663. If either Date or Time is omitted then see what fits best, a time or a date (issue #0020522)
  664. Date and Time are separated by whitespace (space Tab, Linefeed or carriage return)
  665. FS.DateSeparator can be the same as FS.TimeSeparator (issue #0020522)
  666. If they are both #32 and TrimWhite(DateTimeStr) contains a #32 a date is assumed.
  667. Post-condition
  668. DateStr holds date as string or is empty
  669. TimeStr holds time as string or is empty
  670. Result = number of strings returned, 0 = error
  671. }
  672. const
  673. WhiteSpace = [#9,#10,#13,#32];
  674. var
  675. p: Integer;
  676. DummyDT: TDateTime;
  677. begin
  678. Result := 0;
  679. DateStr := '';
  680. TimeStr := '';
  681. DateTimeStr := Trim(DateTimeStr);
  682. if Length(DateTimeStr) = 0 then exit;
  683. if (FS.DateSeparator = #32) and (FS.TimeSeparator = #32) and (Pos(#32, DateTimeStr) > 0) then
  684. begin
  685. DateStr:=DateTimeStr;
  686. {
  687. Assume a date: dd [mm [yy]].
  688. Really fancy would be counting the number of whitespace occurrences and decide
  689. and split accordingly
  690. }
  691. Exit(1);
  692. end;
  693. p:=1;
  694. //find separator
  695. if (FS.DateSeparator<>#32) then
  696. begin
  697. while (p<Length(DateTimeStr)) and (not (DateTimeStr[p+1] in WhiteSpace)) do
  698. Inc(p);
  699. end
  700. else
  701. begin
  702. p:=Pos(FS.TimeSeparator, DateTimeStr);
  703. if (p<>0) then
  704. repeat
  705. Dec(p);
  706. until (p=0) or (DateTimeStr[p] in WhiteSpace);
  707. end;
  708. //Always fill DateStr, it eases the algorithm later
  709. if (p=0) then
  710. p:=Length(DateTimeStr);
  711. DateStr:=Copy(DateTimeStr,1,p);
  712. TimeStr:=Trim(Copy(DateTimeStr,p+1,MaxInt));
  713. if (Length(TimeStr)<>0) then
  714. Result:=2
  715. else
  716. begin
  717. Result:=1; //found 1 string
  718. // 2 cases when DateTimeStr only contains a time:
  719. // Date/time separator differ, and string contains a timeseparator
  720. // Date/time separators are equal, but transformation to date fails.
  721. if ((FS.DateSeparator<>FS.TimeSeparator) and (Pos(FS.TimeSeparator,DateStr) > 0))
  722. or ((FS.DateSeparator=FS.TimeSeparator) and (not TryStrToDate(DateStr, DummyDT, FS))) then
  723. begin
  724. TimeStr := DateStr;
  725. DateStr := '';
  726. end;
  727. end;
  728. end;
  729. function StrToDateTime(const s: AnsiString; const FormatSettings : TFormatSettings): TDateTime;
  730. var
  731. TimeStr, DateStr: AnsiString;
  732. PartsFound: Integer;
  733. begin
  734. PartsFound := SplitDateTimeStr(S, FormatSettings, DateStr, TimeStr);
  735. case PartsFound of
  736. 0: Result:=StrToDate('');
  737. 1: if (Length(DateStr) > 0) then
  738. Result := StrToDate(DateStr, FormatSettings.ShortDateFormat,FormatSettings.DateSeparator)
  739. else
  740. Result := StrToTime(TimeStr, FormatSettings);
  741. 2: Result := ComposeDateTime(StrTodate(DateStr,FormatSettings.ShortDateFormat,FormatSettings.DateSeparator),
  742. StrToTime(TimeStr,FormatSettings));
  743. end;
  744. end;
  745. function StrToDateTime(const s: AnsiString): TDateTime;
  746. begin
  747. Result:=StrToDateTime(S,DefaultFormatSettings);
  748. end;
  749. function StrToDateTime(const s: ShortString; const FormatSettings : TFormatSettings): TDateTime;
  750. var
  751. A : AnsiString;
  752. begin
  753. A:=S;
  754. Result:=StrToDateTime(A,FormatSettings);
  755. end;
  756. { FormatDateTime formats DateTime to the given format string FormatStr }
  757. function FormatDateTime(const FormatStr: string; DateTime: TDateTime): string;
  758. begin
  759. DateTimeToString(Result, FormatStr, DateTime, DefaultFormatSettings);
  760. end;
  761. function FormatDateTime(const FormatStr: string; DateTime: TDateTime; const FormatSettings: TFormatSettings): string;
  762. begin
  763. DateTimeToString(Result, FormatStr, DateTime, FormatSettings);
  764. end;
  765. { DateTimeToString formats DateTime to the given format in FormatStr }
  766. procedure DateTimeToString(out Result: string; const FormatStr: string; const DateTime: TDateTime);
  767. begin
  768. DateTimeToString(Result, FormatStr, DateTime, DefaultFormatSettings);
  769. end;
  770. procedure DateTimeToString(out Result: string; const FormatStr: string; const DateTime: TDateTime; const FormatSettings: TFormatSettings);
  771. var
  772. ResultLen: integer;
  773. ResultBuffer: array[0..255] of char;
  774. ResultCurrent: pchar;
  775. {$IFDEF MSWindows}
  776. isEnable_E_Format : Boolean;
  777. isEnable_G_Format : Boolean;
  778. eastasiainited : boolean;
  779. {$ENDIF MSWindows}
  780. {$IFDEF MSWindows}
  781. procedure InitEastAsia;
  782. var ALCID : LCID;
  783. PriLangID , SubLangID : Word;
  784. begin
  785. ALCID := GetThreadLocale;
  786. PriLangID := ALCID and $3FF;
  787. if (PriLangID>0) then
  788. SubLangID := (ALCID and $FFFF) shr 10
  789. else
  790. begin
  791. PriLangID := SysLocale.PriLangID;
  792. SubLangID := SysLocale.SubLangID;
  793. end;
  794. isEnable_E_Format := (PriLangID = LANG_JAPANESE)
  795. or
  796. (PriLangID = LANG_KOREAN)
  797. or
  798. ((PriLangID = LANG_CHINESE)
  799. and
  800. (SubLangID = SUBLANG_CHINESE_TRADITIONAL)
  801. );
  802. isEnable_G_Format := (PriLangID = LANG_JAPANESE)
  803. or
  804. ((PriLangID = LANG_CHINESE)
  805. and
  806. (SubLangID = SUBLANG_CHINESE_TRADITIONAL)
  807. );
  808. eastasiainited :=true;
  809. end;
  810. {$ENDIF MSWindows}
  811. procedure StoreStr(Str: PChar; Len: Integer);
  812. begin
  813. if ResultLen + Len < SizeOf(ResultBuffer) then
  814. begin
  815. StrMove(ResultCurrent, Str, Len);
  816. ResultCurrent := ResultCurrent + Len;
  817. ResultLen := ResultLen + Len;
  818. end;
  819. end;
  820. procedure StoreString(const Str: string);
  821. var Len: integer;
  822. begin
  823. Len := Length(Str);
  824. if ResultLen + Len < SizeOf(ResultBuffer) then
  825. begin
  826. StrMove(ResultCurrent, pchar(Str), Len);
  827. ResultCurrent := ResultCurrent + Len;
  828. ResultLen := ResultLen + Len;
  829. end;
  830. end;
  831. procedure StoreInt(Value, Digits: Integer);
  832. var
  833. S: string[16];
  834. Len: integer;
  835. begin
  836. System.Str(Value:Digits, S);
  837. for Len := 1 to Length(S) do
  838. begin
  839. if S[Len] = ' ' then
  840. S[Len] := '0'
  841. else
  842. Break;
  843. end;
  844. StoreStr(pchar(@S[1]), Length(S));
  845. end ;
  846. var
  847. Year, Month, Day, DayOfWeek, Hour, Minute, Second, MilliSecond: word;
  848. DT : TDateTime;
  849. procedure StoreFormat(const FormatStr: string; Nesting: Integer; TimeFlag: Boolean);
  850. var
  851. Token, lastformattoken: char;
  852. FormatCurrent: pchar;
  853. FormatEnd: pchar;
  854. Count: integer;
  855. Clock12: boolean;
  856. P: pchar;
  857. tmp: integer;
  858. begin
  859. if Nesting > 1 then // 0 is original string, 1 is included FormatString
  860. Exit;
  861. FormatCurrent := PChar(FormatStr);
  862. FormatEnd := FormatCurrent + Length(FormatStr);
  863. Clock12 := false;
  864. P := FormatCurrent;
  865. // look for unquoted 12-hour clock token
  866. while P < FormatEnd do
  867. begin
  868. Token := P^;
  869. case Token of
  870. '''', '"':
  871. begin
  872. Inc(P);
  873. while (P < FormatEnd) and (P^ <> Token) do
  874. Inc(P);
  875. end;
  876. 'A', 'a':
  877. begin
  878. if (StrLIComp(P, 'A/P', 3) = 0) or
  879. (StrLIComp(P, 'AMPM', 4) = 0) or
  880. (StrLIComp(P, 'AM/PM', 5) = 0) then
  881. begin
  882. Clock12 := true;
  883. break;
  884. end;
  885. end;
  886. end; // case
  887. Inc(P);
  888. end ;
  889. token := #255;
  890. lastformattoken := ' ';
  891. while FormatCurrent < FormatEnd do
  892. begin
  893. Token := UpCase(FormatCurrent^);
  894. Count := 1;
  895. P := FormatCurrent + 1;
  896. case Token of
  897. '''', '"':
  898. begin
  899. while (P < FormatEnd) and (p^ <> Token) do
  900. Inc(P);
  901. Inc(P);
  902. Count := P - FormatCurrent;
  903. StoreStr(FormatCurrent + 1, Count - 2);
  904. end ;
  905. 'A':
  906. begin
  907. if StrLIComp(FormatCurrent, 'AMPM', 4) = 0 then
  908. begin
  909. Count := 4;
  910. if Hour < 12 then
  911. StoreString(FormatSettings.TimeAMString)
  912. else
  913. StoreString(FormatSettings.TimePMString);
  914. end
  915. else if StrLIComp(FormatCurrent, 'AM/PM', 5) = 0 then
  916. begin
  917. Count := 5;
  918. if Hour < 12 then StoreStr(FormatCurrent, 2)
  919. else StoreStr(FormatCurrent+3, 2);
  920. end
  921. else if StrLIComp(FormatCurrent, 'A/P', 3) = 0 then
  922. begin
  923. Count := 3;
  924. if Hour < 12 then StoreStr(FormatCurrent, 1)
  925. else StoreStr(FormatCurrent+2, 1);
  926. end
  927. else
  928. raise EConvertError.Create('Illegal character in format string');
  929. end ;
  930. '/': StoreStr(@FormatSettings.DateSeparator, 1);
  931. ':': StoreStr(@FormatSettings.TimeSeparator, 1);
  932. ' ', 'C', 'D', 'H', 'M', 'N', 'S', 'T', 'Y', 'Z', 'F' :
  933. begin
  934. while (P < FormatEnd) and (UpCase(P^) = Token) do
  935. Inc(P);
  936. Count := P - FormatCurrent;
  937. case Token of
  938. ' ': StoreStr(FormatCurrent, Count);
  939. 'Y': begin
  940. if Count > 2 then
  941. StoreInt(Year, 4)
  942. else
  943. StoreInt(Year mod 100, 2);
  944. end;
  945. 'M': begin
  946. if (lastformattoken = 'H') or TimeFlag then
  947. begin
  948. if Count = 1 then
  949. StoreInt(Minute, 0)
  950. else
  951. StoreInt(Minute, 2);
  952. end
  953. else
  954. begin
  955. case Count of
  956. 1: StoreInt(Month, 0);
  957. 2: StoreInt(Month, 2);
  958. 3: StoreString(FormatSettings.ShortMonthNames[Month]);
  959. else
  960. StoreString(FormatSettings.LongMonthNames[Month]);
  961. end;
  962. end;
  963. end;
  964. 'D': begin
  965. case Count of
  966. 1: StoreInt(Day, 0);
  967. 2: StoreInt(Day, 2);
  968. 3: StoreString(FormatSettings.ShortDayNames[DayOfWeek]);
  969. 4: StoreString(FormatSettings.LongDayNames[DayOfWeek]);
  970. 5: StoreFormat(FormatSettings.ShortDateFormat, Nesting+1, False);
  971. else
  972. StoreFormat(FormatSettings.LongDateFormat, Nesting+1, False);
  973. end ;
  974. end ;
  975. 'H': if Clock12 then
  976. begin
  977. tmp := hour mod 12;
  978. if tmp=0 then tmp:=12;
  979. if Count = 1 then
  980. StoreInt(tmp, 0)
  981. else
  982. StoreInt(tmp, 2);
  983. end
  984. else begin
  985. if Count = 1 then
  986. StoreInt(Hour, 0)
  987. else
  988. StoreInt(Hour, 2);
  989. end;
  990. 'N': if Count = 1 then
  991. StoreInt(Minute, 0)
  992. else
  993. StoreInt(Minute, 2);
  994. 'S': if Count = 1 then
  995. StoreInt(Second, 0)
  996. else
  997. StoreInt(Second, 2);
  998. 'Z': if Count = 1 then
  999. StoreInt(MilliSecond, 0)
  1000. else
  1001. StoreInt(MilliSecond, 3);
  1002. 'T': if Count = 1 then
  1003. StoreFormat(FormatSettings.ShortTimeFormat, Nesting+1, True)
  1004. else
  1005. StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True);
  1006. 'C': begin
  1007. StoreFormat(FormatSettings.ShortDateFormat, Nesting+1, False);
  1008. if (Hour<>0) or (Minute<>0) or (Second<>0) then
  1009. begin
  1010. StoreString(' ');
  1011. StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True);
  1012. end;
  1013. end;
  1014. 'F': begin
  1015. StoreFormat(FormatSettings.ShortDateFormat, Nesting+1, False);
  1016. StoreString(' ');
  1017. StoreFormat(FormatSettings.LongTimeFormat, Nesting+1, True);
  1018. end;
  1019. {$IFDEF MSWindows}
  1020. 'E':
  1021. begin
  1022. if not Eastasiainited then InitEastAsia;
  1023. if Not(isEnable_E_Format) then StoreStr(@FormatCurrent^, 1)
  1024. else
  1025. begin
  1026. while (P < FormatEnd) and (UpCase(P^) = Token) do
  1027. P := P + 1;
  1028. Count := P - FormatCurrent;
  1029. StoreString(ConvertEraYearString(Count,Year,Month,Day));
  1030. end;
  1031. lastformattoken:=token;
  1032. end;
  1033. 'G':
  1034. begin
  1035. if not Eastasiainited then InitEastAsia;
  1036. if Not(isEnable_G_Format) then StoreStr(@FormatCurrent^, 1)
  1037. else
  1038. begin
  1039. while (P < FormatEnd) and (UpCase(P^) = Token) do
  1040. P := P + 1;
  1041. Count := P - FormatCurrent;
  1042. StoreString(ConvertEraString(Count,Year,Month,Day));
  1043. end;
  1044. lastformattoken:=token;
  1045. end;
  1046. {$ENDIF MSWindows}
  1047. end;
  1048. lastformattoken := token;
  1049. end;
  1050. else
  1051. StoreStr(@Token, 1);
  1052. end ;
  1053. Inc(FormatCurrent, Count);
  1054. end;
  1055. end;
  1056. begin
  1057. {$ifdef MSWindows}
  1058. eastasiainited:=false;
  1059. {$endif MSWindows}
  1060. DecodeDateFully(DateTime, Year, Month, Day, DayOfWeek);
  1061. DecodeTime(DateTime, Hour, Minute, Second, MilliSecond);
  1062. ResultLen := 0;
  1063. ResultCurrent := @ResultBuffer[0];
  1064. if FormatStr <> '' then
  1065. StoreFormat(FormatStr, 0, False)
  1066. else
  1067. StoreFormat('C', 0, False);
  1068. ResultBuffer[ResultLen] := #0;
  1069. result := StrPas(@ResultBuffer[0]);
  1070. end ;
  1071. Function DateTimeToFileDate(DateTime : TDateTime) : Longint;
  1072. Var YY,MM,DD,H,m,s,msec : Word;
  1073. begin
  1074. Decodedate (DateTime,YY,MM,DD);
  1075. DecodeTime (DateTime,h,m,s,msec);
  1076. {$ifndef unix}
  1077. If (YY<1980) or (YY>2099) then
  1078. Result:=0
  1079. else
  1080. begin
  1081. Result:=(s shr 1) or (m shl 5) or (h shl 11);
  1082. Result:=Result or longint(DD shl 16 or (MM shl 21) or (word(YY-1980) shl 25));
  1083. end;
  1084. {$else unix}
  1085. Result:=LocalToEpoch(yy,mm,dd,h,m,s);
  1086. {$endif unix}
  1087. end;
  1088. function CurrentYear: Word;
  1089. var
  1090. SysTime: TSystemTime;
  1091. begin
  1092. GetLocalTime(SysTime);
  1093. Result := SysTime.Year;
  1094. end;
  1095. Function FileDateToDateTime (Filedate : Longint) : TDateTime;
  1096. {$ifndef unix}
  1097. Var Date,Time : Word;
  1098. begin
  1099. Date:=FileDate shr 16;
  1100. Time:=FileDate and $ffff;
  1101. Result:=ComposeDateTime(EncodeDate((Date shr 9) + 1980,(Date shr 5) and 15, Date and 31),
  1102. EncodeTime(Time shr 11, (Time shr 5) and 63, (Time and 31) shl 1,0));
  1103. end;
  1104. {$else unix}
  1105. var
  1106. y, mon, d, h, min, s: word;
  1107. begin
  1108. EpochToLocal(FileDate,y,mon,d,h,min,s);
  1109. Result:=ComposeDateTime(EncodeDate(y,mon,d),EncodeTime(h,min,s,0));
  1110. end;
  1111. {$endif unix}
  1112. function TryStrToDate(const S: ShortString; out Value: TDateTime): Boolean;
  1113. begin
  1114. result := TryStrToDate(S, Value, #0);
  1115. end;
  1116. function TryStrToDate(const S: ShortString; out Value: TDateTime;
  1117. const useformat : string; separator : char = #0): Boolean;
  1118. Var
  1119. Msg : Ansistring;
  1120. begin
  1121. Value:=IntStrToDate(Msg,@S[1],Length(S),useformat,defaultformatsettings,separator);
  1122. Result:=(Msg='');
  1123. end;
  1124. function TryStrToDate(const S: AnsiString; out Value: TDateTime;
  1125. const useformat : string; separator : char = #0): Boolean;
  1126. Var
  1127. Msg : Ansistring;
  1128. begin
  1129. Result:=Length(S)<>0;
  1130. If Result then
  1131. begin
  1132. Value:=IntStrToDate(Msg,@S[1],Length(S),useformat,DefaultFormatSettings,Separator);
  1133. Result:=(Msg='');
  1134. end;
  1135. end;
  1136. function TryStrToDate(const S: ShortString; out Value: TDateTime; separator : char): Boolean;
  1137. begin
  1138. Result:=TryStrToDate(S,Value,DefaultFormatSettings.ShortDateFormat,Separator);
  1139. end;
  1140. function TryStrToDate(const S: AnsiString; out Value: TDateTime): Boolean;
  1141. begin
  1142. Result:=TryStrToDate(S,Value,DefaultFormatSettings.ShortDateFormat,#0);
  1143. end;
  1144. function TryStrToDate(const S: AnsiString; out Value: TDateTime; separator : char): Boolean;
  1145. begin
  1146. Result:=TryStrToDate(S,Value,DefaultFormatSettings.ShortDateFormat,Separator);
  1147. end;
  1148. function TryStrToDate(const S: string; out Value: TDateTime; const FormatSettings: TFormatSettings): Boolean;
  1149. Var
  1150. Msg : Ansistring;
  1151. begin
  1152. Result:=Length(S)<>0;
  1153. If Result then
  1154. begin
  1155. Value:=IntStrToDate(Msg,@S[1],Length(S),FormatSettings.ShortDateFormat,FormatSettings,#0);
  1156. Result:=(Msg='');
  1157. end;
  1158. end;
  1159. function TryStrToTime(const S: ShortString; out Value: TDateTime; separator : char): Boolean;
  1160. Var
  1161. Msg : AnsiString;
  1162. begin
  1163. Value:=IntStrToTime(Msg,@S[1],Length(S),DefaultFormatSettings,Separator);
  1164. result:=(Msg='');
  1165. end;
  1166. function TryStrToTime(const S: ShortString; out Value: TDateTime): Boolean;
  1167. begin
  1168. Result := TryStrToTime(S,Value,#0);
  1169. end;
  1170. function TryStrToTime(const S: AnsiString; out Value: TDateTime; separator : char): Boolean;
  1171. Var
  1172. Msg : AnsiString;
  1173. begin
  1174. Result:=Length(S)<>0;
  1175. If Result then
  1176. begin
  1177. Value:=IntStrToTime(Msg,@S[1],Length(S),DefaultFormatSettings,Separator);
  1178. Result:=(Msg='');
  1179. end;
  1180. end;
  1181. function TryStrToTime(const S: AnsiString; out Value: TDateTime): Boolean;
  1182. begin
  1183. result := TryStrToTime(S,Value,#0);
  1184. end;
  1185. function TryStrToTime(const S: string; out Value: TDateTime; const FormatSettings: TFormatSettings): Boolean;
  1186. Var msg : AnsiString;
  1187. begin
  1188. Result:=Length(S)<>0;
  1189. If Result then
  1190. begin
  1191. Value:=IntStrToTime(Msg,@S[1],Length(S),FormatSettings,#0);
  1192. Result:=(Msg='');
  1193. end;
  1194. end;
  1195. function TryStrToDateTime(const S: ShortString; out Value: TDateTime): Boolean;
  1196. begin
  1197. result:=true;
  1198. try
  1199. value:=StrToDateTime(s);
  1200. except
  1201. on EConvertError do
  1202. result:=false
  1203. end;
  1204. end;
  1205. function TryStrToDateTime(const S: AnsiString; out Value: TDateTime): Boolean;
  1206. begin
  1207. result:=true;
  1208. try
  1209. value:=StrToDateTime(s);
  1210. except
  1211. on EConvertError do
  1212. result:=false
  1213. end;
  1214. end;
  1215. function TryStrToDateTime(const S: string; out Value: TDateTime; const FormatSettings: TFormatSettings): Boolean;
  1216. var
  1217. I: integer;
  1218. dtdate, dttime :TDateTime;
  1219. begin
  1220. result:=false;
  1221. I:=Pos(FormatSettings.TimeSeparator,S);
  1222. If (I>0) then
  1223. begin
  1224. While (I>0) and (S[I]<>' ') do
  1225. Dec(I);
  1226. If I>0 then
  1227. begin
  1228. if not TryStrToDate(Copy(S,1,I-1),dtdate,Formatsettings) then
  1229. exit;
  1230. if not TryStrToTime(Copy(S,i+1, Length(S)-i),dttime,Formatsettings) then
  1231. exit;
  1232. Value:=ComposeDateTime(dtdate,dttime);
  1233. result:=true;
  1234. end
  1235. else
  1236. result:=TryStrToTime(s,Value,Formatsettings);
  1237. end
  1238. else
  1239. result:=TryStrToDate(s,Value,Formatsettings);
  1240. end;
  1241. function StrToDateDef(const S: ShortString; const Defvalue : TDateTime): TDateTime;
  1242. begin
  1243. result := StrToDateDef(S,DefValue,#0);
  1244. end;
  1245. function StrToTimeDef(const S: ShortString; const Defvalue : TDateTime): TDateTime;
  1246. begin
  1247. result := StrToTimeDef(S,DefValue,#0);
  1248. end;
  1249. function StrToDateTimeDef(const S: ShortString; const Defvalue : TDateTime): TDateTime;
  1250. begin
  1251. if not TryStrToDateTime(s,Result) Then
  1252. result:=defvalue;
  1253. end;
  1254. function StrToDateDef(const S: ShortString; const Defvalue : TDateTime; separator : char): TDateTime;
  1255. begin
  1256. if not TryStrToDate(s,Result, separator) Then
  1257. result:=defvalue;
  1258. end;
  1259. function StrToTimeDef(const S: ShortString; const Defvalue : TDateTime; separator : char): TDateTime;
  1260. begin
  1261. if not TryStrToTime(s,Result, separator) Then
  1262. result:=defvalue;
  1263. end;
  1264. function StrToDateDef(const S: AnsiString; const Defvalue : TDateTime): TDateTime;
  1265. begin
  1266. result := StrToDateDef(S,DefValue,#0);
  1267. end;
  1268. function StrToTimeDef(const S: AnsiString; const Defvalue : TDateTime): TDateTime;
  1269. begin
  1270. result := StrToTimeDef(S,DefValue,#0);
  1271. end;
  1272. function StrToDateTimeDef(const S: AnsiString; const Defvalue : TDateTime): TDateTime;
  1273. begin
  1274. if not TryStrToDateTime(s,Result) Then
  1275. result:=defvalue;
  1276. end;
  1277. function StrToDateDef(const S: AnsiString; const Defvalue : TDateTime; separator : char): TDateTime;
  1278. begin
  1279. if not TryStrToDate(s,Result, separator) Then
  1280. result:=defvalue;
  1281. end;
  1282. function StrToTimeDef(const S: AnsiString; const Defvalue : TDateTime; separator : char): TDateTime;
  1283. begin
  1284. if not TryStrToTime(s,Result, separator) Then
  1285. result:=defvalue;
  1286. end;
  1287. procedure ReplaceTime(var dati:TDateTime; NewTime : TDateTime);inline;
  1288. begin
  1289. dati:= ComposeDateTime(dati, newtime);
  1290. end;
  1291. procedure ReplaceDate(var DateTime: TDateTime; const NewDate: TDateTime); inline;
  1292. var
  1293. tmp : TDateTime;
  1294. begin
  1295. tmp:=NewDate;
  1296. ReplaceTime(tmp,DateTime);
  1297. DateTime:=tmp;
  1298. end;
  1299. {$IFNDEF HAS_LOCALTIMEZONEOFFSET}
  1300. Function GetLocalTimeOffset : Integer;
  1301. begin
  1302. Result:=0;
  1303. end;
  1304. {$ENDIF}