Página 1 de 2

Somar Hora

Enviado: 15 Jul 2008 22:30
por rubens
Olá pessoal...

Pesquisei no forum e nao encontrei... preciso somar horas/minutos, achei no fórun calculos com horas mas nao encontrei como somar...

Existe alguma função para isso ou tenho que criar uma?

Não preciso incrementar muito nao.. e abri um tópico anterior onde um usuario do forum ensinou subtrair e achar o tempo de uma hora para outra.. agora preciso juntar isso e saber que tempo deu...

por exemplo:
preciso somar os sequintes valores:
00:35
01:40
06:31
00:20
= Total

Vlw..
Rubens

Enviado: 15 Jul 2008 23:20
por Maligno
Pra fazer isso eu converteria tudo pra minutos, somaria e depois converteria de volta para o formato original.

Suponho que o formato seja o que você mostrou: "hh:mm" . Neste caso, separe as strings que representam os minutos e converta-as pra número, somando-as. Em seguida, converta as quantidades de horas pra número, somando-as e já multiplicando-as por 60. Some os dois resultados. Você tem o total de minutos. Aí é só dividir por 60. A parte inteira é a quantidade de horas e o resto da divisão o número de minutos extras.

Mais ou menos o seguinte:

Código: Selecionar todos

function SomaHora(cTime1,cTime2)
local nSub1 :=  Val(Right(cTime1,2)) + Val(Right(cTime2,2))
local nSub2 := (Val( Left(cTime1,2)) + Val( Left(cTime1,2))) * 60
local nMin  := nSub1 + nSub2
return StrZero(Int(nMin/60),2) + ":" + StrZero(nMin%60)
Não testei, mas acho que pode funcionar.

Somar Horas

Enviado: 16 Jul 2008 08:47
por Pablo César
O Maligno escreveu:Não testei, mas acho que pode funcionar.
Eu SIM testei o seu exemplo e não achei correto o resultado, veja só:

TESTE 01:05 02:10 e o resultado deu ==> 02:0000000015.00

De todas formas não tem melhor que transformar em segundos e depois em horas. Eu acostumo usar as funções TIMETOSEC e SECTOTIME da CT.LIB e funciona direitinho sem muito esforço. Outro detalhe, eu colocaria todas as horas a serem somadas num vetor, fica mais fácil de processar. Veja como eu fiz:

Código: Selecionar todos

aTime:={"00:35","01:40","06:31","00:20"}
nSec:=0
FOR i=1 TO LEN(aTime)
    nSec:=nSec+TIMETOSEC(aTime[i])
NEXT
? SECTOTIME(nSec)
Veja se é isso mesmo que você precisa Rubens.

Enviado: 16 Jul 2008 09:07
por Maligno
Como disse antes, não testei. Mas agora corrigi e testei. Funciona.

Código: Selecionar todos

function SomaHora(cTime1,cTime2)
local nSub1 := Val(Right(cTime1,2)) + (Val(Left(cTime1,2))) * 60
local nSub2 := Val(Right(cTime2,2)) + (Val(Left(cTime2,2))) * 60
local nMin  := nSub1 + nSub2
return StrZero(Int(nMin/60),2) + ":" + StrZero(nMin%60,2)
Só faço uma ressalva: no caso da soma de horas ultrapassar 99, será preciso adaptar a função na última linha.

Então fica a opção para o colega, caso ele não queira utilizar a CATools. Ou no caso dele vir a precisar incluir os segundos no cálculo.

Re: Somar Hora

Enviado: 16 Jul 2008 09:10
por gvc
[Maligno]
Encontrei o problema da sua função:

Código: Selecionar todos

cls

? somahora('01:05', '02:10')
 
return
 
function somahora(ctime1,ctime2)
local nsub1 :=  val(right(ctime1, 2)) + val(right(ctime2, 2)) // Estava usando ctime1 nas 2 partes
local nsub2 := (val( left(ctime1, 2)) + val( left(ctime2, 2))) * 60
local nmin  := nsub1 + nsub2

