Tatiane.InterArt Postado Abril 12, 2008 Denunciar Share Postado Abril 12, 2008 Tenho uma telinha de cartão de ponto, onde para cada intervalo faço cálculo de atrazo e extra usando oMinutesBetween, o que está acontecendo é que dependendo do horário q tenho ele não retorna corretamente os minutos, por exemplo:MaskEdit5 - MaskEdit618:00 - 18:5412:00 - 12:54e outras variações com minutos diferenciadosVar Min:Integer;BeginMin:=MinutesBetween(StrToTime(MaskEdit5.Text),StrToTime(MaskEdit6.Text));Min deveria ser igual a 54 corretomas ele me mostra 53o que acontece é q essa diferença de 1min já faz uma grande diferença no cálculo de hora extra, como posso resolver isso? Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Jhonas Postado Abril 12, 2008 Denunciar Share Postado Abril 12, 2008 tenta desta maneira:Var Min:Integer;BeginMin:=MinutesBetween(StrToTime(MaskEdit5.Text),StrToTime(MaskEdit6.Text));if pos(':00',MaskEdit5.Text) > 0 then Min := Min + 1;abraço Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Rento Postado Abril 13, 2008 Denunciar Share Postado Abril 13, 2008 (editado) 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 Abril 13, 2008 por Rento Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Micheus Postado Abril 13, 2008 Denunciar Share Postado Abril 13, 2008 (...) usando o MinutesBetween, o que está acontecendo é que dependendo do horário q tenho ele não retorna corretamente os minutos, por exemplo:MaskEdit5 - MaskEdit618:00 - 18:5412:00 - 12:54e outras variações com minutos diferenciadosVar Min:Integer;Begin Min:=MinutesBetween(StrToTime(MaskEdit5.Text),StrToTime(MaskEdit6.Text));Min deveria ser igual a 54 corretomas ele me mostra 53Tatiane.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 minutos09: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 :Dfunction 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: :oAbraços Citar Link para o comentário Compartilhar em outros sites More sharing options...
0 Tatiane.InterArt Postado Abril 14, 2008 Autor Denunciar Share Postado Abril 14, 2008 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! Citar Link para o comentário Compartilhar em outros sites More sharing options...
Pergunta
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?
Link para o comentário
Compartilhar em outros sites
4 respostass a esta questão
Posts Recomendados
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.