Ir para conteúdo
Fórum Script Brasil
  • 0

(Resolvido) intervalo de horas - calcular minutos - está com prob


Tatiane.InterArt

Pergunta

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?

Link para o comentário
Compartilhar em outros sites

4 respostass a esta questão

Posts Recomendados

  • 0

Eu vendo controle de ponto, mas como sou bonzinho vou postar:

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 ^^
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;

Editado por Rento
Link para o comentário
Compartilhar em outros sites

  • 0
(...) 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 :D

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:
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:
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;

(...) Não me lembro como programei, da uma olhada porque funciona ^^ (...)
:huh: :o

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Ahnnnn com esse seu exemplo:

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!

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152k
    • Posts
      651,8k
×
×
  • Criar Novo...