return strzero(int(nmin / 60), 2) + ":" + strzero(nmin % 60, 2) // Faltava o 2º ", 2"
[Pablo]
Tudo bem, mas nem todos tem a CA-Tools disponível.

Enviado: 16 Jul 2008 09:11
por Maligno
Já foi corrigido. Obrigado. Inclusive, se observar, mudei um pouco o código justamente para facilitar uma possível adaptação para o uso de matriz com os valores.

Somar Horas

Enviado: 16 Jul 2008 11:22
por Pablo César
O gvc escreveu:[Pablo]
Tudo bem, mas nem todos tem a CA-Tools disponível.
Daí ?. Ainda é uma solução. Também acho que todo bom clippeiro conhece o CA-Tools, não é ?. E ja que contucaram-me com vara curta... decidí eu mesmo fazer as funções:

Código: Selecionar todos

/* Compilar com a CT.LIB para comparar as funções TIMETOSEC e SECTOTIME */

? TIME2SEC( "09:06:00" ) ; ?? TIMETOSEC( "09:06:00" )   // Ok
? SEC2TIME( 32760 )  ; ?? "     "+SECTOTIME( 32760 )    // Ok
? SEC2TIME( 332760 ) ; ?? "     "+SECTOTIME( 332760 )   // por que dah resultado diferente ?

Function SEC2TIME(segundos)
Local hor,min,seg
hor := int(segundos / (60 * 60))
min := int( ((segundos - (hor * 60 * 60)) / 60) )
seg := int((segundos - (hor * 60 * 60) - (min * 60)) )
RETURN STRZERO(hor,if(hor>99,len(alltrim(str(hor))),2))+":"+STRZERO(min,2)+":"+STRZERO(seg,2)

Function TIME2SEC(cHor)
Local hor, min, seg
hor := VAL( SUBSTR( cHor,1, AT(":",cHor)-1 ) )
cHor:= SUBSTR( cHor, AT(":",cHor)+1 )
IF AT(":",cHor)=0
   min := VAL( cHor )
   seg := 0
ELSE
   min := VAL( SUBSTR( cHor,1, AT(":",cHor)-1 ) )
   seg := VAL( SUBSTR( cHor, AT(":",cHor)+1 ) )
ENDIF
Return ( (hor * (60*60)) + (min * 60) + seg )
Coloquei essas seis chamadas para comparar. E o que não entendí por quê há diferenças nas duas ultimas ?.

A minha intenção além de ficar livre do uso da CT.LIB (por mero capricho) era também apresentar uma hora com o formato maior que hh:mm:ss podendo ser hhh:mm:ss, hhhh:mm:ss e assim sucessivamente. Acho que esta deve ser a melhor opção para o somatório de horas. Que pelo que parece as funções da CT.LIB limitam-se ao tamanho hh de apenas UM dia.

Enviado: 16 Jul 2008 11:35
por Maligno
Existem diversas formas de tratar a questão da soma de horas. Fica até bem trabalhoso tratar todas as possibilidades. Mas tenho o palpite de que o OP deseja somar horas extras ou algo do tipo. Acho que pra isso ele já deve estar bem servido.

Somar Horas

Enviado: 16 Jul 2008 11:42
por Pablo César
Não sabemos se o colega precisa obter as somas de horas que até poderiam exceder ao valor equivalente de UM dia inteiro (86400 segundos). Mas a função que eu fiz funciona para todos os casos.

A título de aprendizado: (respondendo a minha própria pergunta da mensagem em cor azul)

A diferença de resultado que dá SEC2TIME(332760) e SECTOTIME(332760) é mesmo porque ultrapassou o valor/hora de UM dia (23:59:59). Essa diferença cujos resultados são 92:26:00 e 20:26:00 respectivamente, é justamente o valor equivalente a três dias ( 24 * 3 = 72 ).

