mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-11 18:49:14 +02:00
* fixed errors in Inc*() routines regarding skipping the black home in the data-time continuum around 0, and the same for the *Between() functions + tests, test... git-svn-id: trunk@12958 -
This commit is contained in:
parent
1c2d2ae481
commit
6a813b8e7b
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -8784,6 +8784,7 @@ tests/webtbs/tw1279.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1283.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1284.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1286.pp svneol=native#text/plain
|
||||
tests/webtbs/tw12894.pp svneol=native#text/plain
|
||||
tests/webtbs/tw12942.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1295.pp svneol=native#text/plain
|
||||
tests/webtbs/tw12985.pp svneol=native#text/plain
|
||||
|
@ -1288,54 +1288,66 @@ end;
|
||||
{
|
||||
These functions are declared as approximate by Borland.
|
||||
A bit strange, since it can be calculated exactly ?
|
||||
|
||||
-- No, because you need rounding or truncating (JM)
|
||||
}
|
||||
|
||||
|
||||
Function DateTimeDiff(const ANow, AThen: TDateTime): TDateTime;
|
||||
begin
|
||||
Result:= ANow - AThen;
|
||||
if (ANow>0) and (AThen<0) then
|
||||
Result:=Result-0.5
|
||||
else if (ANow<-1.0) and (AThen>-1.0) then
|
||||
Result:=Result+0.5;
|
||||
end;
|
||||
|
||||
|
||||
Function YearsBetween(const ANow, AThen: TDateTime): Integer;
|
||||
begin
|
||||
Result:=Trunc(Abs(ANow-AThen)/ApproxDaysPerYear);
|
||||
Result:=Round(Abs(DateTimeDiff(ANow,AThen))/ApproxDaysPerYear);
|
||||
end;
|
||||
|
||||
|
||||
Function MonthsBetween(const ANow, AThen: TDateTime): Integer;
|
||||
begin
|
||||
Result:=Trunc(Abs(ANow-Athen)/ApproxDaysPerMonth);
|
||||
Result:=Round(Abs(DateTimeDiff(ANow,AThen))/ApproxDaysPerMonth);
|
||||
end;
|
||||
|
||||
|
||||
Function WeeksBetween(const ANow, AThen: TDateTime): Integer;
|
||||
begin
|
||||
Result:=Trunc(Abs(ANow-AThen)) div 7;
|
||||
Result:=Round(Abs(DateTimeDiff(ANow,AThen))) div 7;
|
||||
end;
|
||||
|
||||
|
||||
Function DaysBetween(const ANow, AThen: TDateTime): Integer;
|
||||
begin
|
||||
Result:=Trunc(Abs(ANow-AThen));
|
||||
Result:=Round(Abs(DateTimeDiff(ANow,AThen)));
|
||||
end;
|
||||
|
||||
|
||||
Function HoursBetween(const ANow, AThen: TDateTime): Int64;
|
||||
begin
|
||||
Result:=Trunc(Abs(ANow-AThen)*HoursPerDay);
|
||||
Result:=Round(Abs(DateTimeDiff(ANow,AThen))*HoursPerDay);
|
||||
end;
|
||||
|
||||
|
||||
Function MinutesBetween(const ANow, AThen: TDateTime): Int64;
|
||||
begin
|
||||
Result:=Trunc(Abs(ANow-AThen)*MinsPerDay);
|
||||
Result:=Round(Abs(DateTimeDiff(ANow,AThen))*MinsPerDay);
|
||||
end;
|
||||
|
||||
|
||||
Function SecondsBetween(const ANow, AThen: TDateTime): Int64;
|
||||
begin
|
||||
Result:=Trunc(Abs(ANow-AThen)*SecsPerDay);
|
||||
Result:=Round(Abs(DateTimeDiff(ANow,AThen))*SecsPerDay);
|
||||
end;
|
||||
|
||||
|
||||
Function MilliSecondsBetween(const ANow, AThen: TDateTime): Int64;
|
||||
begin
|
||||
Result:=Trunc(Abs(ANow-AThen)*MSecsPerDay);
|
||||
Result:=Round(Abs(DateTimeDiff(ANow,AThen))*MSecsPerDay);
|
||||
end;
|
||||
|
||||
|
||||
@ -1345,49 +1357,49 @@ end;
|
||||
|
||||
Function YearSpan(const ANow, AThen: TDateTime): Double;
|
||||
begin
|
||||
Result:=Abs(Anow-Athen)/ApproxDaysPerYear;
|
||||
Result:=Abs(DateTimeDiff(ANow,AThen))/ApproxDaysPerYear;
|
||||
end;
|
||||
|
||||
|
||||
Function MonthSpan(const ANow, AThen: TDateTime): Double;
|
||||
begin
|
||||
Result:=Abs(ANow-AThen)/ApproxDaysPerMonth;
|
||||
Result:=Abs(DateTimeDiff(ANow,AThen))/ApproxDaysPerMonth;
|
||||
end;
|
||||
|
||||
|
||||
Function WeekSpan(const ANow, AThen: TDateTime): Double;
|
||||
begin
|
||||
Result:=Abs(ANow-AThen) / 7
|
||||
Result:=Abs(DateTimeDiff(ANow,AThen)) / 7
|
||||
end;
|
||||
|
||||
|
||||
Function DaySpan(const ANow, AThen: TDateTime): Double;
|
||||
begin
|
||||
Result:=Abs(ANow-AThen);
|
||||
Result:=Abs(DateTimeDiff(ANow,AThen));
|
||||
end;
|
||||
|
||||
|
||||
Function HourSpan(const ANow, AThen: TDateTime): Double;
|
||||
begin
|
||||
Result:=Abs(ANow-AThen)*HoursPerDay;
|
||||
Result:=Abs(DateTimeDiff(ANow,AThen))*HoursPerDay;
|
||||
end;
|
||||
|
||||
|
||||
Function MinuteSpan(const ANow, AThen: TDateTime): Double;
|
||||
begin
|
||||
Result:=Abs(ANow-AThen)*MinsPerDay;
|
||||
Result:=Abs(DateTimeDiff(ANow,AThen))*MinsPerDay;
|
||||
end;
|
||||
|
||||
|
||||
Function SecondSpan(const ANow, AThen: TDateTime): Double;
|
||||
begin
|
||||
Result:=Abs(ANow-AThen)*SecsPerDay;
|
||||
Result:=Abs(DateTimeDiff(ANow,AThen))*SecsPerDay;
|
||||
end;
|
||||
|
||||
|
||||
Function MilliSecondSpan(const ANow, AThen: TDateTime): Double;
|
||||
begin
|
||||
Result:=Abs(ANow-AThen)*MSecsPerDay;
|
||||
Result:=Abs(DateTimeDiff(ANow,AThen))*MSecsPerDay;
|
||||
end;
|
||||
|
||||
|
||||
@ -1395,13 +1407,19 @@ end;
|
||||
Increment/decrement functions.
|
||||
---------------------------------------------------------------------}
|
||||
|
||||
Procedure MaybeSkipTimeWarp(OldDate: TDateTime; var NewDate: TDateTime);
|
||||
begin
|
||||
if (OldDate>0) and (NewDate<0) then
|
||||
NewDate:=NewDate-0.5
|
||||
else if (OldDate<-1.0) and (NewDate>-1.0) then
|
||||
NewDate:=NewDate+0.5;
|
||||
end;
|
||||
|
||||
|
||||
Function IncYear(const AValue: TDateTime; const ANumberOfYears: Integer ): TDateTime;
|
||||
|
||||
Var
|
||||
Y,M,D,H,N,S,MS : Word;
|
||||
|
||||
|
||||
begin
|
||||
DecodeDateTime(AValue,Y,M,D,H,N,S,MS);
|
||||
Y:=Y+ANumberOfYears;
|
||||
@ -1420,6 +1438,7 @@ end;
|
||||
Function IncWeek(const AValue: TDateTime; const ANumberOfWeeks: Integer): TDateTime;
|
||||
begin
|
||||
Result:=AValue+ANumberOfWeeks*7;
|
||||
MaybeSkipTimeWarp(AValue,Result);
|
||||
end;
|
||||
|
||||
|
||||
@ -1432,6 +1451,7 @@ end;
|
||||
Function IncDay(const AValue: TDateTime; const ANumberOfDays: Integer): TDateTime;
|
||||
begin
|
||||
Result:=AValue+ANumberOfDays;
|
||||
MaybeSkipTimeWarp(AValue,Result);
|
||||
end;
|
||||
|
||||
|
||||
@ -1444,6 +1464,7 @@ end;
|
||||
Function IncHour(const AValue: TDateTime; const ANumberOfHours: Int64): TDateTime;
|
||||
begin
|
||||
Result:=AValue+ANumberOfHours/HoursPerDay;
|
||||
MaybeSkipTimeWarp(AValue,Result);
|
||||
end;
|
||||
|
||||
|
||||
@ -1456,6 +1477,7 @@ end;
|
||||
Function IncMinute(const AValue: TDateTime; const ANumberOfMinutes: Int64): TDateTime;
|
||||
begin
|
||||
Result:=AValue+ANumberOfMinutes / MinsPerDay;
|
||||
MaybeSkipTimeWarp(AValue,Result);
|
||||
end;
|
||||
|
||||
|
||||
@ -1468,6 +1490,7 @@ end;
|
||||
Function IncSecond(const AValue: TDateTime; const ANumberOfSeconds: Int64): TDateTime;
|
||||
begin
|
||||
Result:=AValue+ANumberOfSeconds / SecsPerDay;
|
||||
MaybeSkipTimeWarp(AValue,Result);
|
||||
end;
|
||||
|
||||
|
||||
@ -1480,6 +1503,7 @@ end;
|
||||
Function IncMilliSecond(const AValue: TDateTime; const ANumberOfMilliSeconds: Int64): TDateTime;
|
||||
begin
|
||||
Result:=AValue+ANumberOfMilliSeconds/MSecsPerDay;
|
||||
MaybeSkipTimeWarp(AValue,Result);
|
||||
end;
|
||||
|
||||
|
||||
@ -1799,7 +1823,7 @@ Var
|
||||
Y,M,D,H,N,S,MS : Word;
|
||||
|
||||
begin
|
||||
DecodeDateTime(AValue,Y,M,D,H,N,S,MS);
|
||||
DecodeDateTime(AValue,Y,M,D,H,N,S,MS);
|
||||
FV(Y,AYear);
|
||||
FV(M,AMonth);
|
||||
FV(D,ADay);
|
||||
@ -2050,7 +2074,7 @@ end;
|
||||
|
||||
Function DateTimeToUnix(const AValue: TDateTime): Int64;
|
||||
begin
|
||||
Result:=SecondsBetween(UnixEpoch, AValue);
|
||||
Result:=Round(DateTimeDiff(AValue,UnixEpoch)*SecsPerDay);
|
||||
end;
|
||||
|
||||
|
||||
|
88
tests/webtbs/tw12894.pp
Normal file
88
tests/webtbs/tw12894.pp
Normal file
@ -0,0 +1,88 @@
|
||||
program Project1;
|
||||
|
||||
uses
|
||||
Classes, SysUtils, DateUtils;
|
||||
|
||||
var
|
||||
utime : longword;
|
||||
sec : word;
|
||||
currentDt, convertedDt : TDateTime;
|
||||
times: longint;
|
||||
s1, s2: ansistring;
|
||||
|
||||
begin
|
||||
for sec := 0 to 59 do
|
||||
begin
|
||||
currentDt := EncodeDateTime(1989, 9, 16, 12, 0, sec, 0);
|
||||
utime := DateTimeToUnix(currentDt);
|
||||
convertedDt := UnixToDateTime(utime);
|
||||
s1:=FormatDateTime('mm/dd/yyyy HH:nn:ss', currentDt);
|
||||
s2:=FormatDateTime('mm/dd/yyyy HH:nn:ss', convertedDt);
|
||||
writeln(s1 + ' = ' + IntToStr(utime) + ' = ' + s2);
|
||||
if (s1<>s2) then
|
||||
halt(1);
|
||||
end;
|
||||
for times:=-10000 to 10000 do
|
||||
if times<>datetimetounix(unixtodatetime(times)) then
|
||||
begin
|
||||
writeln('error for ',times,', becomes ',datetimetounix(unixtodatetime(times)));
|
||||
halt(2);
|
||||
end;
|
||||
|
||||
// check some borderline cases
|
||||
currentDt := EncodeDateTime(1899, 12, 29, 6, 0, 0, 0);
|
||||
convertedDt := EncodeDateTime(1899, 12, 30, 6, 0, 0, 0);
|
||||
writeln(currentDt:0:4,' - ',convertedDt:0:4);
|
||||
s1:=FormatDateTime('mm/dd/yyyy HH:nn:ss', currentDt);
|
||||
s2:=FormatDateTime('mm/dd/yyyy HH:nn:ss', convertedDt);
|
||||
writeln(s1);
|
||||
writeln(s2);
|
||||
if (currentDt<>-1.25) or
|
||||
(convertedDt<>0.25) or
|
||||
(s1<>'12-29-1899 06:00:00') or
|
||||
(s2<>'12-30-1899 06:00:00') or
|
||||
(DaysBetween(currentDt,convertedDt)<>1) or
|
||||
(HoursBetween(currentDt,convertedDt)<>24) or
|
||||
(MinutesBetween(currentDt,convertedDt)<>24*60) or
|
||||
(SecondsBetween(currentDt,convertedDt)<>24*60*60) or
|
||||
(MilliSecondsBetween(currentDt,convertedDt)<>24*60*60*1000) then
|
||||
begin
|
||||
writeln('between ',s1,' and ',s2);
|
||||
writeln(DaysBetween(currentDt,convertedDt));
|
||||
writeln(HoursBetween(currentDt,convertedDt));
|
||||
writeln(MinutesBetween(currentDt,convertedDt));
|
||||
writeln(SecondsBetween(currentDt,convertedDt));
|
||||
writeln(MilliSecondsBetween(currentDt,convertedDt));
|
||||
halt(3);
|
||||
end;
|
||||
currentDt := EncodeDateTime(1899, 12, 30, 6, 0, 0, 0);
|
||||
convertedDt := EncodeDateTime(1899, 12, 29, 6, 0, 0, 0);
|
||||
if (DaysBetween(currentDt,convertedDt)<>1) or
|
||||
(HoursBetween(currentDt,convertedDt)<>24) or
|
||||
(MinutesBetween(currentDt,convertedDt)<>24*60) or
|
||||
(SecondsBetween(currentDt,convertedDt)<>24*60*60) or
|
||||
(MilliSecondsBetween(currentDt,convertedDt)<>24*60*60*1000) then
|
||||
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
|
||||
(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);
|
||||
currentDt := EncodeDateTime(1898, 12, 29, 6, 0, 0, 0);
|
||||
convertedDt := EncodeDateTime(1899, 12, 30, 6, 0, 0, 0);
|
||||
if (YearsBetween(currentDt,convertedDt)<>1) or
|
||||
(MonthsBetween(currentDt,convertedDt)<>12) or
|
||||
(DaysBetween(currentDt,convertedDt)<>366) or
|
||||
(HoursBetween(currentDt,convertedDt)<>366*24) or
|
||||
(MinutesBetween(currentDt,convertedDt)<>366*24*60) or
|
||||
(SecondsBetween(currentDt,convertedDt)<>366*24*60*60) or
|
||||
(MilliSecondsBetween(currentDt,convertedDt)<>366*24*60*60*1000) then
|
||||
halt(6);
|
||||
// convertedDt:=incseconds(currentDt,
|
||||
|
||||
end.
|
Loading…
Reference in New Issue
Block a user