Diferença entre 2 TIMESTAMPS, somente horas úteis
Preciso obter a diferença de tempo entre dois campos TIMESTAMP, só que essa diferença deve ignorar as horas que não forem de trabalho.
Ex: A primeira hora é 17:00 de hoje e a segunda é 10:00 do dia seguinte. Numa diferença normal, seriam 17 horas, mas nesse caso o período útil seria das 09:00 às 18:00, ou seja, seriam, na verdade, 2 horas. Isso tb vale para as 24h de sábados, domingos e feriados.
Alguém tem uma sugestão de como posso montar isso numa SP no Firebird 1.5?
Ex: A primeira hora é 17:00 de hoje e a segunda é 10:00 do dia seguinte. Numa diferença normal, seriam 17 horas, mas nesse caso o período útil seria das 09:00 às 18:00, ou seja, seriam, na verdade, 2 horas. Isso tb vale para as 24h de sábados, domingos e feriados.
Alguém tem uma sugestão de como posso montar isso numa SP no Firebird 1.5?
Gandalf.nho
Curtidas 0
Respostas
Edilcimar
03/01/2006
Eu acho que neste caso vc deveria trocar o campo time para datetime pois aí vc teria hoje := 2006010317:00:00 e amanhã := 2006010410:00:00, o que realmente devolveria a quantidade de horas desejadas
GOSTEI 0
Gandalf.nho
03/01/2006
Os valores já são data/hora (TIMESTAMP) e preciso da diferença desconsiderando as horas não úteis, não é simplesmente Data2 - Data1
GOSTEI 0
Edilcimar
03/01/2006
Ex: A primeira hora é 17:00 de hoje e a segunda é 10:00 do dia seguinte. Numa diferença normal, seriam 17 horas, mas nesse caso o período útil seria das 09:00 às 18:00, ou seja, seriam, na verdade, 2 horas.
Pela conta normal realmente são 17 horas usando TIMESTAMP(não tinha reparado, li time), mas de onde aparece este 09:00 as 18:00 que dá 2 horas? Se quiser considerar este período como a jornada de trabalho, então como é que ficam as outras 15 horas trabalhadas? Foram em vão?
Pois neste caso você considera das 17 as 18 (1 hora) e depois no outro dia das 9 as 10 (1 hora), agora se o problema for em digitar hora errada então não permita que a pessoa digite hora entre 18:00 e 09:00!
GOSTEI 0
Gandalf.nho
03/01/2006
Não tem nada a ver com jornada de trabalho, é para um sistema de Helpdesk e me foi exigido que o cálculo seja assim para determinar o período decorrido para atender o usuário
GOSTEI 0
Afarias
03/01/2006
bom, acho q existem alguns algorítmos possíveis... vou colocar 1 aqui (com 2 variantes, sendo 1 retornando o tempo em horas inteiras e a outra em minutos) ::
os procedimentos são ´selecionáveis´ ... mas poderiam ser ´executáveis´ -- tanto faz...
T+
set term ^; create procedure tempo_h (di timestamp, df timestamp) returns (r integer) as begin r = 0; while (di<df) do begin di = di + 0.041667; /* aprox. 1 hora */ if ((not extract(weekday from di) in (0,6)) and (cast(di as time) between ´09:00´ and ´18:00´)) then r = r+1; end suspend; end^ create procedure tempo_m (di timestamp, df timestamp) returns (r integer) as begin r = 0; while (di<df) do begin di = di + 0.000695; /* aprox. 1 min */ if ((not extract(weekday from di) in (0,6)) and (cast(di as time) between ´09:00´ and ´18:00´)) then r = r+1; end suspend; end^
os procedimentos são ´selecionáveis´ ... mas poderiam ser ´executáveis´ -- tanto faz...
T+
GOSTEI 0
Vinicius2k
03/01/2006
Eu, teria outra interpretação. Não exatamente para o caso específico de HelpDesk onde os tempos, normalmente, são curtos.
Um exemplo seria o código abaixo, mas ainda podem existir ´n´ outras variantes como, por exemplo se finais de semana são válidos ou não.
Eu utilizo algorítimos semelhantes para cálculo de tempo em produção e, no meu caso, existe ainda a possibilidade de existirem paradas de produção. Esta(s) parada(s) geram dois ou mais registros de ´inicio´ e ´final´, obrigando a efetuar a agregação.
Além disto, este código deve poder ser melhorado. :)
Considerando uma tabela:
A procedure seria:
T+
Um exemplo seria o código abaixo, mas ainda podem existir ´n´ outras variantes como, por exemplo se finais de semana são válidos ou não.
Eu utilizo algorítimos semelhantes para cálculo de tempo em produção e, no meu caso, existe ainda a possibilidade de existirem paradas de produção. Esta(s) parada(s) geram dois ou mais registros de ´inicio´ e ´final´, obrigando a efetuar a agregação.
Além disto, este código deve poder ser melhorado. :)
Considerando uma tabela:
create table horario ( inicial timestamp, final timestamp);
A procedure seria:
create procedure tempoutil returns ( inicial timestamp, final timestamp, horas_uteis double precision) as declare variable util_i time; declare variable util_f time; declare variable dias integer; begin /* período útil */ util_i = ´09:00:00´; util_f = ´18:00:00´; for select inicial, final from horario into :inicial, :final do begin /* verifica se "inicial" e "final" estão dentro do período útil */ if ((cast(inicial as time) >= cast(util_i as time)) and (cast(final as time) <= cast(util_f as time))) then begin /* verifica se "inicial" e "final" estão dentro do mesmo dia */ if (cast(inicial as date) = cast(final as date)) then begin /* se sim, horas_uteis recebe apenas "final" - "inicial" */ horas_uteis = (cast(final as time) - cast(inicial as time)) / 3600; end else begin /* se não... */ /* "horas_uteis" recebe a diferença entre o término do período útil e "inicial" */ horas_uteis = (cast(util_f as time) - cast(inicial as time)) / 3600; /* "horas_uteis" agrega a diferença entre "final" e inicio do período útil*/ horas_uteis = horas_uteis + (cast(final as time) - cast(util_i as time)) / 3600; /* verifica a diferença em dias. se maior que 1, horas_uteis agrega ainda a (qtd de dias - 1) x qtd de horas úteis em um dia */ dias = cast(final as date) - cast(inicial as date); if (dias > 1 ) then begin horas_uteis = horas_uteis + (dias - 1) * ((cast(util_f as time) - cast(util_i as time)) / 3600); end end end suspend; end end
T+
GOSTEI 0
Gandalf.nho
03/01/2006
Valeu pelas respostas, vou tentar ambas as sugestões no meu banco e ver qual que fica melhor.
GOSTEI 0
Gandalf.nho
03/01/2006
Consegui resolver o problema, fiz um código híbrido entre as sugestões de vcs e ainda modifiquei para se ajustar às necessidades do sistema, e tá funcionando beleza. Obrigada pela ajuda.
GOSTEI 0