Cómo evitar el redondeo de datos TDateTime
Estoy escribiendo clases de columnas y celdas para FMXTGrid
eso contendráTCalendarEdit
yTTimeEdit
instancias en cada celda. Todo funciona bien, excepto el procesamiento adecuado de los cambios realizados en estos controles secundarios.
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;
La idea es que los datos se asignen a través deTGrid
OnGetValue
controlador de eventos. Se muestran tanto la fecha como la hora. La actividad del usuario se captura yModified
Se establece la bandera. El problema es que este indicador se establece en verdadero a veces incluso sin ninguna actividad del usuario. Sospecho que se debe al redondeo del tiempo que forma parte de TDateTime. No hay otras formas en que el código asigna valores aFCalendarEdit.Date
yFTimeEdit.Time
.
¿Cómo puedo comparar adecuadamente los datos almacenados enFCalendarEdit.Date
yFTimeEdit.Time
con eso almacenado enFDate_Time.FieldValue
?
Adjunto
Establecer la bandera de esta manera no resuelve el problema.
FDate_Time.Modified := (FDate_Time.Modified) or
(DateOf(FDate_Time.FieldValue) <> FCalendarEdit.Date) or
(TimeOf(FDate_Time.FieldValue)<> FTimeEdit.Time);
Adjunto 2. Siguiendo un valioso consejo de @ Ken-White. Si reemplazamos la línea de comparación por
FDate_Time.Modified := (FDate_Time.Modified) or
(not SameDateTime(FDate_Time.FieldValue,
FCalendarEdit.Date + FTimeEdit.Time));
Funciona bien. Por lo tanto, la comparación TDataTime debe hacerse solo con esta función.