Dato
a := StrToTime('7:00');
b := StrToTime('17:30');
ShowMessage(FloatToStr(a));
ShowMessage(FloatToStr(b));
il codice, utilizzando MinutesBetween
, lo fa in modo efficace questo:
ShowMessage(IntToStr(trunc(MinuteSpan(a, b)))); // Gives 629
Tuttavia, potrebbe essere meglio turno:
ShowMessage(IntToStr(round(MinuteSpan(a, b)))); // Gives 630
Qual è in realtà il galleggiante -punto di valore?
ShowMessage(FloatToStr(MinuteSpan(a, b))); // Gives 630
quindi si sta chiaramente soffrendo di problemi a virgola mobile tradizionali qui.
Aggiornamento:
Il vantaggio principale di Round
è che se lo span minuto è molto vicino a un numero intero, il valore arrotondato sarà garantito essere che intero, mentre il valore troncato potrebbe benissimo essere precedente numero intero.
Il principale vantaggio di Trunc
è che si potrebbe effettivamente desiderare questo tipo di logica: infatti, se si compie 18 anni in cinque giorni, legalmente non è ancora consentito richiedere una patente di guida svedese.
Quindi, se si desidera utilizzare Round
invece di Trunc
, si può semplicemente aggiungere
function MinutesBetween(const ANow, AThen: TDateTime): Int64;
begin
Result := Round(MinuteSpan(ANow, AThen));
end;
alla vostra unità. Quindi l'identificatore MinutesBetween
farà riferimento a questo, nella stessa unità, anziché a quello in DateUtils
. La regola generale è che il compilatore utilizzerà la funzione trovata più tardi. Così, per esempio, se si desidera mettere questa funzione in precedenza nella propria unità DateUtilsFix
, quindi
implementation
uses DateUtils, DateUtilsFix
utilizzerà il nuovo MinutesBetween
, dal momento che DateUtilsFix
occurss alla destra di DateUtils
.
Aggiornamento 2:
altro approccio potrebbe essere plausibile
function MinutesBetween(const ANow, AThen: TDateTime): Int64;
var
spn: double;
begin
spn := MinuteSpan(ANow, AThen);
if SameValue(spn, round(spn)) then
result := round(spn)
else
result := trunc(spn);
end;
Ciò restituirà round(spn)
rappresenta l'intervallo è compreso nell'intervallo lanugine di un numero intero, e trunc(spn)
altrimenti.
Ad esempio, utilizzando questo approccio
07:00:00 and 07:00:58
produrrà 0 minuti, proprio come la versione basata su trunc
originale, e proprio come il Trafikverket svedese vorrebbe. Ma non soffrirà il problema che ha innescato la domanda dell'OP.
Il grosso problema con 'TDateTime' di delphi è che sono doppi che rappresentano giorni, invece di punti fissi. Ciò significa che non possono rappresentare esattamente i minuti. (Non sono sicuro se questo è ciò che causa il problema, ma non sarei sorpreso) – CodesInChaos
@CodesInChaos: Mi è stato detto. Non è una scusa adeguata per me. Potrebbero semplicemente farlo funzionare nel modo giusto invece di avere una [leaky astrazione] (http://www.joelonsoftware.com/articles/LeakyAbstractions.html). –
Nelle versioni più recenti di delphi (2006 o giù di lì) è possibile creare i propri record che rappresentano date/ora e sovraccaricare gli operatori. Quindi è possibile eliminare i doppi dateti intrinsecamente difettosi. – CodesInChaos