dati.inc 41 KB

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