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?

Kromster
  • 7,181
  • 7
  • 63
  • 111
JustMe
  • 2,329
  • 3
  • 23
  • 43

1 Answers1

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.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • 2
    `DateTimeToStr(V)` shows the correct result too. Apparently, the issue is with the `VarToStr()` function. – Andriy M Apr 05 '12 at 11:43
  • 2
    @AndriyM: True, but it is never (?) wrong to be too explicit! :) – Andreas Rejbrand Apr 05 '12 at 11:48
  • 1
    @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). – Andreas Rejbrand Apr 05 '12 at 11:51
  • @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? – JustMe Apr 05 '12 at 11:55
  • 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.) – Andriy M Apr 05 '12 at 12:05
  • @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`. – Andreas Rejbrand Apr 05 '12 at 12:08
  • 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. – Andriy M Apr 05 '12 at 12:12