dati.inc 41 KB

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