GARANTIR DESCONTO

Fórum Tem BUG na função MonthsBetween #214328

15/02/2004

0

As variaveis são:

dataadm,datadem:TDateTime;
mes:integer

a atribuição é:
dataadm := StrToDate(MaskEdit1.Text);
datadem := StrToDate(MaskEdit2.Text);
//Calcular qtos meses tem nas datas informadas
mes := MonthsBetween(dataadm, datadem);


o formato da mascara é: 00/00/0000



Esse ´bug´ só ocorre no mês de fevereiro

Erro:

02/02/2004
02/03/2005

Ele retorna a quantidade de mês igual a 12, deveria ser 13

02/03/2004
02/04/2005

Ele retorna a quantidade de mês igual a 13

Eu notei q este erro só ocorre no mês de fevereiro, em um ano (ex: entre 02/[b:3fef76338d]03[/b:3fef76338d]/2004 a 02/[b:3fef76338d]04[/b:3fef76338d]/2006 retorna 25 meses, mais em 02/[b:3fef76338d]02[/b:3fef76338d]/2004 a 02/[b:3fef76338d]03[/b:3fef76338d]/2006 retorna 24 meses, antes q digam, eu diminui as mêses!!!, por tanto seria 25 tb )

E quando houver um diferença de 3 dias na data, da certo ex: se 01/03/2004 a 03/03/2004 tem 1 mês, 02/02/2004 a 05/03/2004 tem 1 mês, 03/03/2004 a 06/03/2004 tem 1 mês, etc... .

E tb:
01/01/2004 a 09/03/2004 ele retorna 2 meses, porem 01/03/2004 a 09/06/2004 ele retorna 3 meses, ele pula o mês de fevereiro

Desde já agradeço

O programa esta disponível em http://superdownloads.ubbi.com.br/download/i24496.html


Wolverine

Wolverine

Responder

Posts

15/02/2004

Beppe

Esse pode até ser um comentário idiota, mas não será por causa dos anos bissextos?


Responder

Gostei + 0

15/02/2004

Wolverine

eu tb pensei nisto, mais ñ é, e bug contece para bi ou ñ, é so no infeliz do mes de Fevereiro


Responder

Gostei + 0

16/02/2004

Adilsond

Essas bibliotecas foram incorporadas ao delphi da RxLib. Testei com o Delphi3 utilizando as funções da RxLib e funcionou normalmente. Ex:

procedure TForm1.Button1Click(Sender: TObject);
var
  DataAdm,
  DataDem: TDateTime;
  Mes: Double;
begin
  DataAdm := StrToDate(´02/02/2004´);
  DataDem := StrToDate(´02/03/2005´);
  Mes := DateUtil.MonthsBetween(DataAdm, DataDem);
  Edit1.Text := IntToStr(Trunc(Mes));
end;


O resultado é 13


Responder

Gostei + 0

16/02/2004

Wolverine

:cry:


Responder

Gostei + 0

17/02/2004

Wolverine

AdilsonD ñ deu certo no DELPHI 6, continua informando 12 e ñ 13 q seria o certo

Continuo perguntando!

[color=red:aeef98bdd8][size=24:aeef98bdd8][b:aeef98bdd8]Tem BUG na função MonthsBetween[/b:aeef98bdd8][/size:aeef98bdd8][/color:aeef98bdd8]


Responder

Gostei + 0

01/03/2004

Wolverine

gente, destei em DP 7 e tb da erro

uses DateUtils

var
DataAdm,
DataDem: TDateTime;
Mes: Double;
begin
DataAdm := StrToDate(´02/02/2004´);
DataDem := StrToDate(´02/03/2004´);
Mes := MonthsBetween(DataAdm, DataDem);
Edit1.Text := IntToStr(Trunc(Mes));
end;


Responder

Gostei + 0

01/03/2004

Wolverine

gente, destei em DP 7 e tb da erro

uses DateUtils

var
DataAdm,
DataDem: TDateTime;
Mes: Double;
begin
DataAdm := StrToDate(´02/02/2004´);
DataDem := StrToDate(´02/03/2004´);
Mes := MonthsBetween(DataAdm, DataDem);
Edit1.Text := IntToStr(Trunc(Mes));
end;

ele me retorna [b:11e095e861]0[/b:11e095e861]


Responder

Gostei + 0

02/03/2004

Adilsond

Veja onde está o problema. Veja diferença.

procedure TForm1.Button1Click(Sender: TObject);
var
  DataAdm,
  DataDem: TDateTime;
  Mes: Double;
begin
  ShortDateFormat := ´mm/dd/yyyy´;
  DataAdm := StrToDate(´02/02/2004´);
  DataDem := StrToDate(´02/03/2005´);
  Mes := DateUtil.MonthsBetween(DataAdm, DataDem);
  Edit1.Text := IntToStr(Trunc(Mes)); // o resultado é 12