Por esta razão, só tome cuidado Rubens, na utilização do SECTOTIME() da CT.LIB pois esta devolverá os valores ao máximo de um dia. E você terá que guardar esta informação excedente em outro lugar. Em sintese, a função que apresentei, acredito que seja a mais indicada para os caso de somatoria de horas, independentemente se excedem ou não as 24 horas do dia.

Enviado: 16 Jul 2008 12:59
por Maligno
Nos casos de somas de horas extras, a soma dos tempos não pode ser convertida para o equivalente a dias. Se for esta a tarefa que o colega deve realizar e se a sua função converte para dias o que passa de 24 horas (não testei), ela não servirá.

Por isso que eu disse que há diversas formas de efetuar cálculos com horas. Depende da necessidade que se apresenta. Como o OP não especificou,...

Re: Somar Hora

Enviado: 16 Jul 2008 13:05
por rubens
Pessoal...

fiz vários testes e o que mais se ajustou ao que preciso foi o modelo que o Maligno apresentou.. no inicio realmente estava com um erro, daí tentei "ajusta-la" mas conforme foi corrigida.. ficou excelente...
No meu caso é para ser usado num relatorio de coletivo aqui da cidade... e o cliente precisa que conforme ele lanca as minutas já calcule tambem quantas horas o motorista trabalhou... entao subtraio a qtde de horas/minuto por lancamento e somo no final tenho tb a qtde horas que o motorista trabalhou, como e feito um acerto semanal dificilmente vai passar e 99 horas e se passar aí é só ajustar a função do maligno..

Vlw... obrigado a todos como sempre...

Rubens

Enviado: 16 Jul 2008 14:29
por Maligno
Caso precise, será necessário trocar apenas a última linha. Algo do tipo:

Código: Selecionar todos

return LTrim(Str(Int(nMin/60),2)) + ":" + StrZero(nMin%60,2)
Aí você obteria resultados como: "5:12", "25:34" ou "101:48". Se tiver que normalizar isso (tipo: "005:12" (com zeros ou espaços)), seria melhor após o retorno desta função.

Somar Hora

Enviado: 16 Jul 2008 15:27
por Pablo César
Rubens, você deve ter testado o meu exemplo anterior, pois eu tinha notado que estava com um problema mas logo corrigí. De então o meu segundo exemplo não precisa adaptar NADA, seja o resultado com mais de 24 horas, mais que 99 enfim, repito não precisa adaptar nada e está correto.
Rubens escreveu:conforme ele lanca as minutas já calcule tambem quantas horas o motorista trabalhou... entao subtraio a qtde de horas/minuto por lancamento e somo no final tenho tb a qtde horas que o motorista trabalhou
Bastaria então fazer assim utilizando as funções TIME2SEC/SEC2TIME que criei:

Código: Selecionar todos

SomaH:="00:35"
SomaH:=SEC2TIME( TIME2SEC(SomaH)+TIME2SEC("01:40") )
..//.. com outro registro
SomaH:=SEC2TIME( TIME2SEC(SomaH)+TIME2SEC("06:31") )
..//.. com outro registro
SomaH:=SEC2TIME( TIME2SEC(SomaH)+TIME2SEC("00:20") )

? SomaH // Verá o resultado em formato hh:mm ou hhh:mm (dependerá da quantidade de horas somadas)

Function SEC2TIME(segundos)
Local hor,min,seg
hor := int(segundos / (60 * 60))
min := int( ((segundos - (hor * 60 * 60)) / 60) )
seg := int((segundos - (hor * 60 * 60) - (min * 60)) )
RETURN STRZERO(hor,if(hor>99,len(alltrim(str(hor))),2))+":"+STRZERO(min,2)+":"+STRZERO(seg,2)

Function TIME2SEC(cHor)
Local hor, min, seg
hor := VAL( SUBSTR( cHor,1, AT(":",cHor)-1 ) )
cHor:= SUBSTR( cHor, AT(":",cHor)+1 )
IF AT(":",cHor)=0
   min := VAL( cHor )
   seg := 0
