Bad conversion from EndOfTheMonth(date) to Variant value
Asked Answered
E

1

6

I have a TDateTime value (that I get as result from EndOfTheMonth(date)) to a variant type. The result is wrongly rounded. Let's have a look at example:

  data := EndOfTheMonth(date);
  V := data;
  ShowMessage(DateTimeToStr(data) + ' vs ' + VarToStr(V));
 // output is
 // data = 2012-01-31 23:59:59
 // v    = 2012-02-01            // why next day?

Is it designed behaviour? How to work around this?

Efferent answered 5/4, 2012 at 11:32 Comment(0)
F
6
ShowMessage(DateTimeToStr(data) + ' vs ' + DateTimeToStr(VarToDateTime(V)));

Update: I would guess the problem is that the last millisecond of the month is very close to 0:00:00 the next day, that is, the TDateTime value (which is basically a double) is very close to an integer (e.g. 41029.9999999884 is very close to 41029) and so the VarToStr function assumes the decimals to be numerical fuzz.

Ferdie answered 5/4, 2012 at 11:39 Comment(7)
DateTimeToStr(V) shows the correct result too. Apparently, the issue is with the VarToStr() function.Proa
@AndriyM: True, but it is never (?) wrong to be too explicit! :)Ferdie
@JustMe: I haven't studied that page very carefully, but I am pretty sure that the best workaround for this particular problem is the one I gave above (or the slightly briefer version suggested by Andrily M).Ferdie
@AndreasRejbrand Thanks - they use vartostr() function to check if TDateTime values are converted correctly to Variants, and assumed that way that this is not a bug in their software?Efferent
I guess not. I was only adding more evidence to point out that the issue is not related to rounding (when assigning a TDateTime to a Variant). After digging a bit more, I found out that VarToStr() does nothing criminal: just calls VarToStrDef(), which in turn merely performs this assignment: Result := V (i.e. (string) := (Variant)). So, the conversion to string is done at a lower level, I guess. (Note: I used Delphi 6 in my research.)Proa
@AndriyM: I saw that too. But it still appears to be some kind of numerical inaccuracy here (call it 'rounding' or not). For instance, if you IncHour(EndOfTheMonth(date), -2) instead of EndOfTheMonth(date) then you get 2012-04-30 21:59:59 vs 2012-04-30 22:00:00 if you use VarToStr.Ferdie
Ah yes, of course it must have something to do with rounding, just not at the time of assignment, but rather at the time of string conversion.Proa

© 2022 - 2024 — McMap. All rights reserved.