* corrected *Between() functions: add epsilon and truncate, rather than

round the results (bug reported on irc)

git-svn-id: trunk@13107 -
This commit is contained in:
Jonas Maebe 2009-05-06 20:35:20 +00:00
parent 8c898e963a
commit 8193cd175d
2 changed files with 30 additions and 11 deletions

View File

@ -423,6 +423,9 @@ implementation
uses sysconst;
const
TDateTimeEpsilon = 2.2204460493e-16;
{ ---------------------------------------------------------------------
Auxiliary routines
---------------------------------------------------------------------}
@ -1305,49 +1308,49 @@ end;
Function YearsBetween(const ANow, AThen: TDateTime): Integer;
begin
Result:=Round(Abs(DateTimeDiff(ANow,AThen))/ApproxDaysPerYear);
Result:=Trunc((Abs(DateTimeDiff(ANow,AThen))+TDateTimeEpsilon)/ApproxDaysPerYear);
end;
Function MonthsBetween(const ANow, AThen: TDateTime): Integer;
begin
Result:=Round(Abs(DateTimeDiff(ANow,AThen))/ApproxDaysPerMonth);
Result:=Trunc((Abs(DateTimeDiff(ANow,AThen))+TDateTimeEpsilon)/ApproxDaysPerMonth);
end;
Function WeeksBetween(const ANow, AThen: TDateTime): Integer;
begin
Result:=Round(Abs(DateTimeDiff(ANow,AThen))) div 7;
Result:=Trunc(Abs(DateTimeDiff(ANow,AThen))+TDateTimeEpsilon) div 7;
end;
Function DaysBetween(const ANow, AThen: TDateTime): Integer;
begin
Result:=Round(Abs(DateTimeDiff(ANow,AThen)));
Result:=Trunc(Abs(DateTimeDiff(ANow,AThen))+TDateTimeEpsilon);
end;
Function HoursBetween(const ANow, AThen: TDateTime): Int64;
begin
Result:=Round(Abs(DateTimeDiff(ANow,AThen))*HoursPerDay);
Result:=Trunc((Abs(DateTimeDiff(ANow,AThen))+TDateTimeEpsilon)*HoursPerDay);
end;
Function MinutesBetween(const ANow, AThen: TDateTime): Int64;
begin
Result:=Round(Abs(DateTimeDiff(ANow,AThen))*MinsPerDay);
Result:=Trunc((Abs(DateTimeDiff(ANow,AThen))+TDateTimeEpsilon)*MinsPerDay);
end;
Function SecondsBetween(const ANow, AThen: TDateTime): Int64;
begin
Result:=Round(Abs(DateTimeDiff(ANow,AThen))*SecsPerDay);
Result:=Trunc((Abs(DateTimeDiff(ANow,AThen))+TDateTimeEpsilon)*SecsPerDay);
end;
Function MilliSecondsBetween(const ANow, AThen: TDateTime): Int64;
begin
Result:=Round(Abs(DateTimeDiff(ANow,AThen))*MSecsPerDay);
Result:=Trunc((Abs(DateTimeDiff(ANow,AThen))+TDateTimeEpsilon)*MSecsPerDay);
end;

View File

@ -65,14 +65,26 @@ begin
halt(4);
currentDt := EncodeDateTime(1898, 12, 30, 6, 0, 0, 0);
convertedDt := EncodeDateTime(1899, 12, 30, 6, 0, 0, 0);
if (YearsBetween(currentDt,convertedDt)<>1) or
(MonthsBetween(currentDt,convertedDt)<>12) or
{ 0 and 11 rather than 1 and 12, because YearsBetween and MonthsBetween
are averaged over 4 years -> include a leap year }
if (YearsBetween(currentDt,convertedDt)<>0) or
(MonthsBetween(currentDt,convertedDt)<>11) or
(DaysBetween(currentDt,convertedDt)<>365) or
(HoursBetween(currentDt,convertedDt)<>365*24) or
(MinutesBetween(currentDt,convertedDt)<>365*24*60) or
(SecondsBetween(currentDt,convertedDt)<>365*24*60*60) or
(MilliSecondsBetween(currentDt,convertedDt)<>365*24*60*60*1000) then
halt(5);
begin
writeln('between ',s1,' and ',s2);
writeln(YearsBetween(currentDt,convertedDt));
writeln(MonthsBetween(currentDt,convertedDt));
writeln(DaysBetween(currentDt,convertedDt));
writeln(HoursBetween(currentDt,convertedDt));
writeln(MinutesBetween(currentDt,convertedDt));
writeln(SecondsBetween(currentDt,convertedDt));
writeln(MilliSecondsBetween(currentDt,convertedDt));
halt(5);
end;
currentDt := EncodeDateTime(1898, 12, 29, 6, 0, 0, 0);
convertedDt := EncodeDateTime(1899, 12, 30, 6, 0, 0, 0);
if (YearsBetween(currentDt,convertedDt)<>1) or
@ -83,6 +95,10 @@ begin
(SecondsBetween(currentDt,convertedDt)<>366*24*60*60) or
(MilliSecondsBetween(currentDt,convertedDt)<>366*24*60*60*1000) then
halt(6);
currentDt := 39939.796069305557;
convertedDt := 39939.0;
if YearsBetween(currentDt,convertedDt)<>0 then
halt(7);
// convertedDt:=incseconds(currentDt,
end.