end;


procedure TForm1.Button2Click(Sender: TObject);
var
  DataAdm,
  DataDem: TDateTime;
  Mes: Double;
begin
  ShortDateFormat := ´dd/mm/yyyy´;
  DataAdm := StrToDate(´02/02/2004´);
  DataDem := StrToDate(´02/03/2005´);
  Mes := DateUtil.MonthsBetween(DataAdm, DataDem);
  Edit1.Text := IntToStr(Trunc(Mes)); // o resultado é 13
end;


Utilizando a RXlib (´Uses DateUtil´). Testei utilizando o Delphi3 e o 5 e o resultado é o mesmo. A função desta biblioteca está abaixo:

function MonthsBetween(Date1, Date2: TDateTime): Double;
var
  D, M, Y: Word;
begin
  DateDiff(Date1, Date2, D, M, Y);
  Result := 12 * Y + M;
  if (D > 1) and (D < 7) then Result := Result + 0.25
  else if (D >= 7) and (D < 15) then Result := Result + 0.5
  else if (D >= 15) and (D < 21) then Result := Result + 0.75
  else if (D >= 21) then Result := Result + 1;
end;



Responder

Gostei + 0

04/03/2004

Wolverine

Amigo, escrevi oq vc postou no Delphi 7, mais:

1° erro: a biblioteca DateUtil ñ exite exite DateUtil[b:5c36b8e702]s[/b:5c36b8e702]

