简体   繁体   中英

How to compare Firebird TimeStamp and Delphi DateTime?

I have the following script that never retrieve any data since TimeStamp data type in Firebird/Interbase is not DateTime (*)

How should i fix it ?? TX.

 with DMApp.qryValidPeriod_ do
  begin
    Close;
    SQL.Clear;
    SQL.Add('select P.* from PERIOD P, FISCAL_YR F');    
    SQL.Add('where');
    SQL.Add('P.FISCAL_YR_ID = F.FISCAL_YR_ID and');     
    SQL.Add('F.ENTITY_DB_ID = :PRIMARY_DB_ID and');     
    SQL.Add('F.FISCAL_YR_ID = :CURR_FY_ID and');        
    SQL.Add(':pTranDate BETWEEN P.BEG_PERIOD and P.END_PERIOD');

    ParamByName('pTranDate').AsDateTime :=  sBATCH_DATE; 

// BEG_PERIOD and END_PERIOD are TimeStamp data type such as '2010-11-09 12:00' // parameter return data type such as '2010-11-09'


(*) A timestamp is a column datatype available in Firebird/Interbase/SQL Server... that helps to ensure data integrity. Timestamps are automatically updated every time a row containing a timestamp column is inserted or updated. Values in timestamp columns are not datetime data, but binary(8) varbinary(8) data. The timestamp datatype has no relation to the system time, it is simply a monotonically increasing counter whose values will always be unique within a database (making it basically a unique random number.)

Isn't that you misunderstood TIMESTAMP datatypes in Firebird? In SQL92 TIMESTAMP is a standard data type to hold both date and time values. It's not automatically updated and the functions returning TIMESTAMP values are related to the database time.

AFAIK, the Firebird TIMESTAMP implementation follows the SQL 92 rules ( http://www.firebirdsql.org/index.php?op=guide&id=ib6_newfeatures#datetime ), and it should work perfectly with a Delphi .AsDateTime parameter.

It's SQL Server TIMESTAMPs that are as you described - and should never be used in comparison with date and times, "The SQL Server timestamp data type has nothing to do with times or dates" http://msdn.microsoft.com/en-us/library/ms191240(SQL.90).aspx

Usually, I use it as string parameter, because of the time part. Idea is to have settings independent format that is for example '11-NOV-2010 12:32:25'

For example, you might try

ParamByName('pTranDate').AsString :=  FormatSQLDateTime(sBATCH_DATE);

Where as you should have functions similar to these

function FormatSQLDate(date: TDate) : string;
const months : array[1..12] of string[3] =
('JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC');
 var d, y : integer;
     m : string[3];
begin
   d := DayOf(date);
   y := YearOf(date);
   m := months[MonthOf(date)];
   Result := Format('%d-%s-%d', [d, m, y]);
end;


function FormatSQLDateTime(date : TDateTime) : String;
var
  d : String;
  h, m, s : Integer;
begin
  d := SQLDate(date);
  h := HourOf(date);
  m := MinuteOf(date);
  s := SecondOf(date);
  Result := d + Format(' %d:%d:%d', [h, m, s]);
end;

Notice that you can also work something out on the server side with use of sql extract

extract(day from timestamp_field)

http://www.firebirdsql.org/refdocs/langrefupd20-extract.html

An UDF below written in Delphi. It gets three parts of a date and returns date value in Firebird format. Maybe this will help you to understand how to convert dates between Delphi and FB.

type
  PIBDateTime = ^TIBDateTime;
  TIBDateTime = record
    Days,                           // Date: Days since 17 November 1858
    MSec10 : Integer;               // Time: Millisecond * 10 since midnigth
  end;

const                               // Date translation constants
  MSecsPerDay10 = MSecsPerDay * 10; // Milliseconds per day * 10
  IBDateDelta = 15018;              // Days between Delphi and InterBase dates

// ==============================================
//  declare external function ...
//    smallint, smallint, smallint, date
//  returns
//    date
//  ...
// ==============================================

function g_d_encodedate(var Year, Month, Day: SmallInt;
  var IBDateTime: TIBDateTime): PIBDateTime; cdecl; export;
var
  DateTime: TDateTime;
  DelphiDays : Integer;
begin
  DateTime := EncodeDate(Year, Month, Day);
  DelphiDays := Trunc(DateTime);
  with IBDateTime do begin
    Days := DelphiDays + IBDateDelta;
    MSec10 := Trunc((DateTime - DelphiDays) * MSecsPerDay10);
  end;
  Result := @IBDateTime;
end;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM