Colegas, sorry mas em 99,99% das vezes, quando eu vejo funções tipo 'calcula 
bissexto', 'adiciona_dias', ou quetais são Puro desperdício, pois o bd Oracle 
já faz adição / subtração de dias E faz o cálculo de meses já levando em 
consideração anos bissextos e TUDO O MAIS - coincidentemente há algumas semas 
dei um Treinamento zás-trás de PL/SQL (assumi uma turma temporária,num cursinho 
de dias, na verdade) prum pessoal que não trabalhava com Oracle, foi uma 
novidade Total isso pra eles, pois é uma característica que não é comum em 
outros BDs...  E já que NECESSARIAMENTE SEMPRE temos 12 meses no ano, 
rigorosamente não há necessidade Alguma de funções, diferença se faz 
diretamente, assumindo 12 meses ao ano, tipo assim :

sc...@o10gr2:SQL>l
  1 DECLARE
  2     v_start_date date := to_date('&dia_mes_ano_ini', 'dd/mm/yyyy');
  3     v_end_date   date := to_date('&dia_mes_ano_fim', 'dd/mm/yyyy');
  4  BEGIN
  5     dbms_output.put_line(  'anos=' || trunc(months_between(v_end_date, 
v_start_date) / 12)      ||
  6                          ',meses=' || trunc(mod(months_between(v_end_date, 
v_start_date), 12))  ||
  7                           ',dias=' || trunc(v_end_date - 
add_months(v_start_date, trunc(months_between(v_end_date, v_start_date))))
  8                         );
  9* END;
  
==> vejamos uns exemplos :

sc...@o10gr2:SQL>/
Informe o valor para dia_mes_ano_ini: 20/11/2009
Informe o valor para dia_mes_ano_fim: 20/11/2009

anos=0,meses=0,dias=0

=> ok, pegou o caso de sem diferença, agora vamos bottar uns anos (E VEJA que 
teve bissextos no intervalo, não terá prob algum ) :

sc...@o10gr2:SQL>/

Informe o valor para dia_mes_ano_ini: 20/02/2000
Informe o valor para dia_mes_ano_fim: 28/02/2009

anos=9,meses=0,dias=8

==> agora pegando séculos diferentes : 

sc...@o10gr2:SQL>/
Informe o valor para dia_mes_ano_ini: 10/01/1998
Informe o valor para dia_mes_ano_fim: 31/03/2009

anos=11,meses=2,dias=21

==> agora pegando mais de cem anos, ie, vários séculos no intervalo, mas com 
números redondos sempre pra ficar fácil de conferir :


sc...@o10gr2:SQL>/
Informe o valor para dia_mes_ano_ini: 01/01/1800
Informe o valor para dia_mes_ano_fim: 31/12/2130

anos=330,meses=11,dias=30

==> finalmente, um caso de número do dia de início e/ou mês maior que o dia/mês 
final, que não tinha tido :

sc...@o10gr2:SQL>/
Informe o valor para dia_mes_ano_ini: 30/12/2005
Informe o valor para dia_mes_ano_fim: 15/08/2009

anos=3,meses=7,dias =16

==> no exemplo acima, SE vc fizesse a contragem simples , de 2005 até 2009  
daria 04, e de dezembro (Mês 12, o final) até o mês 08 daria 8 meses, ** MAS ** 
é esse o correto, quando não completou anos/meses extaos se quer a fração nesse 
caso - a rotina reconheceu que NÃO chegou a completar 4 anos nem 8 meses, yes 
??? Veja o que acontece se eu "completar" os 16 dias que ficaram de fração :

sc...@o10gr2:SQL>/
Informe o valor para dia_mes_ano_ini: 30/12/2005
Informe o valor para dia_mes_ano_fim: 31/08/2009

anos=3,meses=8,dias =1

==> Belezinha, a rotina ** reconheceu ** certinho que o mês fechou, ** mas ** 
como o Mês de Agosto tem 31 dias tá lá o dia extra da fração .... Vamos 
completar o ano, com e sem o dia extra que Dezembro tem ???

sc...@o10gr2:SQL>/
Informe o valor para dia_mes_ano_ini: 30/12/2005
Informe o valor para dia_mes_ano_fim: 31/12/2009

anos=4,meses=0,dias =1

e... 

sc...@o10gr2:SQL>/
Informe o valor para dia_mes_ano_ini: 30/12/2005
Informe o valor para dia_mes_ano_fim: 30/12/2009

anos=4,meses=0,dias =0

Procedimento PL/SQL concluído com sucesso.

==>> TAÍ, reconheceu CERTINHO quando foi o número exato de anos e/ou meses, a 
fração (se houve) foi pra Dias...Veja o que acontece se eu não completar o Mês :

sc...@o10gr2:SQL>/
Informe o valor para dia_mes_ano_ini: 30/12/2005
Informe o valor para dia_mes_ano_fim: 25/12/2009

anos=3,meses=11,dias =25

==> Certinho, ela reconhecu que havia menos de 4 anos, a 'sobra' era de 3 anos 
, 11 meses e 25 dias... Legal ?? Veja que a ÚNICA exigência é que realmente a 
data inicial seja MESMO menor que a data final, pois a contagem será feita A 
partir dela, ok ? Creio que sem probs, pela definição do colega q fez a 
pergunta....

 []s
 
  Chiappa

