2

Is there a way to check whether a Delphi TDateTime variable has valid contents without trapping exceptions on conversions?

I have written an application that has to parse through hundreds of huge files written as raw Delphi records that contain a TDateTime field. Occasionally I get a record where the contents has a TDateTime value like 2.0927117954e+262 which gives a Floating point invalid Operation exception when passed to conversion routines. I know I can simply trap the exception but this is such a nuisance when debugging as the debugger keeps stopping and I want to keep it enabled in case of other errors.

Wolf
  • 9,679
  • 7
  • 62
  • 108
Stargate
  • 21
  • 1
  • 2
  • 3
    Define "valid contents". `TDateTime` is basically just a `Double` with special semantics. Every value is techncally valid. If your conversion routines are raising errors, then please show the actual conversion routines, the input values, and the errors. – Remy Lebeau Jul 31 '12 at 19:58

3 Answers3

11

Your example value is obviously out of valid DateTime range. You can test if it is in range before performing any conversion.

var
  d: TDateTime;
..

d := 2.0927117954e+262;
if (d <= MaxDateTime) and (d >= MinDateTime) then
  s := DateTimeToStr(d)
else
  ..
Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
5

If your issue is the debugger stopping, you can fix that in the IDE of later Delphi versions. Set two breakpoints before and after the line where the exception will occur. E.g. in Delphi 2007, right-click on the margin red dot for the first BP, choose BreakPoint properties/Advanced/Ignore subsequent exceptions. On the second BP, 'Handle subsequent exceptions'

Jan Doggen
  • 8,799
  • 13
  • 70
  • 144
4

Reading your problem description, I conclude that it's absolutely valid for your application to go on reading the file if some record has a corrupt/invalid time value and so you want so skip it (maybe mark or collect the problem otherwise).

The VCL function System.SysUtils.TryFloatToDateTime is made exactly for this purpose, and using it seems by far the best option to me.

Delphi example:

uses SysUtils;

function IsValidDateTime(dt: Double): Boolean;
var
  dummy: TDateTime;
begin
  Result := TryFloatToDateTime(dt, dummy);
end;

C++ Builder example:

#include <SysUtils.hpp>

bool isValidDateTime(const double dt) 
{
    TDateTime dummy;
    return TryFloatToDateTime(dt, dummy);
}

This function is not only handy (because exception-free and already there) but also very readable, it also follows a nice convention that runs through the entire framework:

  • name begins with Try saying that it can fail
  • Boolean direct results to indicate a valid operation
  • indirect result gets the actual value (if operation succeeded)
Wolf
  • 9,679
  • 7
  • 62
  • 108
  • Didn't know it, I don't think it's *by far* the best option but + 1. Ctrl+click on it, and you'll see it does the same thing as in my answer, compares the value against MinDateTime and MaxDateTime. However my answer may be off by 1 on MaxDateTime according to that. – Sertac Akyuz Sep 05 '14 at 11:00
  • @SertacAkyuz Your answer is my favourite so far, but the function (I already checked that it does basically the same) is more compact and has also an expressive name. I found it by accident, when exploring in which namespace `MinTimeValue` and `MaxTimeValue` live... – Wolf Sep 05 '14 at 12:03