UDF para calcular Idade não funciona

Firebird

02/12/2007

Bom dia a todos.

Estou usando o Firebird 2.0.3.12981.
Tenho o seguinte cenário:
Criei uma UDF (braUDF.dll) bem simples para calcular a idade dos meus clientes como segue abaixo:

unit UnitUDF;

interface

uses
  SysUtils, DateUtils;

function CalculaIdade(DATA: TDateTime): Integer; export;Stdcall;

implementation

{Função para calcular a idade atual a partir da data do nascimento}
function CalculaIdade(DATA: TDateTime): Integer;
VAR COMPLETO : Integer;
begin
  result := 0;
  COMPLETO := YearOf(Date) - YearOf(DATA);
  if MonthOf(DATE) > MonthOf(DATA) then
    result := COMPLETO;
  if MonthOf(DATE) < MonthOf(DATA) then
    result := COMPLETO - 1;
  if MonthOf(DATE) = MonthOf(DATA) then
    if DayOf(DATE) >= DayOf(DATA) then
      result := COMPLETO
    else
      result := COMPLETO - 1;
end;

end.


É importante informar que testei essa dll usando o um novo aplicativo Delphi e tudo funciona perfeitamente, ouseja, a função está escrita corretamente (o problema será quando executar usando o servidor do banco de dados).

Pois bem!
Copiei a DLL para o diretório UDF do Firebird e a registrei no meu banco de dados usando o IBExpert segundo o código abaixo:

DECLARE EXTERNAL FUNCTION CALCULAIDADE
    DATE
RETURNS INTEGER BY VALUE
ENTRY_POINT ´CalculaIdade´ MODULE_NAME ´braUDF´;


Até aí tudo ok.
Chegou a hora de testar a função. Então uso o próprio IBExpert para fazer a seguinte pesquisa na minha tabela de clientes:

select codigo,nome, nascimento, calculaidade(nascimento) from CLIENTES


E aí começa o meu tormento:
todos os meus clintes têm 107 anos. ou seja, o Firebird está passando como parâmetro para a função UDF CalculaIdade a data ´30/12/1899´ para TODOS os registros.
Alguém conseguiria detectar onde estou errando?

Agradeço qualquer dica.

Obrigado e bom trabalho a todos.


Brasidata

Brasidata

Curtidas 0

Respostas

Gandalf.nho

Gandalf.nho

02/12/2007

Para fazer UDFs para IB/FB envolvendo datas é necessário um certo tratamento dos parâmetros, devido ao formato usado. Dê uma olhada nesse link, que tem as explicações para isso: http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_howto2


GOSTEI 0
Brasidata

Brasidata

02/12/2007

Obrigado pela atenção gandalf.nho,

Li o material do link, mas achei a coisa realmente complexa para DATAS além de ser direcionado mais especificamente ao INTERBASE.
Tentei refazer minha UDF com as adaptações necessárias para o Firebird + BDS2006 (substituindo o tipo LONG por Int64 e as dlls do interbase, etc...) e mesmo assim, a ´coisa´ não funcionou tão bem quanto eu esperava.
Portanto, optei por abandonar temporariamente a idéia da UDF e parti para a solução através de uma Stored Procedure :

create procedure SP_AgeOf(NASCIMENTO Date) returns (IDADE integer)
as
declare variable MesNasc Integer;
declare variable DiaNasc Integer; 
declare variable MesAtual Integer;
declare variable DiaAtual Integer;
begin
MesNasc = extract(month from NASCIMENTO);
DiaNasc = extract(day from NASCIMENTO);
MesAtual = extract(month from current_date);
DiaAtual = extract(day from current_date);
IDADE = extract(year from current_date) - extract(year from NASCIMENTO);
if ((MesNasc > MesAtual) or ((MesNasc = MesAtual) and (DiaNasc > DiaAtual))) then
IDADE = IDADE - 1;
  suspend;
end;


Obrigado , mais uma vez, pela dica.


GOSTEI 0
POSTAR