如何避免TDateTime数据舍入

asd*_*-tm 2 delphi datetime firemonkey

我写FMX柱和小区类别TGrid将包含TCalendarEditTTimeEdit在每个细胞中的情况.一切正常,除了正确处理这些子控件中所做的更改.

type
  TFMTValue<T> = record
    FieldValue: T;
    Modified: boolean;
    Appended: boolean;
    Deleted: boolean;
  end;

  TDateTimeCell = class(TStyledControl)
    private
      FDate_Time: TFMTValue<TDateTime>;
      procedure SetDateTime(const Value: TFMTValue<TDateTime>);
      function GetDateTime: TFMTValue<TDateTime>;
    protected
      procedure SetData(const Value: TValue); override;
    public
      property Date_Time: TFMTValue<TDateTime> read GetDateTime write SetDateTime;
    ...   
   end;
...     
  function TDateTimeCell.GetDateTime: TFMTValue<TDateTime>;
    begin
      FDate_Time.Modified := (FDate_Time.Modified) or
        (FDate_Time.FieldValue <> FCalendarEdit.Date +
         + FTimeEdit.Time);
      FDate_Time.FieldValue := FCalendarEdit.Date + FTimeEdit.Time;
      Result := FDate_Time;
    end;

    procedure TDateTimeCell.SetData(const Value: TValue);
    begin
      Date_Time := Value.AsType<TFMTValue<TDateTime>>;
      inherited SetData(TValue.From<TDateTime>(FDate_Time.FieldValue));
      ApplyStyling;
    end;

    procedure TDateTimeCell.SetDateTime(const Value: TFMTValue<TDateTime>);
    begin
      FDate_Time := Value;
      FCalendarEdit.Date := DateOf(FDate_Time.FieldValue);
      FTimeEdit.Time := TimeOF(FDate_Time.FieldValue);
      FDate_Time.FieldValue:=FCalendarEdit.Date + FTimeEdit.Time; //this line helps but not in all cases
    end;
Run Code Online (Sandbox Code Playgroud)

想法是通过TGrid OnGetValue事件处理程序分配数据.显示日期和时间.捕获用户活动并Modified设置标志.问题是即使没有任何用户活动,有时也会将此标志设置为true.我怀疑这是由于TDateTime的时间部分的四舍五入.代码没有其他方式为FCalendarEdit.Date和分配值FTimeEdit.Time.

我怎样才能正确地比较存储在数据FCalendarEdit.DateFTimeEdit.Time与存储在FDate_Time.FieldValue

附加

以这种方式设置标志不能解决问题.

  FDate_Time.Modified := (FDate_Time.Modified) or
    (DateOf(FDate_Time.FieldValue) <> FCalendarEdit.Date) or
    (TimeOf(FDate_Time.FieldValue)<> FTimeEdit.Time);
Run Code Online (Sandbox Code Playgroud)

附加2.关于@Ken-White的重要建议.如果我们替换比较线

FDate_Time.Modified := (FDate_Time.Modified) or
(not SameDateTime(FDate_Time.FieldValue,
 FCalendarEdit.Date + FTimeEdit.Time));
Run Code Online (Sandbox Code Playgroud)

它工作正常.因此,TDataTime比较必须仅由此函数完成.

Ken*_*ite 5

TDateTime是的type Double,这意味着它是一个浮点值,因此这样做的相等比较时没有指定的可接受的增量(差)是受二进制表示的通常问题..

特别是对于TDateTime值,您可以使用DateUtils.SameDateTime将等式比较到小于1毫秒:

FDate_Time.Modified := (FDate_Time.Modified) or
           (not SameDateTime(FDate_Time.FieldValue, 
            FCalendarEdit.Date + FTimeEdit.Time));
Run Code Online (Sandbox Code Playgroud)