Declare a TDateTime as a Const in Delphi

11,260

Solution 1

Ok, my reaction is a bit late, but here's a solution for the newer Delphi's.

It uses implicit class overloaders so that records of this type can be used as if they are TDateTime variables.

  TDateRec = record
    year,month,day,hour,minute,second,millisecond:word;
    class operator implicit(aDateRec:TDateRec):TDateTime;
    class operator implicit(aDateTime:TDateTime):TDateRec; // not needed
    class operator implicit(aDateRec:TDateRec):String; // not needed
    class operator implicit(aDateRec:String):TDateRec; // not needed
  end;

Implementation:

uses DateUtils;

class operator TDateRec.Implicit(aDateRec:TDateRec):TDateTime;
begin
  with aDateRec do // Yeah that's right you wankers. I like "with" :)
    Result := encodeDateTime(Year,Month,Day,Hour,Minute,Second,Millisecond);
end;

class operator TDateRec.Implicit(aDateTime:TDateTime):TDateRec;
begin
  with Result do
    DecodeDateTime(aDateTime,Year,Month,Day,Hour,Minute,Second,Millisecond);
end;

class operator TDateRec.Implicit(aDateRec:TDateRec):String;
begin
  Result := DateTimeToStr(aDateRec)
end;

class operator TDateRec.Implicit(aDateRec:String):TDateRec;
begin
  Result := StrToDateTime(aDateRec)
end;

Now you can declare your dates like this:

const
  Date1:TDateRec=(Year:2009;month:05;day:11);
  Date2:TDateRec=(Year:2009;month:05;day:11;hour:05);
  Date3:TDateRec=(Year:2009;month:05;day:11;hour:05;minute:00);

To see if it works, execute the following:

ShowMessage(Date1); // it can act like a string
ShowMessage(DateToStr(Date1)); // it can act like a date

If you really want to replace all your TdateTime variables with this, you probably need to overload some other operators too (Add, subtract, explicit, ...).

Solution 2

The only? possible way, but probably not what you are looking for:

const
{$J+}
  Expire: TDateTime = 0;
{$J-}

initialization
  Expire := EncodeDate(2009, 3, 23);

Solution 3

I tend to simulate const dates with a function. Technically they're a little more constant than the "pseudo-constant" assignable typed const's.

function Expire: TDateTime;
begin
  Result := EncodeDate(2009, 3, 23);
end;

NOTE the use of EncodeDate rather than StrToDate. StrToDate is affected by regional settings meaning there's no guarantee a string will be interpreted as would be expected.

For example, did you know that there's a strange a group of people who think it makes sense to "shuffle" date parts into an inconsistent order of significance? They use middle, then least, then most significant part (e.g. '3/23/2009') <cheeky grin>. The only time that logic makes sense is when you turn 102 years old - then you can claim your age is 021.

For the premature optimisers out there, if the function is called so frequently that the nano seconds required to encode a date becomes an issue - you have a far bigger problem than this minor inefficiency in the name of readable, maintainable code.

Solution 4

There is no way to do this because interpreting a date litteral in itself is not deterministic, it depends on the convention/locale you follow.
'1/4/2009' is not in January for any French person for instance, and having the compiler translating as January 4th would make it a fool's compiler ;-)
Unless the compiler implements some (well documented) "magic" bijective function for pairing a date value and a display representation... And anyway, half of the planet would not like it.
The only non ambiguous way I see now is to provide the value even if it looks like a pain... ... my $0.02

Solution 5

No, Delphi doesn't support that.

Your first idea would be a request for date-time literals distinct from ordinary floating-point literals. I found QC 72000, which is about displayingTDateTime values as dates in the debugger, but nothing about your particular request. It's not like nobody's ever mentioned it before, though. It's a perennial topic on the newsgroups; I just can't find anything in QC about it.

Your second idea would require StrToDate to be evaluable at compile time. I don't see any entries in QC about it either, but for what it's worth, C++ is getting such a feature for functions that are shown to have the necessary qualities. StrToDate wouldn't meet those requirements, though, because it's sensitive to the current locale's date settings.

Share:
11,260
Joel
Author by

Joel

Developer Advocate for Embarcadero Technologies Invented and patented swipe to unlock in 2000. See US Patent # 8352745 &amp; 6766456, and others. Host of the Podcast at Delphi.org. (mostly a blog with occasional episodes). Preferred Languages: Delphi / Object Pascal C++ JavaScript C# / .NET Java

Updated on June 16, 2022

Comments

  • Joel
    Joel almost 2 years

    As far as I know there is no way to do this, but I am going to ask just in case someone else knows how to do this. How can I declare a date as a const in Delphi?

    The only solution I have found is to use the numeric equivalent, which is kind of a pain to maintain because it is not human readable.

    const
      Expire : TDateTime = 39895; // Is actually 3/23/2009
    

    What I would like to be able to do is something like this:

    const
      Expire : TDateTime = TDateTime ('3/23/2009');
    

    or

    const
      Expire : TDateTime = StrToDate('3/23/2009');
    

    So let me know if this is a feature request or if I just missed how to do this (yeah, I know it seems like an odd thing to want . . . .)