From f3f090d2734207215f8034bb3269622ac036d1b8 Mon Sep 17 00:00:00 2001 From: mattias Date: Sat, 7 Feb 2015 12:00:17 +0000 Subject: [PATCH] codetools: DateToCfgStr extended for time git-svn-id: branches/fixes_1_4@47624 - --- components/codetools/fileprocs.pas | 104 +++++++++++++++++---- test/codetoolstests/testbasiccodetools.pas | 30 ++++++ 2 files changed, 115 insertions(+), 19 deletions(-) diff --git a/components/codetools/fileprocs.pas b/components/codetools/fileprocs.pas index 2c8a945429..1d85b19635 100644 --- a/components/codetools/fileprocs.pas +++ b/components/codetools/fileprocs.pas @@ -236,9 +236,11 @@ function FindNextDelimitedItem(const List: string; Delimiter: char; var Position: integer; FindItem: string): string; inline; function AVLTreeHasDoubles(Tree: TAVLTree): TAVLTreeNode; +// store date locale independent, thread safe const DateAsCfgStrFormat='YYYYMMDD'; -function DateToCfgStr(const Date: TDateTime): string; -function CfgStrToDate(const s: string; out Date: TDateTime): boolean; +const DateTimeAsCfgStrFormat='YYYY/MM/DD HH:NN:SS'; +function DateToCfgStr(const Date: TDateTime; const aFormat: string = DateAsCfgStrFormat): string; +function CfgStrToDate(const s: string; out Date: TDateTime; const aFormat: string = DateAsCfgStrFormat): boolean; function SimpleFormat(const Fmt: String; const Args: Array of const): String; @@ -1855,39 +1857,103 @@ begin end; end; -function DateToCfgStr(const Date: TDateTime): string; +function DateToCfgStr(const Date: TDateTime; const aFormat: string): string; +var + NeedDate: Boolean; + NeedTime: Boolean; + Year: word; + Month: word; + Day: word; + Hour: word; + Minute: word; + Second: word; + MilliSecond: word; + p: Integer; + w: Word; + StartP: Integer; + s: String; + l: Integer; begin - try - Result:=FormatDateTime(DateAsCfgStrFormat,Date); - except - Result:=''; + Result:=aFormat; + NeedDate:=false; + NeedTime:=false; + for p:=1 to length(aFormat) do + case aFormat[p] of + 'Y','M','D': NeedDate:=true; + 'H','N','S','Z': NeedTime:=true; + end; + if NeedDate then + DecodeDate(Trunc(Date),Year,Month,Day); + if NeedTime then + DecodeTime(Frac(Date),Hour,Minute,Second,MilliSecond); + p:=1; + while p<=length(aFormat) do begin + case aFormat[p] of + 'Y': w:=Year; + 'M': w:=Month; + 'D': w:=Day; + 'H': w:=Hour; + 'N': w:=Minute; + 'S': w:=Second; + 'Z': w:=MilliSecond; + else + inc(p); + continue; + end; + StartP:=p; + repeat + inc(p); + until (p>length(aFormat)) or (aFormat[p]<>aFormat[p-1]); + l:=p-StartP; + s:=IntToStr(w); + if length(s)l then + raise Exception.Create('date format does not fit'); + ReplaceSubstring(Result,StartP,l,s); + p:=StartP+length(s); end; //debugln('DateToCfgStr "',Result,'"'); end; -function CfgStrToDate(const s: string; out Date: TDateTime): boolean; +function CfgStrToDate(const s: string; out Date: TDateTime; + const aFormat: string): boolean; + + procedure AddDecimal(var d: word; c: char); inline; + begin + d:=d*10+ord(c)-ord('0'); + end; + var i: Integer; - Year, Month, Day: word; + Year, Month, Day, Hour, Minute, Second, MilliSecond: word; begin //debugln('CfgStrToDate "',s,'"'); - Result:=true; - if length(s)<>length(DateAsCfgStrFormat) then begin - Result:=false; - exit; + if length(s)<>length(aFormat) then begin + Date:=0.0; + exit(false); end; try Year:=0; Month:=0; Day:=0; - for i:=1 to length(DateAsCfgStrFormat) do begin - case DateAsCfgStrFormat[i] of - 'Y': Year:=Year*10+ord(s[i])-ord('0'); - 'M': Month:=Month*10+ord(s[i])-ord('0'); - 'D': Day:=Day*10+ord(s[i])-ord('0'); + Hour:=0; + Minute:=0; + Second:=0; + MilliSecond:=0; + for i:=1 to length(aFormat) do begin + case aFormat[i] of + 'Y': AddDecimal(Year,s[i]); + 'M': AddDecimal(Month,s[i]); + 'D': AddDecimal(Day,s[i]); + 'H': AddDecimal(Hour,s[i]); + 'N': AddDecimal(Minute,s[i]); + 'S': AddDecimal(Second,s[i]); + 'Z': AddDecimal(MilliSecond,s[i]); end; end; - Date:=EncodeDate(Year,Month,Day); + Date:=ComposeDateTime(EncodeDate(Year,Month,Day),EncodeTime(Hour,Minute,Second,MilliSecond)); + Result:=true; except Result:=false; end; diff --git a/test/codetoolstests/testbasiccodetools.pas b/test/codetoolstests/testbasiccodetools.pas index 75da9f1c55..28ca2805f5 100644 --- a/test/codetoolstests/testbasiccodetools.pas +++ b/test/codetoolstests/testbasiccodetools.pas @@ -9,6 +9,7 @@ ./runtests --format=plain --suite=TestGuessIndentSize ./runtests --format=plain --suite=TestReindent ./runtests --format=plain --suite=TestSimpleFormat + ./runtests --format=plain --suite=TestDateToCfgStr } unit TestBasicCodetools; @@ -33,6 +34,7 @@ type procedure TestGuessIndentSize; procedure TestReIndent; procedure TestSimpleFormat; + procedure TestDateToCfgStr; end; implementation @@ -240,6 +242,34 @@ begin t('A%1:s%0:sB',['Foo','Bar'],'ABarFooB'); end; +procedure TTestBasicCodeTools.TestDateToCfgStr; + + procedure t(const Date: TDateTime; const aFormat, Expected: string); + var + Actual: String; + ActualDate: TDateTime; + begin + Actual:=DateToCfgStr(Date,aFormat); + if Actual<>Expected then begin + writeln(dbgsDiff(Expected,Actual)); + AssertEquals('DateToCfgStr failed: Format="'+aFormat+'"',Expected,Actual); + exit; + end; + if (not CfgStrToDate(Actual,ActualDate,aFormat)) then begin + AssertEquals('CfgStrToDate failed: Format="'+aFormat+'" Cfg="'+Actual+'"',false,true); + exit; + end; + if ActualDate<>Date then begin + AssertEquals('CfgStrToDate failed: Format="'+aFormat+'"',DateTimeToStr(ActualDate),DateTimeToStr(Date)); + end; + end; + +begin + t(EncodeDate(1234,12,17),DateAsCfgStrFormat,'12341217'); + t(EncodeDate(1234,1,2),DateAsCfgStrFormat,'12340102'); + t(ComposeDateTime(EncodeDate(1234,1,2),EncodeTime(3,4,5,6)),DateTimeAsCfgStrFormat,'1234/01/02 03:04:05'); +end; + initialization AddToCodetoolsTestSuite(TTestBasicCodeTools);