How know type variable is TDateTime, TDate and TTime in Delphi
Asked Answered
F

3

5

I need know type variable TDateTime, TDate and TTime.

Anyone have any idea how to do this?

I used the code below, the result is "Is NOT TDateTime", "Is NOT TDate", "Is NOT Ttime"


program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.Rtti,
  System.SysUtils;

var
  DateTime, Date,Time: TValue;

begin

  DateTime:= StrToDateTime( '01/01/2013 01:05:09' );
  if ( DateTime.TypeInfo = System.TypeInfo(TDateTime) ) then
    Writeln( 'Is TDateTime' )
  else
    Writeln( 'Is NOT TDateTime' );

  Date:=  StrToDate( '01/01/2015' );
  if ( Date.TypeInfo = System.TypeInfo(TDate) ) then
    Writeln( 'Is TDate' )
  else
    Writeln( 'Is NOT TDate' );

 Time:=  StrToTime( '01:01:02' );
  if ( Date.TypeInfo = System.TypeInfo(TTime) ) then
    Writeln( 'Is TTime' )
  else
    Writeln( 'Is NOT TTime' );

 Readln;

end.

Thanks

Farwell answered 3/10, 2013 at 17:2 Comment(4)
Maybe you can try to follow the answer from here.Nitpicking
Welcome to Stack Overflow. It's very good that you included what results you expected to get, but it's also helpful to report what results you got instead. You know you didn't get a TDateTime, so investigate a little further and find out what type you got instead. Also note that StrToDateTime, StrToDate, and StrToTime all return TDateTime, so don't get your hopes up about distinguishing them.Chura
Type is TDateTime, always.Devoir
No, the type is Extended always - see my answer below.Edington
E
5

The Implicit operator overloads of TValue got you.

When you assign the result of StrToDateTime, StrToDate and StrToTime to a TValue it uses the most matching Implicit operator overload from TValue which is Extended.

Also keep in mind that all three functions return TDateTime so even if there were operator overloads for TDateTime, TDate and TTime it would not work as expected.

To get the correct results you would have to explicitly specify the type when assigning your values to the TValue variables:

DateTime := TValue.From<TDateTime>(StrToDateTime( '01.01.2013 01:05:09' ));

Date:= TValue.From<TDate>(StrToDate( '01.01.2015' ));

Time:= TValue.From<TTime>(StrToTime( '01:01:02' ));
Edington answered 4/10, 2013 at 6:14 Comment(3)
Wow, Extended! I cannot get over the fact that new Emba RTL code still uses Extended. Putting a date time into an Extended is just bonkers. Bad enough storing them in binary floating point (!!). Pah!Miscreant
The "problem" is that the only matching Implicit operator overload of TValue for float numbers is Extended which breaks TDateTime/TTime/TDate/any other float type compatibility (i.e. being able to determine the type afterwards). While it manifests mostly with these types it is also the case for any other type that does not have a specific Implicit operator overload in TValue but is assignment compatible to any that has an overload.Edington
I just like any opportunity to whine about Extended which should never have existed, and TDateTime being floating point. An opportunity have both whines at the same time was too enticing to pass up! ;-)Miscreant
T
2

Just in case you were trying to determine the result type of StrToDateTime:

type
  TDateType = (dtDate, dtDateTime, dtTime);

function getDateType(date: TDateTime): TDateType;
begin
  if Trunc(date) = date then // Or DateOf(date), if available
  begin
    Result := dtDate;
  end
  else
  begin
    if Trunc(date) = 0 then // Or DateOf(date), if avaialble
    begin
      Result := dtTime
    end
    else
    begin
      Result := dtDateTime;
    end;
  end;
end;

// Sample
var
  result: TDateType;
begin
  result := getDateType(StrToDateTime('01/01/2013 01:05:09')); // dtDateTime
  result := getDateType(StrToDateTime('01/01/2015')); // dtDate
  result := getDateType(StrToDateTime('01:01:02')); // dtTime
  // One caveat
  result := getDateType(StrToDateTime('01/01/2013 00:00:00')); // dtDate
end;

Alternatively, you could use the TryStrToDate, TryStrToTime, and TryStrToDateTime functions.

Transaction answered 3/10, 2013 at 18:10 Comment(2)
It's more descriptive to use DateOfMiscreant
@DavidHeffernan, I agree, where available.Transaction
C
2

In case you're curious, the TDateTime is encoded as floating point Double internally.

TDateTime internals
The fractional part denotes the time, the integer part denotes the date.
Knowing this the following tests will evaluate to true.

dtTime: ABS(Double(DateTime1)) < 1.0 
dtDate: Trunc(Double(DateTime1)) = Double(DateTime1)
dtDateTime:  (     (ABS(Double(DateTime1)) > 1.0) 
         and (Trunc(Double(DateTime1)) <> Double(DateTime1)) )

Obviously that's a very roundabout way of testing, but sometimes it helps to know how a TDateTime is shaped internally.

DateUtils
The sane versions of these tests would be:

uses DateUtils;

dtDate: DateTime1 = DateOf(DateTime1)
dtTime: DateTime1 = TimeOf(DateTime1)
dtDateTime:(DateTime1 <> DateOf(DateTime1)) and (DateTime1 <> TimeOf(DateTime1))

TDateTime is compatible with Excel
The value 0 links to the epoch in Microsoft's Excel: 30 December 1899; 12:00 A.M.
(It should have been 1-1-1900, but they changed it to compensate for an error in Lotus' 123 date algorithm)
This is great, because Delphi's TDateTime is fully compatible with Excel's DateTime.

Here's the official doc: http://docwiki.embarcadero.com/Libraries/XE5//en/System.TDateTime

Champlain answered 4/10, 2013 at 1:28 Comment(7)
"There are no negative dates!" Obviously we don't have the same dating experience. ;-)Porkpie
You don't really get a choice of whether to use -ve dates or not - you either need to represent a pre-1900 date or you don't. I can see how the time segment could be confusing, though.Psephology
@MattAllwood Sure you can roll your own, but don't expect RTL support (DateToStr) etc. Oh and pre 1900 dates are complicated. See wikipedia.Champlain
-1 for stating there are no negative dates. There are and they function perfectly fine. The documentation you linked even explicitely states that -1.25 is December 29, 1899; 6:00 A.M. Now what should -1.25 + 0.25 add up to? ... Well, -1 of course. And yest that is exactly 6 hours ahead: December 30 1989 at midnight. Nothing complicated about it. Completely and utterly normal. Which is only to be expected as we would otherwise never be able to do anything with dates prior to December 30 1989 and genealogy programs would have no business being programmed in DelphiAalst
Correction. I'll admit to a bit of complication when doing calculations with time fractions. Time increases away from zero on both sides of zero and that seems "off" because you would expect time fractions to move from left to right just like dates do even below zero. That fact time fractions sort of increase "contrary" to the dates is actually to make calculations work correctly.Aalst
@MarjanVenema, Yes, you are correct, I misread. Corrected now.Champlain
Downvote converted to upvote. I already liked the rest of your post!Aalst

© 2022 - 2024 — McMap. All rights reserved.