2° erro: tanto Mes := DateUtil.MonthsBetween(DataAdm, DataDem); quanto Mes := DateUtil[b:5c36b8e702]s[/b:5c36b8e702].MonthsBetween(DataAdm, DataDem); da erro (Undeclered identifer:´DateUtil´ //ou DateUtil[b:5c36b8e702]s[/b:5c36b8e702])
3° erro: ele retorna 12

a unica solução q tive foi fazer a minha propria logica q deu certo

procedure TForm1.Button1Click(Sender: TObject);
var
  DataAdm,
  DataDem: string;
  Mes: integer;
begin
  ShortDateFormat := ´dd/mm/yyyy´;
  DataAdm := ´02/02/2004´;
  DataDem :=´02/03/2005´;
  Mes := mesentredatas(dataadm, DataDem);
  Edit1.Text := IntToStr(Trunc(Mes)); // o resultado é 13
end;


function TForm1.mesentredatas(datatotainicial, datatotafinal: string): integer;
var
  mesini,mesfin,mes,anoini,anofin,ano,cont,cont1,I:integer;
begin
  mesini:=strtoint(copy (datatotainicial,4,2));
  mesfin:=strtoint(copy (datatotafinal,4,2));
  anoini:=strtoint(copy (datatotainicial,7,4));
  anofin:=strtoint(copy (datatotafinal,7,4));
  mes:=0;
  ano:=0;
// um if para saber se o funcionário ficou mais de um ano na empresa
  if anoini<anofin then
  begin
  // este for é para contar(cont) quantos anos e adicionar 12(cont1)x quantidade(cont) em mêses
    for I:=anoini to anofin do
    begin
      cont:=cont+1;
      cont1:=cont1+12;
    end;
    mesini:=12-mesini;
    mes:=((mesini+mesfin+cont1)-24);
  end
// este eles é para saber se ele ficou até um ano
  else
  begin
    mesini:=12-mesini;
    mesfin:=12-mesfin;
    mes:=(mesini-mesfin);
  end;
  Result:=mes
end;



Responder

Gostei + 0

07/03/2004

Wolverine

Para resolver isso, eu escrevi essa rotina: 

Código: 
function MesEntreDatas(DataInicial, DataFinal: TDateTime): integer; 
var DataIni, DataFim: TDateTime; 
      Dias, Meses, Anos: integer; 
begin 
    if DataInicial > DataFinal then 
    begin 
        DataIni := Trunc(DataFinal); 
        DataFim := Trunc(DataInicial); 
    end 
    else 
    begin 
        DataIni := Trunc(DataInicial); 
        DataFim := Trunc(DataFinal); 
    end; 

    Dias := Trunc(DayOfTheMonth(DataFim) - DayOfTheMonth(DataIni)); 
    Meses := Trunc(MonthOf(DataFim) - MonthOf(DataIni)); 
    Anos := Trunc(YearOf(DataFim) - YearOf(DataIni)); 
    if Dias < 0 then Dec(Meses); 

    Result := Meses + (Anos * 12); 
end; 


assim como a minha, tb da certo, so q com menos codigo e evita dar bug em relação com as configurações regionais de cada PC, falew :lol:


Responder

Gostei + 0

07/03/2004

Marco Salles

Por Gentileza ´Emerson.EN´ , Todas as Funções Usadas Na Sua Rotina Estão Na Uses ´DateUtils´ :?: :?: Meu Delphí é o 5.0 , Não Tem Essa Units :?: Tem Condições De Baixa-la :?:


Responder

Gostei + 0

07/03/2004

Marco Salles

Esta Questão De Data, Deve Ser Colocada Com Cautela..A Função Brilhantemente Apresentada Pelo Nosso Amigo Emerson, No Meu Ponto De Vista, Não Deve Ser Confrontada Com a Função MonthsBetween(dataadm, datadem);...As Duas Funções Seguem Definições De Datas Distintas... O Que e Extremamente Viável, Diga-se De Passagem , Porque Ninguem Conseguiu Determinar Com Precissâo Um Sistema Exato De Calendários..A Própia Natureza(Rotação Da Terra Etc...), Não Favorece ... Então Haverá Sempre Ressalvas Que Poderão Ser Questionadas... O Própio Emerson Em Uma De Suas Colocações Anteriores Levantou o Problema:
realmente há um Bug na função MonthsBetween. Isso ocorre porque ela trabalha com uma constante com o número médio de dias no mês (30.4375 - devido aos anos bissextos) e o mês de fevereiro está bem longe desse valor.


Veja a Função Abaixo Que Se Aproxima Em Principio Da Função MonthsBetween:
function MesEntreDatas2(DataInicial, DataFinal: TDateTime): integer;
var
Diferenca:TDateTime;
begin
Diferenca:=Abs(DataFinal-DataInicial);
Result:=Trunc((12*Diferenca)/365.2421969697);//Obs:Valor Medio
end;


Esta Função <Para Diferenças De Datas Pequena> Tenderá a Ter Um Comportamento Parecedissímo Com a Função MonthsBetween, e Para <Diferenças De Datas Grandes> Ela Tenderá a Se Comporta Com a Função Apresentada Pelo Emerson... Qual é a Certo :?: Ou Qual é a Que Esta Errada :?:

Isto, No Meu Ver Vai Depender Do Que Voce Procura :!: Para Um Sistema Financeiro Por Exemplo Onde a Quantidade De Dias é Fartor Crucial Eu não Aplicaria a Função Do Emerson..Explico:Se Voce Comprar Em 01/02/2003 em 01/03/2003 Já Se Foram 1 Mes..Mas Na Verdade Foram 28 Dias..Então Se Esta No Caso Antecipando o Pagamento..Em Termos De Juros Isto Tem Que Ser Considerado...

Já Para Um Sistema Onde Se Necessita De Meses E Não De Dias , Como Por Exemplo Uma Folha De Pagamento (Funcionário Que Trabalha No Mes Fevereiro= 28 Dias Recebe o Mesmo Valor Quando Trabalha No Mes De Março= 31Dias), O Sistema Do Emerson é Altamente Aplicavel...

O Que Quero Na Verdade Com Tudo Isto é Dar Minha Contribuição,
Esclarecendo Que Na Minha Opinião Não Há Bug Na Função MonthsBetween,E Dependendo Do Sistema Ela Pode Ser Conviavelmente Aplicada..

Mas Falando Nisso , Eu Ainda Não Consegui:
Por Gentileza ´Emerson.EN´ , Todas as Funções Usadas Na Sua Rotina Estão Na Uses ´DateUtils´ Meu Delphí é o 5.0 , Não Tem Essa Units Tem Condições De Baixa-la



Responder

Gostei + 0

07/03/2004

Marco Salles

Esta Questão De Data, Deve Ser Colocada Com Cautela..A Função Brilhantemente Apresentada Pelo Nosso Amigo Emerson, No Meu Ponto De Vista, Não Deve Ser Confrontada Com a Função MonthsBetween(dataadm, datadem);...As Duas Funções Seguem Definições De Datas Distintas... O Que e Extremamente Viável, Diga-se De Passagem , Porque Ninguem Conseguiu Determinar Com Precissâo Um Sistema Exato De Calendários..A Própia Natureza(Rotação Da Terra Etc...), Não Favorece ... Então Haverá Sempre Ressalvas Que Poderão Ser Questionadas... O Própio Emerson Em Uma De Suas Colocações Anteriores Levantou o Problema:
realmente há um Bug na função MonthsBetween. Isso ocorre porque ela trabalha com uma constante com o número médio de dias no mês (30.4375 - devido aos anos bissextos) e o mês de fevereiro está bem longe desse valor.


Veja a Função Abaixo Que Se Aproxima Em Principio Da Função MonthsBetween:
function MesEntreDatas2(DataInicial, DataFinal: TDateTime): integer;
var
Diferenca:TDateTime;
begin
Diferenca:=Abs(DataFinal-DataInicial);
Result:=Trunc((12*Diferenca)/365.2421969697);//Obs:Valor Medio
end;


Esta Função <Para Diferenças De Datas Pequena> Tenderá a Ter Um Comportamento Parecedissímo Com a Função MonthsBetween, e Para <Diferenças De Datas Grandes> Ela Tenderá a Se Comporta Com a Função Apresentada Pelo Emerson... Qual é a Certo :?: Ou Qual é a Que Esta Errada :?:

Isto, No Meu Ver Vai Depender Do Que Voce Procura :!: Para Um Sistema Financeiro Por Exemplo Onde a Quantidade De Dias é Fartor Crucial Eu não Aplicaria a Função Do Emerson..Explico:Se Voce Comprar Em 01/02/2003 em 01/03/2003 Já Se Foram 1 Mes..Mas Na Verdade Foram 28 Dias..Então Se Esta No Caso Antecipando o Pagamento..Em Termos De Juros Isto Tem Que Ser Considerado...

Já Para Um Sistema Onde Se Necessita De Meses E Não De Dias , Como Por Exemplo Uma Folha De Pagamento (Funcionário Que Trabalha No Mes Fevereiro= 28 Dias Recebe o Mesmo Valor Quando Trabalha No Mes De Março= 31Dias), O Sistema Do Emerson é Altamente Aplicavel...

O Que Quero Na Verdade Com Tudo Isto é Dar Minha Contribuição,
Esclarecendo Que Na Minha Opinião Não Há Bug Na Função MonthsBetween,E Dependendo Do Sistema Ela Pode Ser Conviavelmente Aplicada..

Mas Falando Nisso , Eu Ainda Não Consegui:
Por Gentileza ´Emerson.EN´ , Todas as Funções Usadas Na Sua Rotina Estão Na Uses ´DateUtils´ Meu Delphí é o 5.0 , Não Tem Essa Units Tem Condições De Baixa-la



Responder

Gostei + 0

08/03/2004

Marco Salles

Acho Que Devo Finalisar Com Algumas Citações:
Wolverine Usando a Função MonthsBetween Observou Que a Função
Retornava Para Determinadas Datas Um Valor Que Fugia Da Razão:
Entre 01/02/20003 a 01/03/2003 Por Exemplo a Funçao Retorna ´Zero´...
A Expicação para Isto Foi Data Pelo Emerson Quando Em Sua Citação
Alegou Que Esta Função Trabalha ´Com Uma Média E O Mes De Fevereiro Esta Longe Disto´...E Além Disto Ele Mostrou Uma Função Que Parece Estar Bem Mais Próxima Da Realidade...O Que Eu Tentei Passar Que é Extremamente Plausível Existir Diferenças Na Definição De Meses..Um Mes o Que Que é :?: (30 Dias Decorridos De Uma Data :?: Se Completa Um Mes A Partir Da Data Do Mes Seguinte Que Suceder Imediatamente ao Dia Do Mes SubJacente :?: ) Ora Uma Definição Vai Levar Em Determinadas Situações Vantagens Em Relação a Outra ....
Empreste Dinheiro a Uma Pessoa Em 01/02/2003 E Cobre-a Em 01/03/2003 => Ela Vai Alegar : [color=red:b36063a0b7]Mas Ainda Não Deu 30 Dias[/color:b36063a0b7] Empreste Dinheiro a Uma Pessoa Em 01/03/2003 E Cobre-a Em 31/03/2003 = > Ela Vai Alegar : [color=red:b36063a0b7]Mas Ainda Não Deu Um Mes [/color:b36063a0b7]

E Por Fim Eu Acredito Que Bug São Situações Inesperads Que Ocorrem e Onde Não Há Devido Tratamento Para Elas... Por visto o Autor Desta Função No Meu Entender Preferiu Trabalhar Com Media, E Como Se Definir a Função MonthsBetween, Como a Que Descrevi Anteriormente:
function MesEntreDatas2(DataInicial, DataFinal: TDateTime): integer; 
var 
Diferenca:TDateTime; 
begin 
Diferenca:=Abs(DataFinal-DataInicial); 
Result:=Trunc((12*Diferenca)/365.2421969697);//Obs:Valor Medio 
end;

Esta Função Irá Dar o Mesmo Problema Que A Função MonthsBetween...

P.S.: a segunda forma da função, utilizando DecodeDate() não funcionou?


Funcionou, Mas Independendo Disto Eu Gostaria De:
Por Gentileza ´Emerson.EN´ , Todas as Funções Usadas Na Sua Rotina Estão Na Uses ´DateUtils´ Meu Delphí é o 5.0 , Não Tem Essa Units Tem Condições De Baixa-la



Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar