Procedure - Retorna tempo (dias/horas/minutos/segundos) entre datas (dias uteis)
SQL:
CREATE OR ALTER PROCEDURE RETORNA_TEMPO_DIAS_UTEIS (DATA_INICIO TIMESTAMP, DATA_FIM TIMESTAMP, HR_INICIO_EXPEDIENTE VARCHAR(8), HR_FIM_EXPEDIENTE VARCHAR(8))
RETURNS (
DIAS INTEGER,
HORAS INTEGER,
MINUTOS NUMERIC(15,2),
SEGUNDOS NUMERIC(15,2)
)
AS
declare variable DIFERENCA integer;
declare variable I integer;
declare variable dif integer;
declare variable temp_dt_ini TIMESTAMP;
declare variable temp_dt_fim TIMESTAMP;
begin
i = 0;
DIFERENCA = 0;
DIAS = 0;
HORAS = 0;
MINUTOS = 0;
SEGUNDOS = 0;
dif = 0;
if (:DATA_INICIO is not null and :DATA_FIM is not null and :DATA_INICIO <= :DATA_FIM) THEN
BEGIN
dif = datediff(SECOND from :DATA_INICIO to :DATA_FIM);
if (Extract(Weekday from :DATA_INICIO) IN (1,2,3,4,5) and Extract(Weekday from :DATA_FIM) IN (1,2,3,4,5) AND dif <= 86400) THEN
begin
SEGUNDOS = :SEGUNDOS + :dif;
MINUTOS = :SEGUNDOS / 60;
HORAS = cast(:SEGUNDOS / 3600 as integer);
DIAS = cast(:SEGUNDOS / 86400 as integer);
suspend;
END
ELSE
BEGIN
DIFERENCA = cast(:DATA_FIM as date) - cast(:DATA_INICIO as date);
if (:DIFERENCA > 0) then
BEGIN
WHILE (i <= :DIFERENCA) DO
BEGIN
if (i = 0) then
begin
temp_dt_ini = :DATA_INICIO;
end
ELSE
begin
temp_dt_ini = cast(cast(:DATA_INICIO + i as date) || ' ' || :hr_inicio_expediente as TIMESTAMP);
end
if (Extract(Weekday from :temp_dt_ini) not in (0,6)) THEN
begin
if (cast(cast(:temp_dt_ini as date) || ' ' || :hr_fim_expediente as TIMESTAMP) > :DATA_FIM) then
temp_dt_fim = :DATA_FIM;
else
temp_dt_fim = cast(cast(:temp_dt_ini as date) || ' ' || :hr_fim_expediente as TIMESTAMP);
if (Extract(Weekday from :temp_dt_fim) not in (0,6)) then
begin
dif = datediff(SECOND from :temp_dt_ini to :temp_dt_fim);
:SEGUNDOS = :SEGUNDOS + :dif;
END
END
i = i +1;
END
MINUTOS = :SEGUNDOS / 60;
HORAS = cast(:SEGUNDOS / 3600 as integer);
DIAS = cast(:SEGUNDOS / 86400 as integer);
Suspend;
END
end
END
ELSE
BEGIN
SEGUNDOS = :SEGUNDOS;
MINUTOS = :SEGUNDOS;
HORAS = :SEGUNDOS;
DIAS = :SEGUNDOS;
suspend;
END
END;
Parâmetros da procedure:
Entrada:
- DATA_INICIO (timestamp) = Data inicial para cálculo do tempo. Exemplo: 2019-08-13 18:04:20
- DATA_FIM (timestamp) = Data final para cálculo do tempo. Exemplo: 2019-08-14 23:04:20
- HR_INICIO_EXPEDIENTE (varchar(5)) = Horário de início do expediente em formato texto. Exemplo: '08:00'
- HR_FIM_EXPEDIENTE (varchar(5)) = Horário de fim do expediente em formato texto. Exemplo: '18:30'
***OBSERVAÇÕES: Lembrar de passar os campos esse HR_INICIO_EXPEDIENTE e HR_FIM_EXPEDIENTE campo entre aspas simples. Caso queria calcular as horas totais do dia, sem considerar o expediente, bastas digitar passar '00:00' e '23:59' nos campos HR_INICIO_EXPEDIENTE e HR_FIM_EXPEDIENTE .
Saída
- DIAS (integer)= Tempo em dias do período informado entre DATA_INICIO e DATA_FIM.
- HORAS (integer) = Tempo em horas do período informado entre DATA_INICIO e DATA_FIM.
- MINUTOS (numeric) = Tempo em minutos do período informado entre DATA_INICIO e DATA_FIM.
- SEGUNDOS (numeric) = Tempo em segundos do período informado entre DATA_INICIO e DATA_FIM.
***OBSERVAÇÕES: Os campos de saída DIAS e HORAS são arredondados (inteiros) para facilitar o uso em Painéis, relatórios, cubos, entre outros. Caso queira um valor em formato numérico. Mas usar o campo MINUTOS ou SEGUNDOS convertendo para horas e ou dias.
Chamada da procedure:
SELECT dias,
horas,
minutos,
segundos
FROM RETORNA_TEMPO_DIAS_UTEIS ('2019-08-09 08:21:16', '2019-08-14 13:21:16','00:00:00','23:59:59')
Retorno:
DIAS|HORAS|MINUTOS|SEGUNDOS | ----|-----|-------|---------| 3| 77|4619.95|277197.00|
Explicação do retorno:
O tempo entre 09/08/2019 08:21:16 até 14/08/2019 13:21:16 é de 277.197 de segundos que é igual a 4619,95 de minutos que é igual a 77 de horas que é igual a 3 dias.
Detalhamento do cálculo:
- 09/08/2019 08:21:16 até 09/08/2019 23:59:59 = 56.323 segundos
- 10/08/2019 00:00:00 até 10/08/2019 23:59:59 = 0 segundos (não tem calculo pois é sábado)
- 11/08/2019 00:00:00 até 11/08/2019 23:59:59 = 0 segundos (não tem calculo pois é domingo)
- 12/08/2019 00:00:00 até 12/08/2019 23:59:59 = 86.399 segundos
- 13/08/2019 00:00:00 até 13/08/2019 23:59:59 = 86.399? segundos
- 14/08/2019 00:00:00 até 14/08/2019 13:21:16 = 48.076? segundos
- Totalizando 277.197 segundos