dati.inc 40 KB

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