Nesse artigo vou mostrar uma forma simples de como criar uma stored procedure para retornar o próximo dia útil de uma data desconsiderando feriados pré cadastrados. O objetivo dessa procedure é verificar se a data informada no parâmetro é sábado, domingo ou feriado e caso seja irá retornar o próximo dia útil.

Lembrando que utilizei a versão 1.5 do Firebird para fazer este artigo.

Esse exemplo armazena os feriados como tipo DATE, e com isso será necessário atualizar os feriados anualmente, porém pode-se armazenar somente o dia e mês do feriado em campos separados e com isso eliminar essa atualização anual da tabela de feriados.

Mas voltado ao artigo, o primeiro passo é criar uma tabela para armazenar as datas dos feriados anuais e suas respectivas descrições. Segue a estrutura dessa tabela a seguir:

--tabela de feriados
CREATE TABLE FERIADOS
(
  DT DATE NOT NULL,
  DES VARCHAR(30)
)



Agora vamos criar nossa stored procedure:


CREATE PROCEDURE SP_PROXIMO_DIAUTIL
(
  PI_DATA DATE
)
RETURNS
(
  PO_DATA DATE
)

AS
  DECLARE VARIABLE VDATA DATE;
  DECLARE VARIABLE VDAY INTEGER;
  DECLARE VARIABLE VNEWDAY INTEGER;
  DECLARE VARIABLE I INTEGER;
  DECLARE VARIABLE J INTEGER;
  DECLARE VARIABLE VOK INTEGER;

BEGIN

  --pega o dia da semana
  SELECT EXTRACT(WEEKDAY FROM :PI_DATA) FROM RDB$DATABASE INTO :VDAY;

  --se for sexta incrementa dois dias
  IF (VDAY=6) THEN
    VDATA = PI_DATA+2;

  --se for domingo incrementa um dia
  ELSE IF (VDAY=0) THEN
    VDATA = PI_DATA+1;

  --caso contrário não incrementa nada
  ELSE
    VDATA = PI_DATA;

  --verifica se a data é um feriado
  SELECT COALESCE(COUNT(*),0)  FROM FERIADOS F WHERE F.DT = :VDATA INTO :I;

  --se for incrementa ate que a data não seja feriado e seja um dia util
  IF (I>0) THEN
  BEGIN

    VDATA = VDATA+1;
    VOK = 0;

    WHILE (VOK=0) DO
    BEGIN

      SELECT COALESCE(COUNT(*), 0)  FROM FERIADOS F WHERE F.DT = :VDATA INTO :J;

      IF (J>0) THEN
       
VDATA = VDATA+1;

      ELSE BEGIN
        SELECT EXTRACT(WEEKDAY FROM :VDATA) FROM RDB$DATABASE INTO :VNEWDAY;

        IF (VNEWDAY=6) THEN
         
VDATA = VDATA+2;
       
       
ELSE IF (VNEWDAY=0) THEN
          VDATA = VDATA+1;

        ELSE
          VOK = 1;
      END
    END
  END

  PO_DATA = VDATA;
  SUSPEND;
END;


Espero que tenham gostado e até o próximo artigo.