与えられた
a := StrToTime('7:00');
b := StrToTime('17:30');
ShowMessage(FloatToStr(a));
ShowMessage(FloatToStr(b));
を使用したコードはMinutesBetween
、効果的にこれを行います。
ShowMessage(IntToStr(trunc(MinuteSpan(a, b)))); // Gives 629
ただし、次のように丸める方がよい場合があります。
ShowMessage(IntToStr(round(MinuteSpan(a, b)))); // Gives 630
実際の浮動小数点値は何ですか?
ShowMessage(FloatToStr(MinuteSpan(a, b))); // Gives 630
したがって、ここでは明らかに従来の浮動小数点の問題に苦しんでいます。
アップデート:
の主な利点はRound
、分のスパンが整数に非常に近い場合、丸められた値がその整数であることが保証され、切り捨てられた値が前の整数である可能性が非常に高いことです。
の主な利点Trunc
は、実際にこの種のロジックが必要になる可能性があることです。実際、5 日以内に 18 歳になった場合、法的にはスウェーデンの運転免許証を申請することはまだ許可されていません。
Round
の代わりに使用したい場合はTrunc
、追加するだけです
function MinutesBetween(const ANow, AThen: TDateTime): Int64;
begin
Result := Round(MinuteSpan(ANow, AThen));
end;
あなたのユニットに。次に、識別子MinutesBetween
は、同じユニット内の の代わりに、この識別子を参照しDateUtils
ます。一般的なルールは、コンパイラが最後に見つけた関数を使用することです。したがって、たとえば、この関数を自分の unit の上に置くDateUtilsFix
と、
implementation
uses DateUtils, DateUtilsFix
はの右側にあるMinutesBetween
ため、新しい を使用します。DateUtilsFix
DateUtils
更新 2:
別のもっともらしいアプローチは
function MinutesBetween(const ANow, AThen: TDateTime): Int64;
var
spn: double;
begin
spn := MinuteSpan(ANow, AThen);
if SameValue(spn, round(spn)) then
result := round(spn)
else
result := trunc(spn);
end;
これround(spn)
は、スパンが整数のファズ範囲内にある場合に返され、trunc(spn)
そうでない場合に返されます。
たとえば、このアプローチを使用して
07:00:00 and 07:00:58
trunc
元のをベースにしたバージョンと同様に、スウェーデンの Trafikverket が望んでいるように、0 分になります。しかし、OPの質問を引き起こした問題に悩まされることはありません。