Aqui está um exemplo que demonstra o problema:
var
fdt, fndt : Double;
dt, dt2 : TDateTime;
begin
dt := EncodeDateTime(2023, 12, 31, //
20, 10, 5, 100);
dt2 := EncodeTime(20, 10, 5, 100);
fdt := Frac(dt);
fndt := Frac(dt2);
Memo1.Lines.Add('Equal: ' + BoolToStr(fdt = fndt, True) + CRLF + //
FloatToStr(fdt) + CRLF + //
FloatToStr(fndt) + CRLF + //
FormatDateTime('HH:NN:SS ZZZ', fdt) + CRLF + //
FormatDateTime('HH:NN:SS ZZZ', fndt) + CRLF + //
''
);
Exit;
O resultado é:
Equal: False
0,840336805558763
0,840336805555556
20:10:05 100
20:10:05 100
Então, como você pode ver, a parte do tempo não é igual a Double, mas sim a String formatada.
Por que eles são diferentes?
Como eu sei que EncodeDateTime faz EncodeDate + EncodeTime. E a Data = Trunc(Data). Então a parte fracionária tem que ser igual! Mas não é. Por que? Talvez algumas informações de fuso horário?
Obrigado por qualquer informação sobre isso.
Ambiente: Win 11, Delphi S10, Exe de 32 bits. Fuso horário: Europa/Budapeste (+2/+1).
Comparar valores de ponto flutuante para igualdade usando o
=
operador geralmente não é preciso devido à natureza imprecisa dos tipos de ponto flutuante. Só porque as entradas são idênticas não garante que os flutuadores sejam idênticos.Você deve levar em consideração um épsilon para ver se os valores de ponto flutuante são "próximos o suficiente" para serem considerados iguais. Você pode usar
Math.SameValue()
para esse fim.No entanto, neste caso, você pode usar
DateUtils.SameTime()
ouDateUtils.CompareTime()
em vez disso. ASameTime()
documentação ainda afirma o seguinte: