给定
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
是你可能真的想要这种逻辑:事实上,如果你在五天内就满 18 岁,在法律上你仍然不能申请瑞典驾照。
所以你如果你想使用Round
而不是Trunc
,你可以添加
function MinutesBetween(const ANow, AThen: TDateTime): Int64;
begin
Result := Round(MinuteSpan(ANow, AThen));
end;
到你的单位。然后标识符MinutesBetween
将引用同一单元中的这个,而不是DateUtils
. 一般规则是编译器将使用它最近找到的函数。所以,例如,如果你把这个函数放在你自己的 unitDateUtilsFix
中,那么
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
将产生 0 分钟,就像trunc
基于原始的版本一样,就像瑞典的 Trafikverket 一样。但它不会受到引发 OP 问题的问题的影响。