ELSE
   min := VAL( SUBSTR( cHor,1, AT(":",cHor)-1 ) )
   seg := VAL( SUBSTR( cHor, AT(":",cHor)+1 ) )
ENDIF
Return ( (hor * (60*60)) + (min * 60) + seg )
O Maligno escreveu:Nos casos de somas de horas extras, a soma dos tempos não pode ser convertida para o equivalente a dias. Se for esta a tarefa que o colega deve realizar e se a sua função converte para dias o que passa de 24 horas (não testei)...
Não, meu segundo exemplo, não separa dias coisa alguma. Eu apenas mencionei isso porque se for usar o meu primeiro exemplo (que usa o SECTOTIME/TIMETOSEC), estes só limitam-se a 86400 segundos (que seria um dia inteiro). E pelo visto você nem prestou atenção no meu ultimo exemplo, aliás você está prestando pouca atenção ultimamente nas mensagens.

Eu sempre testo os exemplos que posto e também testo os exemplos dos outros. Não fico falando uma coisa que não é... ao menos que eu me engane. Tal é assim, que seu código-exemplo, fui eu que denunciei erro na execução e você logo consertou. Mas enfim, não estou aqui para competir e sim esclarecer. O importante que ajudamos ao colega e foi bom porque estimulou-me a criação dessa funções que para meu ver estão melhores que a CT.LIB e a do Maligno também.

Re: Somar Hora

Enviado: 16 Jul 2008 16:22
por gvc
[Maligno]
Eu testei e corrigi o seu código original. Vc postou a resposta exatamente no momento que eu editei e re-postei.

[Pablo]
Desculpe se vc entendeu que eu estava provocando-o. Tenho por norma não fazer isso. Não leva a nada provocações.
Eu só estava querendo deixar claro que estamos habituados a usar ferramentas que outro usuário pode não ter. Então uma solução simples, usando uma determinada ferramenta, não vai ajudar um colega com dúvidas/problemas.
Se vc apresenta outra solução, ótimo. Quanto mais opções forem oferecidas, melhor para toda a comunidade Clipper/xHarbour.
Eu tento ler todos os posts com a seguinte mensagem na cabeça: "Em que eu pederei ajudar. Se não puder, melhor só observar e se puder aprender algo, melhor para mim."
Qdo o post sai do assunto (eu já estou saindo) eu mudo a frase: "Não acrescenta nada. Pulo!"
Espero que vc entenda, não quero provocar ninguem. Mesmo as brincadeiras são estremamente restritas. Vc mesmo já observou que eu sou assim nas minhas respostas.

Senhores. acho que o que importa é que o Rubens já conseguiu resolver o seu problema.
Um abraço e boa sorte para todos.

Somar Hora

Enviado: 16 Jul 2008 16:38
por Pablo César
Ok, GVC. Na hora pensei como crítica mas foi até bom, como você disse o importante que acrescentou mais idéias, ajudou também a detectar que as funções as que eu me referia da CT.LIB são limitadas, proporcionando um resultado não totalmente correto. Veja ao que me refiro:

? SECTOTIME(332760) // observe qual será o resultado: "20:26:00" ???

Agora utilizando a função que eu fiz:
? SEC2TIME( 332760 ) // e obterá este outro resulotado: "92:26:00"

Foi isso que eu quis evidenciar e que na tentativa de explicar fui mal comprendido, ou aliás ignorado o contexto das minhas mensagens o que provocou um certo desconforto nas respostas. Pelo disse e não disse...

Mas como todos ja concordamos, o importante que o Rubens achou uma solução e que também houve possibilidades de melhorar as opções que tínhamos. Enfatizo este ultimo, porque eu era convicto que as funções TIMETOSEC e SECTOTIME davam valores precisos e não delimitados aos 86400 segundos.