これは、Delphi/C++ Builder 6で初めて導入されたDateUtils
ユニットの旧バージョンでの既知の問題です。この問題は、Delphi/C++ Builder XEで最終的に修正されるまで数年間続きました。
TDateTime
は本質的にはdouble
であり、日付は整数部分に格納され、時間は小数部分に格納されます。したがって、それはおおよその表現と丸めの対象となります。
この例では、dtEnter
は42703.0340277778
であり、dtExit
は42703.0347222222
です。 SpanOfNowAndThen(dtEnter, dtExit)
が0.000694444439432118
である、あなたの例で
function SpanOfNowAndThen(const ANow, AThen: TDateTime): TDateTime;
begin
if ANow < AThen then
Result := AThen - ANow
else
Result := ANow - AThen;
end;
:
2つのTDateTime
値の間のスパンは、単純な浮動小数点演算を用いて計算されます。 MinsPerDay
定数を乗じSpanOfNowAndThen()
の結果であるDouble
を返すことがMinuteSpan()
を呼び出すことになるXE前MinutesBetween()
関数の場合
、そしてそれは、最終的な整数を生成するように小数部分を切り捨てオフになります:あなたの例で
function MinuteSpan(const ANow, AThen: TDateTime): Double;
begin
Result := MinsPerDay * SpanOfNowAndThen(ANow, AThen);
end;
function MinutesBetween(const ANow, AThen: TDateTime): Int64;
begin
Result := Trunc(MinuteSpan(ANow, AThen));
end;
、MinuteSpan()
は小数がオフに切り捨てられ0となる(正確には、0.99999999278225
)1.0
よりもわずかに小さい小数値を生成します。
XEでは、浮動小数点数学に基づいていないより信頼性の高い計算を使用するために、多くの関数DateUtils
が書き直されました。 MinuteSpan()
はまだ同じですが、MinutesBetween()
はもうMinuteSpan()
を使用しません。その代わりに、それは今、(TDateTime
は、ミリ秒の精度を有するため、可逆である)ミリ秒に2つのTDateTime
値を変換した値を減算し、次いで毎分ミリ秒の一定の数で差の絶対値を除算:
function DateTimeToMilliseconds(const ADateTime: TDateTime): Int64;
var
LTimeStamp: TTimeStamp;
begin
LTimeStamp := DateTimeToTimeStamp(ADateTime);
Result := LTimeStamp.Date;
Result := (Result * MSecsPerDay) + LTimeStamp.Time;
end;
function MinutesBetween(const ANow, AThen: TDateTime): Int64;
begin
Result := Abs(DateTimeToMilliseconds(ANow) - DateTimeToMilliseconds(AThen))
div (MSecsPerSec * SecsPerMin);
end;
あなたの例では、DateTimeToMilliseconds(dtEnter)
は63616063740000
であり、DateTimeToMilliseconds(dtExit)
は63616063800000
であるため、差は60000
ミリ秒であり、正確には1
分です。
XEより前のバージョンでは、独自のコードで手動で同様の修正プログラムを実装する必要があります。私はC++ Builderの10.1ベルリンでこれを再現することはできません
How do I work around Delphi's inability to accurately handle datetime manipulations?
Accurate Difference Between Two TDateTime Values
:これは、次のような様々なオンラインのブログで議論されています。 C++ Builder 6はかなり古くなっています。バグかもしれませんが、そのような古いバグが修正される可能性はゼロです。 –