--- Em [email protected], Elis Azevedo Nery <elisn...@...> escreveu
>
> Aí vai um código tirado da net:
> CREATE OR REPLACE FUNCTION BISSEXTO (VANO IN NUMBER) RETURN BOOLEAN 
> IS 
>   VRESTO1 NUMBER(5,2); 
>   VRESTO2 NUMBER(5,2); 
>   VRESTO3 NUMBER(5,2); 
> BEGIN 
>   VRESTO1 := MOD(VANO,4); 
>   VRESTO2 := MOD(VANO,100); 
>   VRESTO3 := MOD(VANO,400); 
> 
>   IF ((VRESTO1 = 0 AND VRESTO2 <> 0 ) OR VRESTO3 = 0) THEN 
>   DBMS_OUTPUT.PUT_LINE(VANO || ' É UM ANO BISSEXTO'); 
>   RETURN TRUE; 
>   ELSE 
>   DBMS_OUTPUT.PUT_LINE (VANO || ' NÃO É UM ANO BISSEXTO'); 
>   RETURN FALSE; 
>   END IF; 
> 
> 
> Abraço
> Elis
> 
> 
> 
> 
> ________________________________
> De: grimaldol_lopes <grimaldo_lo...@...>
> Para: [email protected]
> Enviadas: Sexta-feira, 20 de Novembro de 2009 18:54:17
> Assunto: [oracle_br] Re: Calculo de datas - Ano Mes e Dia
> 
>   
> 
> Dougla , meu amigo, obrigado pela ajuda, mas o problema é que o calculo deve 
> envolver os anos bissextos, este é o problema, como você havia feito eu 
> realemnte tinha aqui comigo, mas o cliente quer com os bissextos, e ai, 
> alguma dica?, Obrigado.
> 
> --- Em oracle...@yahoogrup os.com.br, Douglas Falcão <listas.dfalcao@ ...> 
> escreveu
> >
> > Grimaldo..
> > 
> > sabendo que Data2 - Data1 = diferenca_em_ dias, bastam alguns cálculos sobre
> > esse número para que chegue onde quer
> > 
> > Ex.:
> > 
> > SQL> select sysdate from dual;
> > SYSDATE
> > --------
> > 20/11/09
> > SQL> select sysdate - to_date('10/ 03/1981', 'dd/mm/yyyy' ) from dual;
> > SYSDATE-TO_DATE( '10/03/1981' ,'DD/MM/YYYY' )
> > ------------ --------- --------- --------- ---
> > 10482,5882
> > 
> > PARA CACULAR o ANO:
> > 
> > SQL> select 10482.5882 /365 from dual;
> > ----------
> > 28,7194197
> > 
> > SQL> select trunc(10482. 5882 /365) anos from dual;
> > ANOS
> > ----------
> > 28
> > 
> > PARA CALCULAR OS MESES
> > 
> > SQL> select 12 * 0.7194197 from dual;
> > 12*0.7194197
> > ------------
> > 8,6330364
> > SQL> select trunc(12 * 0.7194197) meses from dual;
> > 
> > MESES
> > ----------
> > 8
> > 
> > Segue o mesmo raciocínio para a quantidade de dias, horas, minutos, sempre
> > trablahando com a parte decimal.
> > 
> > 
> > DICA: Coloca essa encrenca de forma procedural e cria uma função que retorne
> > o que tu quiser cfe. parâmetros.
> > 
> > 
> > Att.
> > 
> > Douglas Falcão.
> > 
> > 
> > 2009/11/20 Grimaldo Lopes <grimaldo_lopes@ ...>
> > 
> > >
> > >
> > >
> > >
> > > Caros colegas, necessio de um select para que me retorne a diferença entre
> > > duas datsa em anos mes e dias.
> > >
> > > Ex: 01/01/2009
> > >
> > > 10/02/2010
> > >
> > > Resposta: 01 ano 01 mes e 09 dias
> > >
> > > Isso é possível?.
> > >
> > > Grimaldo
> > >
> > >
> > > ____________ _________ _________ _________ _________ _________ _
> > > Converse e compartilhe fotos ao mesmo tempo. Saiba como no novo Site de
> > > Windows Live.
> > > http://www.windowsl ive.com.br/ ?ocid=WindowsLiv e09_MSN_Hotmail_ 
> > > Tagline_out09
> > >
> > > [As partes desta mensagem que não continham texto foram removidas]
> > >
> > > 
> > >
> > 
> > 
> > 
> > -- 
> > Douglas Falcão
> > ------------ --------- --------- --------- --------- -------
> > Oracle Certified Application Developer
> > Sun Java Certified Associate
> > ------------ --------- --------- --------- --------- -------
> > Business Analyst / Business Intelligence Analyst
> > mail: douglas dot falcao at gmail dot com
> > 
> > 
> > [As partes desta mensagem que não continham texto foram removidas]
> >
> 
> 
> 
> 
> 
>       
> ____________________________________________________________________________________
> Veja quais são os assuntos do momento no Yahoo! +Buscados
> http://br.maisbuscados.yahoo.com
> 
> [As partes desta mensagem que não continham texto foram removidas]
>


Responder a