我有这个代码只能用变量运行两次 DateStart:= 27-01-2013 DateStop:= 31-03-2013
我认为它应该与31-01-2013,28-02-2013和31-3-2013的结果一致 但我只得到2个结果
我很确定我一直在凝视着,看不出问题
begin
DateStart := EndOfTheMonth(DateStart);
while DateStart <= DateStop do
begin
FsFutureCreate(DateStart, cxDebit.Value, cxKredit.Value, aAccount, aType, aStore, aCity, txtText.Text, lRecord);
DateStart := EndOfTheMonth(IncMonth(DateStart));
end;
end;
答案 0 :(得分:3)
FsFutureCreate
(你从未告诉我们它是什么)有一些副作用,或你有一些浮点模糊问题。如您所知,日期和时间值是双倍的,因此像<=
这样的比较是危险的。 (特别是如果你忽视时间部分,我的分析如下所示。)
第二个更可能是一个。我刚试过
procedure TForm1.FormCreate(Sender: TObject);
var d: TDate; d2: TDate;
begin
d := EncodeDate(2013, 01, 31);
d := IncMonth(d); // 2013-02-28
d := EndOfTheMonth(d); // 2013-02-28
d := IncMonth(d); // 2013-03-28
d := EndOfTheMonth(d); // 2013-03-31
d2 := EncodeDate(2013, 03, 31);
// d is now 2013-03-31 23:59:59
// d2 is now 2013-03-31 00:00:00
ShowMessage(BoolToStr(d <= d2, true));
end;
并得到false
,正如人们所期望的那样。因此,在这种情况下,问题是EndOfTheMonth
函数还将时间设置为当天的最后一秒(或毫秒)。但即使不是这种情况,使用=进行比较对于浮点值也是危险的。
要修正比较,请执行
CompareDate(d, d2) <= 0
而不是
d <= d2.
我将其作为一项练习,以找出using the documentation,为什么这种方法有效且稳健。
答案 1 :(得分:2)
原因是EndOfTheMonth
为您提供了该月的最后一天,但也提供了与当天结束时间相对应的时间。但是你的DateStop
可能是一天的开始。
如果您在循环中打印出DateStart
和DateStop
的原始值,您会看到:
41333.9999999884 41364
41364.9999999884 41364
所以,看看最后一行你可以看到我们在第41364天的时间是23:59。
我通过使用纯粹的约会来解决这个问题,而不是让时间妨碍事情。更改递增代码以删除日期的时间部分。而且我也明确要在循环测试中做同样的事情。
while DateOf(DateStart) <= DateOf(DateStop) do
begin
....
DateStart := DateOf(EndOfTheMonth(IncMonth(DateStart)));
end;