dati.inc 40 KB

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