3

我有这个代码只运行两次,变量 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;
4

2 回答 2

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.

我将其作为练习使用文档来找出它为什么有效并且是强大的。

于 2013-01-27T20:10:41.103 回答
2

原因是EndOfTheMonth给你一个月的最后一天,也是对应于一天结束的时间。但你DateStop可能是一天的开始。

如果您在循环中打印出DateStartand的原始值,DateStop您会看到:

41333.9999999884 41364
41364.9999999884 41364

因此,查看最后一行,您可以看到我们在第 41364 天的时间是 23:59。

我会通过使用纯日期而不是让时间妨碍事情来解决这个问题。更改递增代码以删除日期的时间部分。而且我也会明确地在循环测试中做同样的事情。

while DateOf(DateStart) <= DateOf(DateStop) do
begin
  ....
  DateStart := DateOf(EndOfTheMonth(IncMonth(DateStart)));
end;
于 2013-01-27T20:10:51.053 回答