dati.inc 40 KB

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