Ajuda - Busca - Membros - Calendário
Versão Completa: (Resolvido) Função Monthsbetween (datas Em Meses E Dia)
Fórum Script Brasil > Programação & Desenvolvimento > Delphi, Kylix
carlinhosprog
Estou usando a função "Monthsbetween" para retornar a diferença em meses de dias datas, so que esta função não esta me dando os valores corretos. Por exemplo:
a diferança entre as data 01/07/07 e 31/12/07, ela retorna 7 meses.

eu so queria uma funcao de me desse a diferença entre duas datas em meses e dias, no caso acima ela me retornaria 6 meses.
Jhonas
Tenta essa:

CODE
function DifDias(DataVenc:TDateTime; DataAtual:TDateTime): String;
Var Data: TDateTime;
dia, mes, ano: Word;
begin
if DataAtual < DataVenc then
begin
Result := 'A data data atual não pode ser menor que a data inicial';
end
else
begin
Data := DataAtual - DataVenc;
DecodeDate( Data, ano, mes, dia);
Result := FloatToStr(Data)+' Dias';
end;
end;


Dica de Marco Barki Algranti
Micheus
QUOTE(carlinhosprog @ 17/09/2007 - 17:45) *
Estou usando a função "Monthsbetween" para retornar a diferença em meses de dias datas, so que esta função não esta me dando os valores corretos. Por exemplo:
a diferança entre as data 01/07/07 e 31/12/07, ela retorna 7 meses.

eu so queria uma funcao de me desse a diferença entre duas datas em meses e dias, no caso acima ela me retornaria 6 meses.
aqui, este código coloca 6 no label:
Label1.Caption := IntToStr(MonthsBetween(StrToDate('01/07/07'), StrToDate('31/12/07')));
carlinhosprog
é o seguinte quando eu uso a função acima com as seguintes datas (01/06/07 e 31/12/07) o resultado é 6, mas com as datas (01/06/07 e 31/01/08) o resultado é 8 sendo que a diferença entre as duas datas é de apenas 1 mes.
Micheus
QUOTE(carlinhosprog @ 18/09/2007 - 14:14) *
é o seguinte quando eu uso a função acima com as seguintes datas (01/06/07 e 31/12/07) o resultado é 6, mas com as datas (01/06/07 e 31/01/08) o resultado é 8 sendo que a diferença entre as duas datas é de apenas 1 mes.

Comigo, continua retornando certo. Agora, este código coloca 7 no label.
Label1.Caption := IntToStr(MonthsBetween(StrToDate('01/07/07'), StrToDate('31/01/08')));

Você não poderia colocar parte do código onde você manipula a função e/ou variáveis?
Parece que há algo no seu código, já que no post inicial, deveria retornar 6 e você obtinha 7; no segundo post, deveria retornar 7 e você diz obter 8...

De qualquer modo, esta função retorna uma aproximação. Veja o que diz o help:
"Because months are not all the same length, MonthsBetween returns an approximation based on an assumption of 30.4375 days per month. Fractional months are not counted. Thus, for example, MonthsBetween reports the difference between Feb 1 and Mar 1 as 0."
traduzindo:
Pelo fato de os meses não terem o mesmo número de dias, MonthsBetween retorna uma aproximação baseada em uma média - 30.4375 dias por mês. Fração de meses não são contados. Assim, por exemplo, MonthsBetween retorna a diferença entre 1 de Fev e 1 de Mar como 0 (zero).
E isto pode realmente gerar algum transtorno.

Para contar dias entre duas datas, você pode utilizar a função que o colega Jhonas citou antes.
Mas se for para contar apenas meses, seria o caso de retornar lá na função apenas o valor da variável Mes. Ainda assim, você deve verificar se você pretende fazer algum arredondamento. Por ex. 3 meses e 20 dias, você poderia querer considerar 4 meses. Neste caso, outras avaliações se fazem necessárias.
Carlinhosprog
eu quero esta função para fazer calculo trabalhista, por isso preciso com exatidão o meses e dias. voces não conhecem outra forma de fazer esse calculo?


obrigado pela dicas acima.
Micheus
QUOTE(Carlinhosprog @ 19/09/2007 - 08:15) *
eu quero esta função para fazer calculo trabalhista, por isso preciso com exatidão o meses e dias. voces não conhecem outra forma de fazer esse calculo?
Carlinhosprog, se fosse para contar dias corridos, você poderia utilizar parte do código do Jhonas para os obter dias exatos.

Ocorre que TDateTime/TTime/TDate são do tipo Float, onde a parte inteira corresponde à data. por isso ele fez este cálculo:
Data := DataAtual - DataVenc;
logo, em Data, você terá a diferença em dias entre as duas datas em questão. Um valor 0 (zero, ou seja datas no mesmo dia) corresponde a data 30/12/1899 e tratar este resultado como uma data comum pode ser meio complicado. Ao utilizar a função:
DecodeDate(Data, ano, mes, dia);
as variáveis ano, mes e dia, vão conter 1899, 12 e 30 respectivamente. Então, acho que esta saída não será a melhor para a sua aplicação.
Experimente algo como o que está abaixo e veja se é o que procura:
CODE
procedure TForm1.BtnCalculaDiferenca(Sender :TObject);
var
  Data1, Data2 :TDateTime
  Meses, Dias :Integer;
begin
// inicializa as variáveis com os valores
  Data1 := StrToDate(Edit1.Text);
  Data2 := StrToDate(Edit2.Text);
  Meses := 0;
  Dias := 0;
// computa meses transcorridos entre as datas
  while IncMonth(Data1) < Data2 do
  begin
    Data1 := IncMonth(Data1);
    Inc(Meses);
  end;
// a diferença que sobra são os dias (+1 para incluir do 1º ao último)
  Dias := Trunc(Data2 -Data1) +1;
// neste ponto você tem os valores
  Label1.Caption := Format('%d meses e %d dias', [Meses, Dias]);
end;
Carlinhos
Eu fiz o seguinte procedimento de ficou certo, ele retorna em duas variaveis a quantidade de mes(es) e dia(s) entre dias datas.
CODE
procedure tfrmfolhapag.difmes(data1,data2:string; var contmes,contdia:integer);
{as variaveis data1 e data2 são de entrada onde coloca-se as datas para se calcular a diferença entre elas em meses e dias}
{a variavel contmes recebe o total de meses inteiro entre as duas data, e a contdia recebe os dias}
var ano, mes, dia, ano2, mes2, dia2: word;
     achoumes,achoumescompleto : boolean;
procedure primeiromes;
begin
achoumes := false;
   if achoumescompleto then
    begin
     contmes := 1;
     achoumes := true;
    end
     else
      begin
       contdia := dia2 - dia +1;
       achoumes := true;
      end;
end;
procedure verificames;
begin
  if (dia = 1) and (dia2 = daysinmonth(strtodate(data2))) then
    achoumescompleto := true
   else
    achoumescompleto := false;
end;
procedure calculomescompleto;
begin
mes2 := mes2+((ano2-ano)*12);
contmes := mes2-mes+1;
achoumes := true;
end;
{area teste}
procedure calculomesincompleto;
var
data3: string;
begin
if dia2 >= dia -1 then
  begin
   mes2 := mes2+((ano2-ano)*12);
   contmes := mes2-mes;
   contdia := dia2 - dia +1;
   achoumes := true;
  end
  else
   begin
    data3 := '01/'+inttostr(mes2-1)+'/'+inttostr(ano2);
    mes2 := mes2+((ano2-ano)*12);
    contmes := mes2-mes-1;
    contdia := (dia2+daysinmonth(strtodate(data3))) - dia +1;
    achoumes := true;
   end;
end;
{area teste}
begin
  contmes := 0;
  contdia := 0;
  decodedate(strtodate(data1),ano,mes,dia);
  decodedate(strtodate(data2),ano2,mes2,dia2);
  verificames;
  if (mes = mes2) and (ano = ano2) then
    primeiromes
   else if achoumescompleto then
      calculomescompleto
     else
      calculomesincompleto;
end;
--BRUNO --
QUOTE(carlinhosprog @ 17/09/2007 - 17:45) *
Estou usando a função "Monthsbetween" para retornar a diferença em meses de dias datas, so que esta função não esta me dando os valores corretos. Por exemplo:
a diferança entre as data 01/07/07 e 31/12/07, ela retorna 7 meses.

eu so queria uma funcao de me desse a diferença entre duas datas em meses e dias, no caso acima ela me retornaria 6 meses.

CODE
var
  YearI, MonthI, DayI: Word;
  YearF, MonthF, DayF: Word;
  ANO, MESES: INTEGER;
begin
  DecodeDate(StrToDate(MaskEdit1.text), YearI, MonthI, DayI);
  DecodeDate(StrToDate(MaskEdit2.text), YearF, MonthF, DayF);
  ANO := YearF - YearI;
  MESES := ((MonthF - MonthI) + (12 * ANO)) + 1;
  showmessage(INTTOSTR(MESES));
end;
Esta é uma versão simplificada de nosso conteúdo principal. Para ver a versão completa com maiores informações, formatação e imagens, por favor clique aqui.
Invision Power Board © 2001-2012 Invision Power Services, Inc.