dati.inc 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404
  1. {
  2. *********************************************************************
  3. Copyright (C) 1997, 1998 Gertjan Schouten
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************
  10. System Utilities For Free Pascal
  11. }
  12. {==============================================================================}
  13. { internal functions }
  14. {==============================================================================}
  15. Function DoEncodeDate(Year, Month, Day: Word): longint;
  16. Var
  17. D : TDateTime;
  18. begin
  19. If TryEncodeDate(Year,Month,Day,D) then
  20. Result:=Trunc(D)
  21. else
  22. Result:=0;
  23. end;
  24. function DoEncodeTime(Hour, Minute, Second, MilliSecond: word): TDateTime;
  25. begin
  26. If not TryEncodeTime(Hour,Minute,Second,MilliSecond,Result) then
  27. Result:=0;
  28. end;
  29. {==============================================================================}
  30. { Public functions }
  31. {==============================================================================}
  32. { ComposeDateTime converts a Date and a Time into one TDateTime }
  33. function ComposeDateTime(Date,Time : TDateTime) : TDateTime;
  34. begin
  35. if Date < 0 then Result := trunc(Date) - Abs(frac(Time))
  36. else Result := trunc(Date) + Abs(frac(Time));
  37. end;
  38. { DateTimeToTimeStamp converts DateTime to a TTimeStamp }
  39. function DateTimeToTimeStamp(DateTime: TDateTime): TTimeStamp;
  40. Var
  41. D : Double;
  42. begin
  43. D:=DateTime * Single(MSecsPerDay);
  44. result.Time := Abs(Round(D)) Mod MSecsPerDay;
  45. result.Date := DateDelta + Round(D) div MSecsPerDay;
  46. end;
  47. { TimeStampToDateTime converts TimeStamp to a TDateTime value }
  48. function TimeStampToDateTime(const TimeStamp: TTimeStamp): TDateTime;
  49. begin
  50. Result := ComposeDateTime(TimeStamp.Date - DateDelta,TimeStamp.Time / MSecsPerDay)
  51. end;
  52. { MSecsToTimeStamp }
  53. function MSecsToTimeStamp(MSecs: comp): TTimeStamp;
  54. begin
  55. result.Date := Trunc(msecs / msecsperday);
  56. msecs:= msecs-comp(result.date)*msecsperday;
  57. result.Time := Round(MSecs);
  58. end ;
  59. { TimeStampToMSecs }
  60. function TimeStampToMSecs(const TimeStamp: TTimeStamp): comp;
  61. begin
  62. result := TimeStamp.Time + comp(timestamp.date)*msecsperday;
  63. end ;
  64. Function TryEncodeDate(Year,Month,Day : Word; Out Date : TDateTime) : Boolean;
  65. var
  66. c, ya: cardinal;
  67. begin
  68. Result:=(Year>0) and (Year<10000) and
  69. (Month in [1..12]) and
  70. (Day>0) and (Day<=MonthDays[IsleapYear(Year),Month]);
  71. If Result then
  72. begin
  73. if month > 2 then
  74. Dec(Month,3)
  75. else
  76. begin
  77. Inc(Month,9);
  78. Dec(Year);
  79. end;
  80. c:= Year DIV 100;
  81. ya:= Year - 100*c;
  82. Date := (146097*c) SHR 2 + (1461*ya) SHR 2 + (153*cardinal(Month)+2) DIV 5 + cardinal(Day);
  83. // Note that this line can't be part of the line above, since TDateTime is
  84. // signed and c and ya are not
  85. Date := Date - 693900;
  86. end
  87. end;
  88. function TryEncodeTime(Hour, Min, Sec, MSec:word; Out Time : TDateTime) : boolean;
  89. begin
  90. Result:=(Hour<24) and (Min<60) and (Sec<60) and (MSec<1000);
  91. If Result then
  92. Time:=TDateTime(cardinal(Hour)*3600000+cardinal(Min)*60000+cardinal(Sec)*1000+MSec)/MSecsPerDay;
  93. end;
  94. { EncodeDate packs three variables Year, Month and Day into a
  95. TDateTime value the result is the number of days since 12/30/1899 }
  96. function EncodeDate(Year, Month, Day: word): TDateTime;
  97. begin
  98. If Not TryEncodeDate(Year,Month,Day,Result) then
  99. Raise EConvertError.CreateFmt('%d-%d-%d is not a valid date specification',
  100. [Year,Month,Day]);
  101. end;
  102. { EncodeTime packs four variables Hour, Minute, Second and MilliSecond into
  103. a TDateTime value }
  104. function EncodeTime(Hour, Minute, Second, MilliSecond:word):TDateTime;
  105. begin
  106. If not TryEncodeTime(Hour,Minute,Second,MilliSecond,Result) then
  107. Raise EConvertError.CreateFmt('%d:%d:%d.%d is not a valid time specification',
  108. [Hour,Minute,Second,MilliSecond]);
  109. end;
  110. { DecodeDate unpacks the value Date into three values:
  111. Year, Month and Day }
  112. procedure DecodeDate(Date: TDateTime; out Year, Month, Day: word);
  113. var
  114. ly,ld,lm,j : cardinal;
  115. begin
  116. if Date <= -datedelta then // If Date is before 1-1-1 then return 0-0-0
  117. begin
  118. Year := 0;
  119. Month := 0;
  120. Day := 0;
  121. end
  122. else
  123. begin
  124. j := pred((Trunc(System.Int(Date)) + 693900) SHL 2);
  125. ly:= j DIV 146097;
  126. j:= j - 146097 * cardinal(ly);
  127. ld := j SHR 2;
  128. j:=(ld SHL 2 + 3) DIV 1461;
  129. ld:= (cardinal(ld) SHL 2 + 7 - 1461*j) SHR 2;
  130. lm:=(5 * ld-3) DIV 153;
  131. ld:= (5 * ld +2 - 153*lm) DIV 5;
  132. ly:= 100 * cardinal(ly) + j;
  133. if lm < 10 then
  134. inc(lm,3)
  135. else
  136. begin
  137. dec(lm,9);
  138. inc(ly);
  139. end;
  140. year:=ly;
  141. month:=lm;
  142. day:=ld;
  143. end;
  144. end;
  145. function DecodeDateFully(const DateTime: TDateTime; out Year, Month, Day, DOW: Word): Boolean;
  146. begin
  147. DecodeDate(DateTime,Year,Month,Day);
  148. DOW:=DayOfWeek(DateTime);
  149. Result:=IsLeapYear(Year);
  150. end;
  151. { DecodeTime unpacks Time into four values:
  152. Hour, Minute, Second and MilliSecond }
  153. procedure DecodeTime(Time: TDateTime; out Hour, Minute, Second, MilliSecond: word);
  154. Var
  155. l : cardinal;
  156. begin
  157. l := DateTimeToTimeStamp(Time).Time;
  158. Hour := l div 3600000;
  159. l := l mod 3600000;
  160. Minute := l div 60000;
  161. l := l mod 60000;
  162. Second := l div 1000;
  163. l := l mod 1000;
  164. MilliSecond := l;
  165. end;
  166. { DateTimeToSystemTime converts DateTime value to SystemTime }
  167. procedure DateTimeToSystemTime(DateTime: TDateTime; out SystemTime: TSystemTime);
  168. begin
  169. DecodeDate(DateTime, SystemTime.Year, SystemTime.Month, SystemTime.Day);
  170. DecodeTime(DateTime, SystemTime.Hour, SystemTime.Minute, SystemTime.Second, SystemTime.MilliSecond);
  171. end ;
  172. { SystemTimeToDateTime converts SystemTime to a TDateTime value }
  173. function SystemTimeToDateTime(const SystemTime: TSystemTime): TDateTime;
  174. begin
  175. result := ComposeDateTime(DoEncodeDate(SystemTime.Year, SystemTime.Month, SystemTime.Day),
  176. DoEncodeTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second, SystemTime.MilliSecond));
  177. end ;
  178. { DayOfWeek returns the Day of the week (sunday is day 1) }
  179. function DayOfWeek(DateTime: TDateTime): integer;
  180. begin
  181. Result := 1 + ((Trunc(DateTime) - 1) mod 7);
  182. If (Result<=0) then
  183. Inc(Result,7);
  184. end;
  185. { Date returns the current Date }
  186. function Date: TDateTime;
  187. var
  188. SystemTime: TSystemTime;
  189. begin
  190. GetLocalTime(SystemTime);
  191. result := DoEncodeDate(SystemTime.Year, SystemTime.Month, SystemTime.Day);
  192. end ;
  193. { Time returns the current Time }
  194. function Time: TDateTime;
  195. var
  196. SystemTime: TSystemTime;
  197. begin
  198. GetLocalTime(SystemTime);
  199. Result := DoEncodeTime(SystemTime.Hour,SystemTime.Minute,SystemTime.Second,SystemTime.MilliSecond);
  200. end ;
  201. { Now returns the current Date and Time }
  202. function Now: TDateTime;
  203. var
  204. SystemTime: TSystemTime;
  205. begin
  206. GetLocalTime(SystemTime);
  207. result := systemTimeToDateTime(SystemTime);
  208. end;
  209. { IncMonth increments DateTime with NumberOfMonths months,
  210. NumberOfMonths can be less than zero }
  211. function IncMonth(const DateTime: TDateTime; NumberOfMonths: integer = 1 ): TDateTime;
  212. var
  213. Year, Month, Day : word;
  214. begin
  215. DecodeDate(DateTime, Year, Month, Day);
  216. IncAMonth(Year, Month, Day, NumberOfMonths);
  217. result := ComposeDateTime(DoEncodeDate(Year, Month, Day), DateTime);
  218. end ;
  219. { IncAMonth is the same as IncMonth, but operates on decoded date }
  220. procedure IncAMonth(var Year, Month, Day: Word; NumberOfMonths: Integer = 1);
  221. var
  222. TempMonth, S: Integer;
  223. begin
  224. If NumberOfMonths>=0 then
  225. s:=1
  226. else
  227. s:=-1;
  228. inc(Year,(NumberOfMonths div 12));
  229. TempMonth:=Month+(NumberOfMonths mod 12)-1;
  230. if (TempMonth>11) or
  231. (TempMonth<0) then
  232. begin
  233. Dec(TempMonth, S*12);
  234. Inc(Year, S);
  235. end;
  236. Month:=TempMonth+1; { Months from 1 to 12 }
  237. If (Day>MonthDays[IsLeapYear(Year)][Month]) then
  238. Day:=MonthDays[IsLeapYear(Year)][Month];
  239. end;
  240. { IsLeapYear returns true if Year is a leap year }
  241. function IsLeapYear(Year: Word): boolean;
  242. begin
  243. Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));
  244. end;
  245. { DateToStr returns a string representation of Date using ShortDateFormat }
  246. function DateToStr(Date: TDateTime): string;
  247. begin
  248. DateTimeToString(Result, 'ddddd', Date);
  249. end ;
  250. function DateToStr(Date: TDateTime; const FormatSettings: TFormatSettings): string;
  251. begin
  252. DateTimeToString(result, FormatSettings.ShortDateFormat, Date, FormatSettings);
  253. end;
  254. { TimeToStr returns a string representation of Time using LongTimeFormat }
  255. function TimeToStr(Time: TDateTime): string;
  256. begin
  257. DateTimeToString(Result, 'tt', Time);
  258. end ;
  259. function TimeToStr(Time: TDateTime; const FormatSettings: TFormatSettings): string;
  260. begin
  261. DateTimeToString(Result, FormatSettings.LongTimeFormat, Time, FormatSettings);
  262. end;
  263. { DateTimeToStr returns a string representation of DateTime using LongDateTimeFormat }
  264. function DateTimeToStr(DateTime: TDateTime): string;
  265. begin
  266. DateTimeToString(Result, 'c', DateTime);
  267. end ;
  268. function DateTimeToStr(DateTime: TDateTime; const FormatSettings: TFormatSettings): string;
  269. begin
  270. DateTimeToString(Result, 'c', DateTime ,FormatSettings);
  271. end;
  272. { StrToDate converts the string S to a TDateTime value
  273. if S does not represent a valid date value
  274. an EConvertError will be raised }
  275. function IntStrToDate(Out ErrorMsg : AnsiString; const S: PChar; Len : integer; const useformat : string; const defs:TFormatSettings; separator : char = #0): TDateTime;
  276. const SInvalidDateFormat = '"%s" is not a valid date format';
  277. procedure FixErrorMsg(const errm :ansistring;const errmarg : ansistring);
  278. begin
  279. errormsg:=format(errm,[errmarg]);
  280. end;
  281. var
  282. df:string;
  283. d,m,y,ly:word;
  284. n,i:longint;
  285. c:word;
  286. dp,mp,yp,which : Byte;
  287. s1:string[4];
  288. values:array[0..3] of longint;
  289. LocalTime:tsystemtime;
  290. YearMoreThenTwoDigits : boolean;
  291. begin
  292. ErrorMsg:=''; Result:=0;
  293. if (Len=0) then
  294. begin
  295. FixErrorMsg(SInvalidDateFormat,'');
  296. exit;
  297. end;
  298. YearMoreThenTwoDigits := False;
  299. if separator = #0 then
  300. separator := defs.DateSeparator;
  301. df := UpperCase(useFormat);
  302. { Determine order of D,M,Y }
  303. yp:=0;
  304. mp:=0;
  305. dp:=0;
  306. Which:=0;
  307. i:=0;
  308. while (i<Length(df)) and (Which<3) do
  309. begin
  310. inc(i);
  311. Case df[i] of
  312. 'Y' :
  313. if yp=0 then
  314. begin
  315. Inc(Which);
  316. yp:=which;
  317. end;
  318. 'M' :
  319. if mp=0 then
  320. begin
  321. Inc(Which);
  322. mp:=which;
  323. end;
  324. 'D' :
  325. if dp=0 then
  326. begin
  327. Inc(Which);
  328. dp:=which;
  329. end;
  330. end;
  331. end;
  332. for i := 1 to 3 do
  333. values[i] := 0;
  334. s1 := '';
  335. n := 0;
  336. dec(len);
  337. for i := 0 to len do
  338. begin
  339. if s[i] in ['0'..'9'] then
  340. s1 := s1 + s[i];
  341. { space can be part of the shortdateformat, and is defaultly in slovak
  342. windows, therefor it shouldn't be taken as separator (unless so specified)
  343. and ignored }
  344. if (Separator <> ' ') and (s[i] = ' ') then
  345. Continue;
  346. if (s[i] = separator) or ((i = len) and (s[i] in ['0'..'9'])) then
  347. begin
  348. inc(n);
  349. if n>3 then
  350. begin
  351. FixErrorMsg(SInvalidDateFormat,s);
  352. exit;
  353. end;
  354. // Check if the year has more then two digits (if n=yp, then we are evaluating the year.)
  355. if (n=yp) and (length(s1)>2) then YearMoreThenTwoDigits := True;
  356. val(s1, values[n], c);
  357. if c<>0 then
  358. begin
  359. FixErrorMsg(SInvalidDateFormat,s);
  360. Exit;
  361. end;
  362. s1 := '';
  363. end
  364. else if not (s[i] in ['0'..'9']) then
  365. begin
  366. FixErrorMsg(SInvalidDateFormat,s);
  367. Exit;
  368. end;
  369. end ;
  370. if (Which<3) and (N>Which) then
  371. begin
  372. FixErrorMsg(SInvalidDateFormat,s);
  373. Exit;
  374. end;
  375. // Fill in values.
  376. getLocalTime(LocalTime);
  377. ly := LocalTime.Year;
  378. If N=3 then
  379. begin
  380. y:=values[yp];
  381. m:=values[mp];
  382. d:=values[dp];
  383. end
  384. Else
  385. begin
  386. Y:=ly;
  387. If n<2 then
  388. begin
  389. d:=values[1];
  390. m := LocalTime.Month;
  391. end
  392. else
  393. If dp<mp then
  394. begin
  395. d:=values[1];
  396. m:=values[2];
  397. end
  398. else
  399. begin
  400. d:=values[2];
  401. m:=values[1];
  402. end;
  403. end;
  404. if (y >= 0) and (y < 100) and not YearMoreThenTwoDigits then
  405. begin
  406. ly := ly - defs.TwoDigitYearCenturyWindow;
  407. Inc(Y, ly div 100 * 100);
  408. if (defs.TwoDigitYearCenturyWindow > 0) and (Y < ly) then
  409. Inc(Y, 100);
  410. end;
  411. if not TryEncodeDate(y, m, d, result) then
  412. errormsg:='Invalid date';
  413. end;
  414. function StrToDate(const S: PChar; Len : integer; const useformat : string; separator : char = #0): TDateTime;
  415. Var
  416. MSg : AnsiString;
  417. begin
  418. Result:=IntStrToDate(Msg,S,Len,useFormat,DefaultFormatSettings,Separator);
  419. If (Msg<>'') then
  420. Raise EConvertError.Create(Msg);
  421. end;
  422. function StrToDate(const S: ShortString; const useformat : string; separator : char = #0): TDateTime;
  423. begin
  424. result := StrToDate(@S[1],Length(s),UseFormat,separator);
  425. end;
  426. function StrToDate(const S: AnsiString; const useformat : string; separator : char = #0): TDateTime;
  427. begin
  428. result := StrToDate(@S[1],Length(s),UseFormat,separator);
  429. end;
  430. function StrToDate(const S: ShortString; separator : char): TDateTime;
  431. begin
  432. result := StrToDate(@S[1],Length(s),DefaultFormatSettings.ShortDateFormat,separator)
  433. end;
  434. function StrToDate(const S: ShortString): TDateTime;
  435. begin
  436. result := StrToDate(@S[1],Length(s),DefaultFormatSettings.ShortDateFormat,#0);
  437. end;
  438. function StrToDate(const S: AnsiString; separator : char): TDateTime;
  439. begin
  440. result := StrToDate(@S[1],Length(s),DefaultFormatSettings.ShortDateFormat,separator)
  441. end;
  442. function StrToDate(const S: AnsiString): TDateTime;
  443. begin
  444. result := StrToDate(@S[1],Length(s),DefaultFormatSettings.ShortDateFormat,#0);
  445. end;
  446. { StrToTime converts the string S to a TDateTime value
  447. if S does not represent a valid time value an
  448. EConvertError will be raised }
  449. function IntStrToTime(Out ErrorMsg : AnsiString; const S: PChar; Len : integer;const defs:TFormatSettings; separator : char = #0): TDateTime;
  450. const
  451. AMPM_None = 0;
  452. AMPM_AM = 1;
  453. AMPM_PM = 2;
  454. tiHour = 0;
  455. tiMin = 1;
  456. tiSec = 2;
  457. tiMSec = 3;
  458. type
  459. TTimeValues = array[tiHour..tiMSec] of Word;
  460. var
  461. AmPm: integer;
  462. TimeValues: TTimeValues;
  463. function StrPas(Src : PChar; len: integer = 0) : ShortString;
  464. begin
  465. //this is unsafe for len > 255, it will trash memory (I tested this)
  466. //reducing it is safe, since whenever we use this a string > 255 is invalid anyway
  467. if len > 255 then len := 255;
  468. SetLength(Result, len);
  469. move(src[0],result[1],len);
  470. end;
  471. function SplitElements(out TimeValues: TTimeValues; out AmPm: Integer): Boolean;
  472. //Strict version. It does not allow #32 as Separator, it will treat it as whitespace always
  473. const
  474. Digits = ['0'..'9'];
  475. var
  476. Cur, Offset, ElemLen, Err, TimeIndex, FirstSignificantDigit: Integer;
  477. Value: Word;
  478. DigitPending, MSecPending: Boolean;
  479. AmPmStr: ShortString;
  480. CurChar: Char;
  481. begin
  482. Result := False;
  483. AmPm := AMPM_None; //No Am or PM in string found yet
  484. MSecPending := False;
  485. TimeIndex := 0; //indicating which TTimeValue must be filled next
  486. FillChar(TimeValues, SizeOf(TTimeValues), 0);
  487. Cur := 0;
  488. //skip leading blanks
  489. While (Cur < Len) and (S[Cur] =#32) do Inc(Cur);
  490. Offset := Cur;
  491. //First non-blank cannot be Separator or DecimalSeparator
  492. if (Cur > Len - 1) or (S[Cur] = Separator) or (S[Cur] = defs.Decimalseparator) then Exit;
  493. DigitPending := (S[Cur] in Digits);
  494. While (Cur < Len) do
  495. begin
  496. //writeln;
  497. //writeln('Main While loop: Cur = ',Cur,' S[Cur] = "',S[Cur],'" Len = ',Len);
  498. CurChar := S[Cur];
  499. if CurChar in Digits then
  500. begin//Digits
  501. //HH, MM, SS, or Msec?
  502. //writeln('Digit');
  503. //Digits are only allowed after starting Am/PM or at beginning of string or after Separator
  504. //and TimeIndex must be <= tiMSec
  505. //Uncomment "or (#32 = Separator)" and it will allllow #32 as separator
  506. if (not (DigitPending {or (#32 = Separator)})) or (TimeIndex > tiMSec) then Exit;
  507. OffSet := Cur;
  508. if (CurChar <> '0') then FirstSignificantDigit := OffSet else FirstSignificantDigit := -1;
  509. while (Cur < Len -1) and (S[Cur + 1] in Digits) do
  510. begin
  511. //Mark first Digit that is not '0'
  512. if (FirstSignificantDigit = -1) and (S[Cur] <> '0') then FirstSignificantDigit := Cur;
  513. Inc(Cur);
  514. end;
  515. if (FirstSignificantDigit = -1) then FirstSignificantDigit := Cur;
  516. ElemLen := 1 + Cur - FirstSignificantDigit;
  517. //writeln(' S[FirstSignificantDigit] = ',S[FirstSignificantDigit], ' S[Cur] = ',S[Cur],' ElemLen = ',ElemLen,' -> ', StrPas(S + Offset, ElemLen));
  518. //writeln(' Cur = ',Cur);
  519. //this way we know that Val() will never overflow Value !
  520. if (ElemLen <= 2) or ((ElemLen <= 3) and (TimeIndex = tiMSec) ) then
  521. begin
  522. Val(StrPas(S + FirstSignificantDigit, ElemLen), Value, Err);
  523. //writeln(' Value = ',Value,' HH = ',TimeValues[0],' MM = ',TimeValues[1],' SS = ',TimeValues[2],' MSec = ',Timevalues[3]);
  524. //This is safe now, because we know Value < High(Word)
  525. TimeValues[TimeIndex] := Value;
  526. Inc(TimeIndex);
  527. DigitPending := False;
  528. end
  529. else Exit; //Value to big, so it must be a wrong timestring
  530. end//Digits
  531. else if (CurChar = #32) then
  532. begin
  533. //writeln('#32');
  534. //just skip, but we must adress this, or it will be parsed by either AM/PM or Separator
  535. end
  536. else if (CurChar = Separator) then
  537. begin
  538. //writeln('Separator');
  539. if DigitPending or (TimeIndex > tiSec) then Exit;
  540. DigitPending := True;
  541. MSecPending := False;
  542. end
  543. else if (CurChar = defs.DecimalSeparator) then
  544. begin
  545. //writeln('DecimalSeparator');
  546. if DigitPending or MSecPending or (TimeIndex <> tiMSec) then Exit;
  547. DigitPending := True;
  548. MSecPending := True;
  549. end
  550. else
  551. begin//AM/PM?
  552. //None of the above, so this char _must_ be the start of AM/PM string
  553. //If we already have found AM/PM or we expect a digit then then timestring must be wrong at this point
  554. //writeln('AM/PM?');
  555. if (AmPm <> AMPM_None) or DigitPending then Exit;
  556. OffSet := Cur;
  557. while (Cur < Len -1) and (not (S[Cur + 1] in [Separator, #32, defs.DecimalSeparator]))
  558. and not (S[Cur + 1] in Digits) do Inc(Cur);
  559. ElemLen := 1 + Cur - OffSet;
  560. //writeln(' S[Offset] = ',S[Offset], ' S[Cur] = ',S[Cur],' ElemLen = ',ElemLen,' -> ', StrPas(S + Offset, ElemLen));
  561. //writeln(' Cur = ',Cur);
  562. AmPmStr := StrPas(S + OffSet, ElemLen);
  563. //writeln('AmPmStr = ',ampmstr,' (',length(ampmstr),')');
  564. //We must compare to TimeAMString before hardcoded 'AM' for delphi compatibility
  565. //Also it is perfectly legal, though insane to have TimeAMString = 'PM' and vice versa
  566. if (AnsiCompareText(AmPmStr, defs.TimeAMString) = 0) then AmPm := AMPM_AM
  567. else if (AnsiCompareText(AmPmStr, defs.TimePMString) = 0) then AmPm := AMPM_PM
  568. else if (CompareText(AmPmStr, 'AM') = 0) then AmPm := AMPM_AM
  569. else if (CompareText(AmPmStr, 'PM') = 0) then AmPm := AMPM_PM
  570. else Exit; //If text does not match any of these, timestring must be wrong;
  571. //if AM/PM is at beginning of string, then a digit is mandatory after it
  572. if (TimeIndex = tiHour) then
  573. begin
  574. DigitPending := True;
  575. end
  576. //otherwise, no more TimeValues allowed after this
  577. else
  578. begin
  579. TimeIndex := tiMSec + 1;
  580. DigitPending := False;
  581. end;
  582. end;//AM/PM
  583. Inc(Cur)
  584. end;//while
  585. //If we arrive here, parsing the elements has been successfull
  586. //if not at least Hours specified then input is not valid
  587. //when am/pm is specified Hour must be <= 12 and not 0
  588. if (TimeIndex = tiHour) or ((AmPm <> AMPM_None) and ((TimeValues[tiHour] > 12) or (TimeValues[tiHour] = 0))) or DigitPending then Exit;
  589. Result := True;
  590. end;
  591. begin
  592. if separator = #0 then
  593. separator := defs.TimeSeparator;
  594. AmPm := AMPM_None;
  595. if not SplitElements(TimeValues, AmPm) then
  596. begin
  597. ErrorMsg:=Format(SErrInvalidTimeFormat,[StrPas(S, Len)]);
  598. Exit;
  599. end;
  600. if (AmPm=AMPM_PM) and (TimeValues[tiHour]<>12) then Inc(TimeValues[tiHour], 12)
  601. else if (AmPm=AMPM_AM) and (TimeValues[tiHour]=12) then TimeValues[tiHour]:=0;
  602. if not TryEncodeTime(TimeValues[tiHour], TimeValues[tiMin], TimeValues[tiSec], TimeValues[tiMSec], result) Then
  603. //errormsg:='Invalid time.';
  604. ErrorMsg:=Format(SErrInvalidTimeFormat,[StrPas(S, Len)]);
  605. end ;
  606. function StrToTime(const S: PChar; Len : integer; separator : char = #0): TDateTime;
  607. Var
  608. Msg : AnsiString;
  609. begin
  610. Result:=IntStrToTime(Msg,S,Len,DefaultFormatSettings,Separator);
  611. If (Msg<>'') then
  612. Raise EConvertError.Create(Msg);
  613. end;
  614. function StrToTime(const S: string; FormatSettings : TFormatSettings): TDateTime;
  615. Var
  616. Msg : AnsiString;
  617. begin
  618. Result:=IntStrToTime(Msg, @S[1], length(S), FormatSettings, #0);
  619. If (Msg<>'') then
  620. Raise EConvertError.Create(Msg);
  621. end;
  622. function StrToTime(const s: ShortString; separator : char): TDateTime;
  623. begin
  624. result := StrToTime(@s[1], length(s), separator);
  625. end;
  626. function StrToTime(const s: AnsiString; separator : char): TDateTime;
  627. begin
  628. result := StrToTime(@s[1], length(s), separator);
  629. end;
  630. function StrToTime(const s: ShortString): TDateTime;
  631. begin
  632. result := StrToTime(@s[1], length(s), #0);
  633. end;
  634. function StrToTime(const s: AnsiString): TDateTime;
  635. begin
  636. result := StrToTime(@s[1], length(s), #0);
  637. end;
  638. { StrToDateTime converts the string S to a TDateTime value
  639. if S does not represent a valid date and/or time value
  640. an EConvertError will be raised }
  641. function StrToDateTime(const s: string): TDateTime;
  642. var
  643. I: integer;
  644. begin
  645. I:=Pos(DefaultFormatSettings.TimeSeparator,S);
  646. If (I>0) then
  647. begin
  648. While (I>0) and (S[I]<>' ') do
  649. Dec(I);
  650. If I>0 then
  651. result:=ComposeDateTime(StrToDate(Copy(S,1,I-1)),StrToTime(Copy(S,i+1, Length(S)-i)))
  652. else
  653. result:=StrToTime(S)
  654. end
  655. else
  656. Result:=StrToDate(S);
  657. end;
  658. function StrToDateTime(const s: AnsiString; const FormatSettings : TFormatSettings): TDateTime;
  659. var
  660. I: integer;
  661. begin
  662. I:=Pos(FormatSettings.TimeSeparator,S);
  663. If (I>0) then
  664. begin
  665. While (I>0) and (S[I]<>' ') do
  666. Dec(I);
  667. If I>0 then
  668. result:=ComposeDateTime(StrToDate(Copy(S,1,I-1),FormatSettings.ShortDateFormat,FormatSettings.DateSeparator),
  669. StrToTime(Copy(S,i+1, Length(S)-i),FormatSettings))
  670. else
  671. result:=StrToTime(S,FormatSettings)
  672. end
  673. else
  674. Result:=StrToDate(S,FormatSettings.ShortDateFormat,FormatSettings.DateSeparator);
  675. end;
  676. function StrToDateTime(const s: ShortString; const FormatSettings : TFormatSettings): TDateTime;
  677. var
  678. I: integer;
  679. begin
  680. I:=Pos(FormatSettings.TimeSeparator,S);
  681. If (I>0) then
  682. begin
  683. While (I>0) and (S[I]<>' ') do
  684. Dec(I);
  685. If I>0 then
  686. result:=ComposeDateTime(StrToDate(Copy(S,1,I-1),FormatSettings.ShortDateFormat,FormatSettings.DateSeparator),
  687. StrToTime(Copy(S,i+1, Length(S)-i),FormatSettings.TimeSeparator))
  688. else
  689. result:=StrToTime(S,FormatSettings.TimeSeparator)
  690. end
  691. else
  692. Result:=StrToDate(S,FormatSettings.ShortDateFormat,FormatSettings.DateSeparator);
  693. end;
  694. { FormatDateTime formats DateTime to the given format string FormatStr }
  695. function FormatDateTime(const FormatStr: string; DateTime: TDateTime): string;
  696. begin
  697. DateTimeToString(Result, FormatStr, DateTime, DefaultFormatSettings);
  698. end;
  699. function FormatDateTime(const FormatStr: string; DateTime: TDateTime; const FormatSettings: TFormatSettings): string;
  700. begin
  701. DateTimeToString(Result, FormatStr, DateTime, FormatSettings);
  702. end;
  703. { DateTimeToString formats DateTime to the given format in FormatStr }
  704. procedure DateTimeToString(out Result: string; const FormatStr: string; const DateTime: TDateTime);
  705. begin
  706. DateTimeToString(Result, FormatStr, DateTime, DefaultFormatSettings);
  707. end;
  708. procedure DateTimeToString(out Result: string; const FormatStr: string; const DateTime: TDateTime; const FormatSettings: TFormatSettings);
  709. var
  710. ResultLen: integer;
  711. ResultBuffer: array[0..255] of char;
  712. ResultCurrent: pchar;
  713. {$IFDEF MSWindows}
  714. isEnable_E_Format : Boolean;
  715. isEnable_G_Format : Boolean;
  716. eastasiainited : boolean;
  717. {$ENDIF MSWindows}
  718. {$IFDEF MSWindows}
  719. procedure InitEastAsia;
  720. var ALCID : LCID;
  721. PriLangID , SubLangID : Word;
  722. begin
  723. ALCID := GetThreadLocale;
  724. PriLangID := ALCID and $3FF;
  725. if (PriLangID>0) then
  726. SubLangID := (ALCID and $FFFF) shr 10
  727. else
  728. begin
  729. PriLangID := SysLocale.PriLangID;
  730. SubLangID := SysLocale.SubLangID;
  731. end;
  732. isEnable_E_Format := (PriLangID = LANG_JAPANESE)
  733. or
  734. (PriLangID = LANG_KOREAN)
  735. or
  736. ((PriLangID = LANG_CHINESE)
  737. and
  738. (SubLangID = SUBLANG_CHINESE_TRADITIONAL)
  739. );
  740. isEnable_G_Format := (PriLangID = LANG_JAPANESE)
  741. or
  742. ((PriLangID = LANG_CHINESE)
  743. and
  744. (SubLangID = SUBLANG_CHINESE_TRADITIONAL)
  745. );
  746. eastasiainited :=true;
  747. end;
  748. {$ENDIF MSWindows}
  749. procedure StoreStr(Str: PChar; Len: Integer);
  750. begin
  751. if ResultLen + Len < SizeOf(ResultBuffer) then
  752. begin
  753. StrMove(ResultCurrent, Str, Len);
  754. ResultCurrent := ResultCurrent + Len;
  755. ResultLen := ResultLen + Len;
  756. end;
  757. end;
  758. procedure StoreString(const Str: string);
  759. var Len: integer;
  760. begin
  761. Len := Length(Str);
  762. if ResultLen + Len < SizeOf(ResultBuffer) then
  763. begin
  764. StrMove(ResultCurrent, pchar(Str), Len);
  765. ResultCurrent := ResultCurrent + Len;
  766. ResultLen := ResultLen + Len;
  767. end;
  768. end;
  769. procedure StoreInt(Value, Digits: Integer);
  770. var
  771. S: string[16];
  772. Len: integer;
  773. begin
  774. System.Str(Value:Digits, S);
  775. for Len := 1 to Length(S) do
  776. begin
  777. if S[Len] = ' ' then
  778. S[Len] := '0'
  779. else
  780. Break;
  781. end;
  782. StoreStr(pchar(@S[1]), Length(S));
  783. end ;
  784. var
  785. Year, Month, Day, DayOfWeek, Hour, Minute, Second, MilliSecond: word;
  786. DT : TDateTime;
  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}