GARANTIR DESCONTO

Fórum Diferença entre 2 TIMESTAMPS, somente horas úteis #54536

03/01/2006

0

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?


Gandalf.nho

Gandalf.nho

Responder

Posts

03/01/2006

Edilcimar

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


Responder

Gostei + 0

03/01/2006

Gandalf.nho

Os valores já são data/hora (TIMESTAMP) e preciso da diferença desconsiderando as horas não úteis, não é simplesmente Data2 - Data1


Responder

Gostei + 0

03/01/2006

Edilcimar

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!


Responder

Gostei + 0

03/01/2006

Gandalf.nho

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


Responder

Gostei + 0

03/01/2006

Afarias

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

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+


Responder

Gostei + 0

03/01/2006

Vinicius2k

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


Responder

Gostei + 0

04/01/2006

Gandalf.nho

Valeu pelas respostas, vou tentar ambas as sugestões no meu banco e ver qual que fica melhor.


Responder

Gostei + 0

04/01/2006

Gandalf.nho

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.


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar