[Lazarus] DateDif function needed
waldo kitty
wkitty42 at windstream.net
Tue Nov 12 21:01:26 CET 2013
On 11/11/2013 6:54 PM, waldo kitty wrote:
> On 11/11/2013 10:46 AM, John Landmesser wrote:
>> Fazit:
>>
>> You can't write a DateDif function with the functions in DateUtils.pas ?!!
>
> actually, you can but it is more brute-force for the results that you and i are
> looking for... brute-force as in actually looping thru each unit and
> incrementing a counter for that part to fill a record of some sort which is then
> used to show the desired counts... i'm working on one as we speak ;)
it is amazing what refinements and streamlining will come up with at times...
originally this was totally brute force... then i started refining and cleaning
it up until i came up with this... it also includes a set of a set of dates for
testing...
===== snip =====
program DateDiff3;
uses
SysUtils,DateUtils,StrUtils;
type
Date_Diff = record
Years,
Months,
Days: Word;
end;
function CalendarDateDiff(Date1,Date2: TDateTime): Date_Diff;
var
theDiffRec: Date_Diff;
Cmp: Integer;
loDate,hiDate: TDateTime;
loYear,hiYear,loMonth,hiMonth,loDay,hiDay: Word;
begin
FillChar(theDiffRec,SizeOf(theDiffRec),0); // init results to zero
Cmp:=CompareDateTime(Date1,Date2); // compare dates
If Cmp<0 then
begin
loDate:= Date1; // and set loDate to oldest
hiDate:= Date2;
end
else if Cmp>0 then
begin
loDate:= Date2; // and set loDate to oldest
hiDate:= Date1;
end;
DecodeDate(loDate,loYear,loMonth,loDay);
DecodeDate(hiDate,hiYear,hiMonth,hiDay);
theDiffRec.Years:= hiYear - loYear;
if (loMonth > hiMonth) or ((loMonth = hiMonth) and (loDay > hiDay)) then
begin
theDiffRec.Years:= theDiffRec.Years - 1;
end;
if loMonth > hiMonth then
begin
hiMonth:= hiMonth + 12;
end;
theDiffRec.Months:= hiMonth - loMonth;
if hiDay >= loDay then
begin
theDiffRec.Days:= hiDay - loDay
end
else
begin
if theDiffRec.Months = 0 then
begin
theDiffRec.Months:= 11;
end
else
begin
theDiffRec.Months:= theDiffRec.Months - 1;
end;
theDiffRec.Days:= DaysInAMonth(hiYear,loMonth) - loDay + hiDay;
end;
Result:= theDiffRec;
end;
procedure Test(D1,D2: TDateTime);
var
DateDiffRec: Date_Diff;
begin
FillChar(DateDiffRec,SizeOf(DateDiffRec),0);
DateDiffRec:= CalendarDateDiff(D1,D2);
writeln(PadLeft(IntToStr(DateDiffRec.Years),4)+' yrs
'+PadLeft(IntToStr(DateDiffRec.Months),4)+' mos
'+PadLeft(IntToStr(DateDiffRec.Days),4)+' days');
end;
type
DateRecord = record
Year,
Month,
Day: Word;
end;
const
TstDates1: array[1..26] of DateRecord = (
(Year:2000;Month:01;Day:01),
(Year:2000;Month:01;Day:02),
(Year:2000;Month:01;Day:31),
(Year:2000;Month:02;Day:01),
(Year:2000;Month:02;Day:28),
(Year:2000;Month:02;Day:29),
(Year:2000;Month:03;Day:01),
(Year:2000;Month:03;Day:15),
(Year:2000;Month:12;Day:31),
(Year:2001;Month:01;Day:01),
(Year:2001;Month:01;Day:02),
(Year:2001;Month:02;Day:01),
(Year:2001;Month:02;Day:28),
(Year:2001;Month:02;Day:29),
(Year:2001;Month:03;Day:01),
(Year:2001;Month:03;Day:15),
(Year:2001;Month:08;Day:01),
(Year:2001;Month:12;Day:31),
(Year:2004;Month:01;Day:01),
(Year:2004;Month:01;Day:02),
(Year:2004;Month:02;Day:01),
(Year:2004;Month:02;Day:28),
(Year:2004;Month:02;Day:29),
(Year:2004;Month:03;Day:01),
(Year:2004;Month:03;Day:15),
(Year:2004;Month:12;Day:31)
);
TstDates2: Array[1..26] of DateRecord = (
(Year:2000;Month:01;Day:01),
(Year:2000;Month:01;Day:02),
(Year:2000;Month:01;Day:31),
(Year:2000;Month:02;Day:01),
(Year:2000;Month:02;Day:28),
(Year:2000;Month:02;Day:29),
(Year:2000;Month:03;Day:01),
(Year:2000;Month:03;Day:15),
(Year:2000;Month:12;Day:31),
(Year:2001;Month:01;Day:01),
(Year:2001;Month:01;Day:02),
(Year:2001;Month:02;Day:01),
(Year:2001;Month:02;Day:28),
(Year:2001;Month:02;Day:29),
(Year:2001;Month:03;Day:01),
(Year:2001;Month:03;Day:15),
(Year:2001;Month:08;Day:01),
(Year:2001;Month:12;Day:31),
(Year:2004;Month:01;Day:01),
(Year:2004;Month:01;Day:02),
(Year:2004;Month:02;Day:01),
(Year:2004;Month:02;Day:28),
(Year:2004;Month:02;Day:29),
(Year:2004;Month:03;Day:01),
(Year:2004;Month:03;Day:15),
(Year:2004;Month:12;Day:31)
);
var
DCnt1,DCnt2: Integer;
DT1,DT2: TDateTime;
DStr1,DStr2: String;
begin
writeln('TstDates1 has ',Length(TstDates1),' records');
writeln('TstDates2 has ',Length(TstDates2),' records');
for DCnt1:= 1 to Length(TstDates1) do
begin
if
IsValidDate(TstDates1[DCnt1].Year,TstDates1[DCnt1].Month,TstDates1[DCnt1].Day) then
begin
DT1:=
EncodeDate(TstDates1[DCnt1].Year,TstDates1[DCnt1].Month,TstDates1[DCnt1].Day);
DStr1:= FormatDateTime('YYYY-MM-DD',DT1);
for DCnt2:= 1 to Length(TstDates2) do
begin
if
IsValidDate(TstDates2[DCnt2].Year,TstDates2[DCnt2].Month,TstDates2[DCnt2].Day) then
begin
DT2:=
EncodeDate(TstDates2[DCnt2].Year,TstDates2[DCnt2].Month,TstDates2[DCnt2].Day);
DStr2:= FormatDateTime('YYYY-MM-DD',DT2);
write(DStr1+' to '+DStr2+' is ');
Test(DT1,DT2); // do the test
end
else
begin
writeln(DStr1+' to
'+PadLeft(IntToStr(TstDates2[DCnt2].Year),4)+'-'+AddChar('0',IntToStr(TstDates2[DCnt2].Month),2)+'-'+AddChar('0',IntToStr(TstDates2[DCnt2].Day),2)+'
invalid ending date');
end;
end;
end
else
begin
writeln(PadLeft(IntToStr(TstDates1[DCnt1].Year),4)+'-'+AddChar('0',IntToStr(TstDates1[DCnt1].Month),2)+'-'+AddChar('0',IntToStr(TstDates1[DCnt1].Day),2)+'
is an invalid starting date');
end;
writeln;
end;
end.
===== snip =====
--
NOTE: No off-list assistance is given without prior approval.
Please keep mailing list traffic on the list unless
private contact is specifically requested and granted.
More information about the Lazarus
mailing list