Buenas a todos,
he creado una función que cuenta las horas laborales entre dos fechas, descontando los días del fin de semana y los días festivos.
Para ello, hay que indicarle la fecha y hora de inicio y de fin, las horas de comienzo y fin del horario, y hay que tener en una tabla los festivos (festivos es el nombre de la tabla), para que pueda descontar esos días.
Es útil para por ejemplo medir las horas de cualquier servicio.
Espero que sea útil. Acepto sugerencias para su mejora.
Un saludo
Código SQL
[-]SET TERM ^ ;
CREATE OR ALTER PROCEDURE TIEMPOENTREFECHAS (
f_inicio timestamp,
f_fin timestamp,
horainiciohorario time,
horafinhorario time)
returns (
tiempo float)
as
declare variable newf_inicio timestamp;
declare variable newf_fin timestamp;
declare variable sabadosydomingos integer;
declare variable festivos integer;
declare variable winicio timestamp;
declare variable wfin timestamp;
declare variable sabydom integer;
declare variable tiempow float;
declare variable horashorario float;
declare variable tiempodia1 float;
declare variable tiempodia2 float;
declare variable tiempoantesfestivos float;
declare variable tiempoendiasantesfestivos float;
begin
NEWF_INICIO= F_INICIO;
NEWF_FIN= F_FIN;
if (CAST(newf_inicio AS TIME) > horafinhorario ) then
NEWF_INICIO= CAST(NEWF_INICIO+1 AS DATE) + HORAINICIOHORARIO;
IF (CAST(NEWF_INICIO AS TIME) < horaINICIOhorario ) then
NEWF_INICIO= CAST(NEWF_INICIO AS DATE) + HORAINICIOHORARIO;
if (EXTRACT(WEEKDAY FROM NEWF_INICIO) = 6) then
NEWF_INICIO= CAST(NEWF_INICIO+2 AS DATE)+ HORAINICIOHORARIO;
if (EXTRACT(WEEKDAY FROM NEWF_INICIO) = 0) then
NEWF_INICIO= CAST(NEWF_INICIO+1 AS DATE)+ HORAINICIOHORARIO;
if (CAST(NEWF_FIN AS TIME)> horafinhorario ) then
NEWF_FIN= CAST(NEWF_FIN AS DATE)+HORAFINHORARIO;
if ( CAST(NEWF_FIN AS TIME) < HORAINICIOhorario ) then
NEWF_FIN= CAST(NEWF_FIN-1 AS DATE)+HORAFINHORARIO;
if (EXTRACT(WEEKDAY FROM NEWF_FIN) = 6) then
NEWF_FIN= CAST(NEWF_FIN-1 AS DATE)+ HORAFINHORARIO;
if (EXTRACT(WEEKDAY FROM NEWF_FIN) = 0) then
NEWF_FIN= CAST(NEWF_FIN-2 AS DATE)+ HORAFINHORARIO;
SABADOSYDOMINGOS =((DATEDIFF(DAY, NEWF_INICIO, NEWF_FIN)+EXTRACT(WEEKDAY FROM NEWF_INICIO) )/7) *2;
TIEMPOW = DATEDIFF( DAY, NEWF_INICIO, newf_fin) -1 - SABADOSYDOMINGOS;
if (TIEMPOW < 0) then
TIEMPOW=0;
TIEMPOENDIASANTESFESTIVOS = TIEMPOW;
TIEMPOANTESFESTIVOS = TIEMPOW * datediff( MINUTE ,HORAINICIOHORARIO, HORAFINHORARIO) /60.00 + -- Dias transcurrido * horasDia
DATEDIFF( minute, CAST(NEWF_INICIO AS TIME), horafinhorario)/60.00 + -- horas de primer dia
DATEDIFF( minute, horainiciohorario, CAST(NEWF_FIN AS TIME))/60.00 ; -- horas del ultimo dia
SELECT COUNT(1) FROM festivos
WHERE DIA BETWEEN CAST(:NEWF_INICIO AS DATE)+1 AND CAST(:newf_fin AS DATE)-1
AND EXTRACT(weekday FROM DIA ) NOT IN (0,6) INTO :FESTIVOS;
TIEMPOW= TIEMPOW - FESTIVOS;
if ( DATEDIFF( DAY, NEWF_INICIO, NEWF_FIN) = 0) then -- si es el mismo dia, horafin - horainicio
TIEMPO= DATEDIFF( minute, CAST(NEWF_INICIO AS TIME), CAST(NEWF_FIN AS TIME)) / 60.00;
ELSE
TIEMPO= TIEMPOW * datediff( MINUTE ,HORAINICIOHORARIO, HORAFINHORARIO) /60.00 + -- Dias transcurridos * horasDia
DATEDIFF( minute, CAST(NEWF_INICIO AS TIME), horafinhorario)/60.00 + -- horas de primer dia
DATEDIFF( minute, horainiciohorario, CAST(NEWF_FIN AS TIME))/60.00 ; -- horas del ultimo dia
-- si el primer dia es festivo y no es sabado ni domingo, restamos las horas
FESTIVOS = 0;
SELECT COUNT(1) from FESTIVOS
where dia= cast(:NEWF_INICIO AS DATE)
AND EXTRACT(weekday FROM DIA ) NOT IN (0,6) INTO :FESTIVOS;
if (festivos =1) then
TIEMPO=tiempo - DATEDIFF( minute, CAST(NEWF_INICIO AS TIME), HORAFINHORARIO)/60.00;
-- si el ultimo día es festivo y no es sabado ni domingo , restamos las horas
FESTIVOS = 0;
SELECT COUNT(1) from FESTIVOS
where dia= cast(:NEWF_FIN AS DATE)
AND EXTRACT(weekday FROM DIA ) NOT IN (0,6) INTO :FESTIVOS;
if (festivos =1) then
TIEMPO=tiempo - DATEDIFF( minute, HORAINICIOHORARIO, CAST(NEWF_FIN AS TIME))/60.00;
HORASHORARIO = (datediff( MINUTE ,HORAINICIOHORARIO, HORAFINHORARIO))/60.00;
tiempodia1 = DATEDIFF( minute, CAST(NEWF_INICIO AS TIME), HORAFINHORARIO)/60.00;
TIEMPODIA2 = DATEDIFF( minute, HORAINICIOHORARIO, CAST(NEWF_FIN AS TIME))/60.00;
WfIN = NEWF_FIN;
WINICIO= NEWF_INICIO;
SABYDOM= SABADOSYDOMINGOS;
TIEMPO= TIEMPO;
if (TIEMPO < 0 or (TIEMPO IS NULL) ) then
TIEMPO=0;
suspend;
end^
SET TERM ; ^
GRANT SELECT ON FESTIVOS TO PROCEDURE TIEMPOENTREFECHAS;
GRANT EXECUTE ON PROCEDURE TIEMPOENTREFECHAS TO SYSDBA;