Is it possible to express an empty (zero) TDateTime value as a constant? I tried TDateTime(0)
, TDateTime(0.0)
and other things, but the compiler (Delphi 7) wasn't impressed.
At the moment I'm using an initialised global variable:
const
TDateTime_0: TDateTime = 0.0;
This sort of works. However, I just inherited a nice big pile of Delphi 7 code and I haven't used Turbo Pascal in ages... Which means I seriously need to brush up my Delphi fu, and this makes me want to know.
By contrast, the compiler is perfectly happy with something like Integer(0)
. Its assignment to a variant results in a value of 0 of type ftInteger
, whereas assigning a plain literal 0 would result in a variant of type ftSmallInt
.
Clarification: the objective is to pass an 'empty' value of a specific type to functions that take variants (which includes the compiler-managed variant arrays known as 'array of const' and also the setters for things like TParameter.Value).
Clarification for Ken White: the issue here is essentially type deduction and overload resolution; above-mentioned 'functions that take variants' are just a special case. The literals 0
and 0.0
are implicitly convertible to TDateTime
, which is why they can be assigned to receptacles of that type (variables, record fields) and they can be used to initialise such receptacles (i.e. function parameters) without further ado. However, things change when the compiler needs to do type deduction:
procedure foo (value: Double); overload;
procedure foo (value: TDateTime); overload;
The underlying type is Double in both cases, which means that the compiler requires arguments to be typed explicitly (i.e. calls with plain literals are rejected as ambiguous). With ordinal-based types the explicit typing is no problem but type Double is problematic and requires values to be stuffed into typed receptacles before they can be used. Compilable example (requires a Delphi that's a bit newer than Delphi 7):
type
TSomeId = type Integer;
procedure foo (value: Integer ); overload; begin WriteLn('Integer ', value); end;
procedure foo (value: TSomeId ); overload; begin WriteLn('TSomeId ', value); end;
procedure foo (value: Double ); overload; begin WriteLn('Double ', value); end;
procedure foo (value: TDateTime); overload; begin WriteLn('TDateTime ', value); end;
procedure test_TYPE_Double;
var
d: Double;
t: TDateTime;
begin
foo(Integer(0));
foo(TSomeId(0));
d := 0; foo(d);
t := 0; foo(t);
end;
My question is/was simply whether it is possible to form expressions of type TDateTime
(or other types based on Double
) in the same way as it is possible for Integer
and TSomeId
in the example above, without allocating and initialising a typed memory location for that purpose. However, Yuriy's answer indicates that this is only possible for ordinal types.
Compiler is OK with casting ordinal types to other ordinal types, but refuses to cast floating-point types to each other, even if they are exact the same:
TMyOwnDouble = type double;
...
var a,b: TMyOwnDouble;
...
a:=MyOwnDouble(0.0); //invalid typecast
b:=0.0; //no problem
What exactly do you want? If this TDateTime constant is needed just to pass it to some function requiring TDateTime, then you can just pass 0.0 and it will work:
caption:=DateTimeToStr(0.0); //it shows 30.12.1899
There are 2 functions which could be handy:
function FloatToDateTime(const Value: Extended): TDateTime; //sysUtils unit
It checks boundaries for Value and if it's all right, makes single assignment.
function VarFromDateTime(DateTime: TDateTime): Variant; //Variants unit
This one explicitly creates DateTime variant. I tried them both in code like this, they work the same:
var V: Variant;
...
V:=VarFromDateTime(0.0);
//V:=FloatToDateTime(0.0); //works as well
Caption:=V; //shows 0:00:00
Code like this may be a little more understandable than using TDateTime_0 constant, but it's a little more bulky.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With