Ajuda - Busca - Membros - Calendário
Versão Completa: (Resolvido) intervalo de horas - calcular minutos - está com prob
Fórum Script Brasil > Programação & Desenvolvimento > Delphi, Kylix
Tatiane.InterArt
Tenho uma telinha de cartão de ponto, onde para cada intervalo faço cálculo de atrazo e extra usando o
MinutesBetween, o que está acontecendo é que dependendo do horário q tenho ele não retorna corretamente os minutos, por exemplo:

MaskEdit5 - MaskEdit6
18:00 - 18:54
12:00 - 12:54

e outras variações com minutos diferenciados

Var Min:Integer;
Begin
Min:=MinutesBetween(StrToTime(MaskEdit5.Text),StrToTime(MaskEdit6.Text));

Min deveria ser igual a 54 correto
mas ele me mostra 53

o que acontece é q essa diferença de 1min já faz uma grande diferença no cálculo de hora extra, como posso resolver isso?
Jhonas
tenta desta maneira:

QUOTE
Var Min:Integer;
Begin
Min:=MinutesBetween(StrToTime(MaskEdit5.Text),StrToTime(MaskEdit6.Text));
if pos(':00',MaskEdit5.Text) > 0 then
Min := Min + 1;


abraço
Rento
Eu vendo controle de ponto, mas como sou bonzinho vou postar:
CODE
function  fDiasDeAtraso(pData1, pData2: TDate): Integer;
var
  X, Y: Integer;
begin
   X := Trunc(pData1 - pData2);
   Y := 0;
   while X > 0 do
      begin
      X := X - 1;
      Y := Y + 1440;
      end;
   Result := Y;
end;
function  fMinAtraso(pHrNorm: string): Integer;
var
  lvNormDate: TDate;
  lvNormTime: TTime;
  lvTempResult: Integer;
begin
   lvNormDate := StrToDate(fFormat(Copy(pHrNorm, 1, 8), rrDbDate));
   lvNormTime := StrToTime(Copy(pHrNorm, 9, 2) + ':' + Copy(pHrNorm, 11, 2));
   if (lvNormDate = Date) and (lvNormTime = Time) then
      lvTempResult := 0
   else
      begin
      if (lvNormDate = Date) then
         lvTempResult := fTimeToMin(lvNormTime, Now)
      else
         begin
         if (lvNormDate > Date) then
            begin
            lvTempResult := fDiasDeAtraso(lvNormDate, Date);
            lvTempResult := lvTempResult + fTimeToMin(lvNormTime, Now);
            end
         else
            lvTempResult := -1;
         end;
      end;
   Result := lvTempResult;
end;
function  fMinAntes(pHrNorm: string): Integer;
   //---------------------------------------------------------------------------
   function  fTimeToMin2(pMin1, pMin2:ttime): Integer;
   var
     lv1, lv2: Integer;
      //------------------------------------------------------------------------
      function fHourToMin(pTime: String): Integer;
      var
        lvHour, lvMin, lvIdx : Integer;
        lvTime : string;
      begin
         lvIdx := 3;
         lvTime := fSomNum(pTime);
         lvHour := StrToInt(Copy(lvTime, 1    , 2));
         lvMin  := StrToInt(Copy(lvTime, lvIdx, 2));
         Result := ((lvHour * MinsPerHour) + lvMin);
      end;
   begin
      lv1 := fHourToMin(TimeToStr(pMin1));
      lv2 := fHourToMin(TimeToStr(pMin2));
      Result := (lv2 - lv1);
   end;
   //---------------------------------------------------------------------------
var
  lvNormDate: TDate;
  lvNormTime: TTime;
  lvTempResult: Integer;
begin
   lvNormDate := StrToDate(fFormat(Copy(pHrNorm, 1, 8), rrDbDate));
   lvNormTime := StrToTime(Copy(pHrNorm, 9, 2) + ':' + Copy(pHrNorm, 11, 2));
   if (lvNormDate = Date) then
      lvTempResult := fTimeToMin2(Now, lvNormTime)
   else
      begin
      if (lvNormDate < Date) then
         begin
         lvTempResult := fDiasDeAtraso(Date, lvNormDate);
         lvTempResult := lvTempResult + fTimeToMin2(Now, lvNormTime);
         end
      else
         lvTempResult := 0;
      end;
   Result := lvTempResult;
end;

