Erro em cálculo com hora!
Preciso dividir um determinado tempo em pedaços iguais onde o cliente determina a hora inicial, a hora final e o intervalo, só que o delphi está calculando errado.
Ex: hora inicial = 08:00, hora final = 08:30, intervalo = 15 minutos
Programa:
For I := 1 to Cont + 1 do
Begin
...HoraInicial := IncMinute(HoraInicial, Intervalo); // se der um showmessage aqui, a hora está correta
...If HoraInicial = HoraFinal then
......Break
...Else If HoraInicial > HoraFinal then
......Showmessage(´mensagem´);
End;
Nesta circunstância a resposta está OK, porém se a diferença entre a hora inicial e a hora final for maior que 30 minutos, não dá certo de jeito nenhum.
Aguém sabe o porquê disto?
Ex: hora inicial = 08:00, hora final = 08:30, intervalo = 15 minutos
Programa:
For I := 1 to Cont + 1 do
Begin
...HoraInicial := IncMinute(HoraInicial, Intervalo); // se der um showmessage aqui, a hora está correta
...If HoraInicial = HoraFinal then
......Break
...Else If HoraInicial > HoraFinal then
......Showmessage(´mensagem´);
End;
Nesta circunstância a resposta está OK, porém se a diferença entre a hora inicial e a hora final for maior que 30 minutos, não dá certo de jeito nenhum.
Aguém sabe o porquê disto?
Edilcimar
Curtidas 0
Respostas
Massuda
17/12/2007
Como TDateTime é um ponto flutuante, sempre existe a possibilidade de haver imprecisões nos cálculos. Explique o que seu loop faz.
GOSTEI 0
Felipeucc
17/12/2007
Olá amigo,
Acredito que o erro esteja no For I := 1 to[color=red:4fdd7fb557] Cont + 1[/color:4fdd7fb557] do
Apesar de não ter especificado o que faz esse for, acredito que não precise do + 1 no Cont.
Verifique se é isso ou dê mais detalhes sobre o código.
Mas, dizer o que o Delphi está fazendo errado.... essa foi boa. hehehhe.
Não leve a mau, mas o Delphi fez o que você programou.
Abraços
Acredito que o erro esteja no For I := 1 to[color=red:4fdd7fb557] Cont + 1[/color:4fdd7fb557] do
Apesar de não ter especificado o que faz esse for, acredito que não precise do + 1 no Cont.
Verifique se é isso ou dê mais detalhes sobre o código.
Mas, dizer o que o Delphi está fazendo errado.... essa foi boa. hehehhe.
Não leve a mau, mas o Delphi fez o que você programou.
Abraços
GOSTEI 0
Edilcimar
17/12/2007
O loop está certo, a conta está certa, eu estou mandando o delphi fazer exatamente aquilo que está escrito e ele está fazendo conta errada.
Quanto ao Cont + 1 eu preciso dele, pois quero ver se o cliente não colocou por exemplo hora incial = 08:00, hora final = 8:50 e intervalo = 15. Se eu colocar apenas o Cont, ele vai até 8:45, mas com Cont + 1 ele vai até 09:00, passando portanto das 08:50 e mostrando para o cliente que a hora final está errada pois 50 minutos não é divisível por 15 minutos!
Coloque o meu código num form e execute para ver se dá certo!
Quanto ao Cont + 1 eu preciso dele, pois quero ver se o cliente não colocou por exemplo hora incial = 08:00, hora final = 8:50 e intervalo = 15. Se eu colocar apenas o Cont, ele vai até 8:45, mas com Cont + 1 ele vai até 09:00, passando portanto das 08:50 e mostrando para o cliente que a hora final está errada pois 50 minutos não é divisível por 15 minutos!
Coloque o meu código num form e execute para ver se dá certo!
GOSTEI 0
Massuda
17/12/2007
Mas de onde vem o Cont? Pelo que entendi, a pessoa informa HoraInicial, HoraFinal e Intervalo, é isso?
GOSTEI 0
Edilcimar
17/12/2007
Este Cont é uma conta que faço para ver quantos consultas caberiam entre a hora inicial e a hora final.
Cont := Trunc(Hora * 24 * 60 / Intervalo); no exemplo de 1 hora e intervalo de 15 minutos isto retorna 4
Cont := Trunc(Hora * 24 * 60 / Intervalo); no exemplo de 1 hora e intervalo de 15 minutos isto retorna 4
GOSTEI 0
Felipeucc
17/12/2007
Que valor é atribuido a hora ?
não vi como o resultado disso pode ser 4.
não vi como o resultado disso pode ser 4.
GOSTEI 0
Massuda
17/12/2007
O que afinal está calculando errado?
GOSTEI 0
Edilcimar
17/12/2007
Desculpe esqueci de escrever
Hora := HoraFinal - HoraInicial
Hora := HoraFinal - HoraInicial
GOSTEI 0
Felipeucc
17/12/2007
Amigo,
Aconselho que dê uma estudada na Library DateUtils (pode ser acessada pelo help do Delphi). Lá você encontrará várias funções que podem dar uma simplificada no seu código.
Exemplo: Substitua o código que atribui valor a sua variavel cont por
MinutesBetween(DateTimePicker2.DateTime, DateTimePicker1.DateTime);
Faça uma verificação de Cont div Intervalo <> 0 then
mensagem que intervalo deve ser divisivel pelo periodo... (algo do tipo)
Aconselho que dê uma estudada na Library DateUtils (pode ser acessada pelo help do Delphi). Lá você encontrará várias funções que podem dar uma simplificada no seu código.
Exemplo: Substitua o código que atribui valor a sua variavel cont por
MinutesBetween(DateTimePicker2.DateTime, DateTimePicker1.DateTime);
Faça uma verificação de Cont div Intervalo <> 0 then
mensagem que intervalo deve ser divisivel pelo periodo... (algo do tipo)
GOSTEI 0
Edilcimar
17/12/2007
Incialmente eu olhei as funções de hora do help do delphi, e não achei algo a contento. O MinutesBeteween() vai me informar a quantidade de minutos entre uma hora inicial e outra final, o que quero é saber quantos ´pedaços´ de intervalos cabem entre a hora inicial e final, para poder calcular se a hora final informada pelo cliente está correta, conforme informei anteriormente, a estrutura que eu montei não tem erro de lógica, o problema está em:
Hora Inicial = 08:00 - Intervalo = 15 minutos
Hora Final = 08:15 -> ok funciona direito
Hora Final = 08:30 -> ok funciona direito
Hora Final = 08:45 -> erro, a conta não bate mais daqui para frente, qualquer que seja o múltiplo de 15 minutos.
O que quero saber é o porquê o delphi me dá este erro?
Se eu der um showmessage(timetostr(hora)), após cada soma, ela está correta, sem nenhum defeito, porém quando faço comparação com a hora final, apesar do showmessage() mostrar a hora correta, internamente o delphi diz que está errado!
Hora Inicial = 08:00 - Intervalo = 15 minutos
Hora Final = 08:15 -> ok funciona direito
Hora Final = 08:30 -> ok funciona direito
Hora Final = 08:45 -> erro, a conta não bate mais daqui para frente, qualquer que seja o múltiplo de 15 minutos.
O que quero saber é o porquê o delphi me dá este erro?
Se eu der um showmessage(timetostr(hora)), após cada soma, ela está correta, sem nenhum defeito, porém quando faço comparação com a hora final, apesar do showmessage() mostrar a hora correta, internamente o delphi diz que está errado!
GOSTEI 0
Felipeucc
17/12/2007
O delphi interpreta data e hora com número float onde o valor antes da virgula representa a data e depois da virgula representa a hora. (use o debug) onde o dia 0 equivale a 30/12/1899. E não recomendo o uso de Trunc para cálculo de datas e horas.
GOSTEI 0
Edilcimar
17/12/2007
Se você reparar, vai ver que uso Trunc não para fazer conta com horas, mas para calcular o Cont (quantidade de intervalos no período), portanto aí não importa se uso trunc ou div, eu pego inicialmente a hora inicial e final de 2 maskedit, já dei showmessage() em cada linha, tudo que é mostrado na tela está correto, pode ser que o erro seja de arredondamento, mas se o erro existe, por que ele não aparece no showmessage()? Outra coisa, se existe erro de arredondamento o que devo usar? DecodeDate e depois EncodeDate para fazer as comparações?
E se fizer isto ainda assim não vai continuar a haver erro de arredondamento?
E se fizer isto ainda assim não vai continuar a haver erro de arredondamento?
GOSTEI 0
Edilcimar
17/12/2007
segue o código completo com comentário
procedure TForm19.MaskEdit8Exit(Sender: TObject);
Var I, Consultas : Word;
begin
...HoraInicial := StrToTime(MaskEdit1.Text);
...MaskEdit8.Color := clWhite;
...Try
......If Trim(MaskEdit8.Text) <> ´:´ then
.........HoraFinal := StrToTime(MaskEdit8.Text);
...Except
......ShowMessage(´Esta não é uma hora válida´);
......MaskEdit8.SetFocus;
...End;
...Hora := HoraFinal - HoraInicial;
...If Hora <= 0 then
...Begin
......ShowMessage(´Horário final tem que ser maior que horário inicial´);
......MaskEdit8.SetFocus;
...End;
...Consultas := Trunc(Hora * 24 * 60 / Intervalo);
...For I := 1 to Consultas + 1 do
...Begin
......HoraInicial := IncMinute(HoraInicial, Intervalo);
......If (HoraInicial = HoraFinal) then
.........Break
......Else If (HoraInicial > HoraFinal) then
......Begin
.........ShowMessage(FormatDateTime(´hh:mm:ss:zzz´, horainicial) + ´ ´ + FormatDateTime(´hh:mm:ss:zzzz´, horafinal)); //////// se a diferença for de 45 minutos ou mais aqui mostra a hora com até os milisegundos iguais, isto foi colocado apenas para efetuar comparação de tempo
.........ShowMessage(´A divisão de tempo entre hora inicial´ + #13 + 10 + ´e hora final, em função do intervalo,´ + 13 + 10 + ´está errada, refaça as contas´);
.........MaskEdit8.SetFocus;
......End;
...End;
end;
O intervalo de tempo usado foi 15 minutos, hora inicial 08:00 (mas pode ser qualquer uma), se hora final for múltiplo de 15 mas maior que 30 minutos, dá erro
???????????????????????????????????
procedure TForm19.MaskEdit8Exit(Sender: TObject);
Var I, Consultas : Word;
begin
...HoraInicial := StrToTime(MaskEdit1.Text);
...MaskEdit8.Color := clWhite;
...Try
......If Trim(MaskEdit8.Text) <> ´:´ then
.........HoraFinal := StrToTime(MaskEdit8.Text);
...Except
......ShowMessage(´Esta não é uma hora válida´);
......MaskEdit8.SetFocus;
...End;
...Hora := HoraFinal - HoraInicial;
...If Hora <= 0 then
...Begin
......ShowMessage(´Horário final tem que ser maior que horário inicial´);
......MaskEdit8.SetFocus;
...End;
...Consultas := Trunc(Hora * 24 * 60 / Intervalo);
...For I := 1 to Consultas + 1 do
...Begin
......HoraInicial := IncMinute(HoraInicial, Intervalo);
......If (HoraInicial = HoraFinal) then
.........Break
......Else If (HoraInicial > HoraFinal) then
......Begin
.........ShowMessage(FormatDateTime(´hh:mm:ss:zzz´, horainicial) + ´ ´ + FormatDateTime(´hh:mm:ss:zzzz´, horafinal)); //////// se a diferença for de 45 minutos ou mais aqui mostra a hora com até os milisegundos iguais, isto foi colocado apenas para efetuar comparação de tempo
.........ShowMessage(´A divisão de tempo entre hora inicial´ + #13 + 10 + ´e hora final, em função do intervalo,´ + 13 + 10 + ´está errada, refaça as contas´);
.........MaskEdit8.SetFocus;
......End;
...End;
end;
O intervalo de tempo usado foi 15 minutos, hora inicial 08:00 (mas pode ser qualquer uma), se hora final for múltiplo de 15 mas maior que 30 minutos, dá erro
???????????????????????????????????
GOSTEI 0
Fknyght
17/12/2007
Cara, tente fazer o seguinte
coloque dois maskedits no form, um edit e um memo e tente o codigo abaixo
Lembre-se que se você tiver que fazer calculos com data e hora você tem que fazer no formato de data e hora, nao pode colocar valores inteiros ok
coloque dois maskedits no form, um edit e um memo e tente o codigo abaixo
procedure TForm1.Button1Click(Sender: TObject); Var HI , HF : TTime; Intervalo : Integer; begin Memo1.Lines.Clear; try HI := StrToTime( MaskEdit1.Text ); except HI := 0; end; try HF := StrToTime( MaskEdit2.Text ); except HF := 0; end; Intervalo := StrToIntDef(Edit1.Text,15); if ( ( HI <> 0 ) and ( HF <> 0 ) ) then Begin While HI <= HF do Begin Memo1.Lines.Add ( TimeToStr( HI ) ); HI := HI + StrToTime(´00:´ + IntToStr(Intervalo) + ´:00´ ); End; End else ShowMessage(´Hora inválidas´); end;
Lembre-se que se você tiver que fazer calculos com data e hora você tem que fazer no formato de data e hora, nao pode colocar valores inteiros ok
GOSTEI 0
Edilcimar
17/12/2007
fknyght, valeu, este teu macete funcionou
GOSTEI 0
Edilcimar
17/12/2007
Houve um problema aqui
While HI <= HF do -> você não compara se HI = HF, eu preciso que existe esta possibilidade para avisar, e no teu caso alguma hora HI vai ser maior que HF, portanto não funcionou como pensei que funcionaria, está acontecendo o mesmo que acontecia anteriormente
While HI <= HF do -> você não compara se HI = HF, eu preciso que existe esta possibilidade para avisar, e no teu caso alguma hora HI vai ser maior que HF, portanto não funcionou como pensei que funcionaria, está acontecendo o mesmo que acontecia anteriormente
GOSTEI 0