Não me lembro como programei, da uma olhada porque funciona ^^
CODE
lvAtraso := fMinAtraso(Copy(lvDtEnt, 9, 12));
            if (lvAtraso = -1) then
               begin
               lvAtraso := fMinAntes(Copy(lvDtEnt, 9, 12));
               if (lvPerm_entrada_antes) then
                  begin
                  rSalvaEntradaAdiantada();
                  rDefEnt();
                  fmArFrame[lvIndex].lblAviso.Caption := 'Entrou adiantado';
                  end
               else
                  begin
                  fmArFrame[lvIndex].lblAviso.Caption := 'Aguarde o horário de entrada';
                  end;
               end
            else
               begin
               if (lvAtraso > lvFalta) then
                  begin
                  fmArFrame[lvIndex].lblAviso.Caption := 'ATENÇÂO: Hoje foi considerado falta';
                  rExecSQL('UPDATE controle SET '+
                  'used = 0, saiu = "-1" WHERE entrada = "'+lvDtEnt+'"');
                  end
               else
                  begin
                  if (lvAtraso = 0) then
                     begin
                     rDefEnt();
                     fmArFrame[lvIndex].lblAviso.Caption := 'Entrou';
                     end
                  else
                     begin
                     rSalvaEntradaAtrasada();
                     rDefEnt();
                     fmArFrame[lvIndex].lblAviso.Caption := 'ENTROU ATRASADO: Devendo mais ' +
                        IntToStr(lvAtraso) + ' minutos';
                     end;
                  end;
               end;
Micheus
QUOTE(Tatiane.InterArt @ 12/04/2008 - 11:50) *
(...) usando o MinutesBetween, o que está acontecendo é que dependendo do horário q tenho ele não retorna corretamente os minutos, por exemplo:

MaskEdit5 - MaskEdit6
18:00 - 18:54
12:00 - 12:54

e outras variações com minutos diferenciados

Var Min:Integer;
Begin
Min:=MinutesBetween(StrToTime(MaskEdit5.Text),StrToTime(MaskEdit6.Text));

Min deveria ser igual a 54 correto
mas ele me mostra 53
Tatiane.InterArt, isto muito provavelmente se deve a um problema associado a números com ponto flutuante e ao fato de MinutesBetween não arredondar valores.
Veja o que consta no help:
"(...) MinutesBetween counts only entire minutes. Thus, MinutesBetween reports the difference between 9:00:00 AM and 9:00:59:999 AM as 0 because the difference is one millisecond short of an entire minute."
lembrando que esta é a apresentação em forma de horas, quando o valor em si (um double), convertido em minutos seria:
09:00:00 => 540 minutos
09:00:55:999 => 540,9999833333...
e ao observar que ele considera a diferença como 0, concluí-se que a função não faz arredondamento - usa a parte inteira.
Associado a isso, tem a questão da operação com ponto flutuante - até já comentei isto na dica "Formatando horas além das 23:59h" (no parágrafo em que cito uma correção incluída)

Uma sugestão especificamente para "substituição" da função MinutesBetween - eu não sou tão bonzinho biggrin.gif
CODE
function NewMinutesBetween(aNow, aThen :TDateTime) :Int64;
var
  MinDiff :Extended;
begin
  MinDiff := (aThen -aNow) *24 *60;
  if (MinDiff -Trunc(MinDiff)) > 0.9999 then
    MinDiff := Round(MinDiff);

  Result := Trunc(MinDiff);
end;


A título de curiosidade, se quiser testar o que tentei explicar, a função MinutesBetween deve estar definida mais ou menos assim:
CODE
function MinutesBetween(aNow, aThen :TDateTime) :Int64;
begin
  Result := Trunc((aThen -aNow) *24 *60);
end;

E um exemplinho de teste, colocando os valores em 2 labels - observe os resultados:
CODE
procedure TForm1.Button2Click(Sender: TObject);
begin
  Label1.Caption := IntToStr(MinutesBetween(StrToTime(MaskEdit1.Text),StrToTime(MaskEdit2.Text)));
  Label2.Caption := IntToStr(NewMinutesBetween(StrToTime(MaskEdit1.Text),StrToTime(MaskEdit2.Text)));
end;



QUOTE(Rento @ 13/04/2008 - 01:45) *
(...) Não me lembro como programei, da uma olhada porque funciona ^^ (...)
huh.gif ohmy.gif

Abraços
Tatiane.InterArt
Ahnnnn com esse seu exemplo:

CODE
function NewMinutesBetween(aNow, aThen :TDateTime) :Int64;
var
  MinDiff :Extended;
begin
  MinDiff := (aThen -aNow) *24 *60;
  if (MinDiff -Trunc(MinDiff)) > 0.9999 then
    MinDiff := Round(MinDiff);

  Result := Trunc(MinDiff);
end;


pude compreender melhor a questão da operação com ponto flutuante, fica bem claro e não imaginava que houvesse essa variação, fiz várias pesquisas na internet e achei alguns exemplos antes de postar mas nenhum deles mensionava essa variação, fiz o teste e funcionou, obrigado mais uma vez Micheus!
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.