Jump to content

Fabiano Carloto

Members
  • Content count

    40
  • Joined

  • Last visited

Community Reputation

0 Comum

About Fabiano Carloto

Informações Pessoais

  • Localização
    Campo Grande - MS
  1. Fabiano Carloto

    Calcular diferença de datas em dias uteis?

    Olá pessoal. Estava procurando algo desse tipo na net pois enfrentava este dilema de calcular dias úteis no Oracle. Cansado de procurar, resolvi criar uma função pra isso. Ela conta tirando os feriados locais e nacionais cadastrados na tabela e conta caso queira por exemplo considerar sábado e/ou domingo como dia útil. Este ultimo, porque eu trabalho com turmas de treinamentos e algumas delas eram faturadas pelo fornecedor também nos sábados e/ou domingos, então eu tinha que considerar como dia útil. A tabela de feriados esta separada por estado porque como tem feriados locais também, tive que separar assim. A função ficou assim: create or replace FUNCTION DIAS_UTEIS(vCOD_UF INT, vDATAI IN DATE, vDATAF IN DATE, PERIODO IN INT) RETURN VARCHAR2 AS total_dias NUMBER; total_feriados NUMBER; total_dias_uteis NUMBER := 0; /* s = dias da semana que devemos considerar 0 conta sabado e domingo 1 não conta domingo 2 não conta sabado e domingo */ begin /* CONTA A QUANTIDADE DE DIAS ENTRE AS DATAS SEM VERIFICAR FERIADOS, SÁBADOS E DOMINGOS */ FOR CUR_ROW IN (SELECT TO_DATE(vDATAF)-TO_DATE(vDATAI) TTDIAS FROM DUAL) LOOP total_dias:=CUR_ROW.TTDIAS; END LOOP; /* CHECA SE EXISTE ALGUM DIA ENTRE AS DATAS NA LISTA DE FERIADOS E SEPARA A CONTAGEM PARA CONSIDERAR: 0 = CONTA SÁBADO E DOMINDO 1 = NÃO CONTA FERIADOS DE DOMINGO 2 = NÃO CONTA FERIADOS DE SÁBADO E DOMINGO PORQUE ISSO? VOCÊ PODE QUERER CONSIDERAR SÁBADO COMO DIA UTIL POR EXEMPLO. */ IF PERIODO = 0 THEN FOR CUR_ROW IN (SELECT COUNT(DATA_FERIADO) TT_FERIADOS FROM GIP_TAB_GBL_FERIADOS WHERE DATA_FERIADO BETWEEN TO_DATE(vDATAI) AND TO_DATE(vDATAF) AND COD_UF=vCOD_UF) LOOP total_feriados:=CUR_ROW.TT_FERIADOS; END LOOP; ELSIF PERIODO = 1 THEN FOR CUR_ROW IN (SELECT SUM(CASE WHEN TO_CHAR(DATA_FERIADO,'DY') NOT IN('DOM') THEN 1 ELSE 0 END) TT_FERIADOS FROM GIP_TAB_GBL_FERIADOS WHERE DATA_FERIADO BETWEEN TO_DATE(vDATAI) AND TO_DATE(vDATAF) AND COD_UF=vCOD_UF) LOOP total_feriados:=CUR_ROW.TT_FERIADOS; END LOOP; ELSIF PERIODO = 2 THEN FOR CUR_ROW IN (SELECT SUM(CASE WHEN TO_CHAR(DATA_FERIADO,'DY') NOT IN('SÁB','DOM') THEN 1 ELSE 0 END) TT_FERIADOS FROM GIP_TAB_GBL_FERIADOS WHERE DATA_FERIADO BETWEEN TO_DATE(vDATAI) AND TO_DATE(vDATAF) AND COD_UF=vCOD_UF) LOOP total_feriados:=CUR_ROW.TT_FERIADOS; END LOOP; END IF; /* PERCORRE DIA POR DIA SEMPRE CHECANDO SE DESEJA CONTAR OU NÃO SABADO E DOMINGO */ FOR i IN 0 .. total_dias LOOP IF PERIODO = 0 THEN FOR CUR_ROW IN (SELECT TO_DATE(vDATAI)+i FROM DUAL) LOOP total_dias_uteis:=total_dias_uteis+1; END LOOP; ELSIF PERIODO = 1 THEN FOR CUR_ROW IN (SELECT (CASE WHEN TO_CHAR(TO_DATE(vDATAI)+i,'DY') NOT IN('DOM') THEN 1 ELSE 0 END) TT FROM DUAL) LOOP total_dias_uteis:=total_dias_uteis++CUR_ROW.TT; END LOOP; ELSIF PERIODO = 2 THEN FOR CUR_ROW IN (SELECT (CASE WHEN TO_CHAR(TO_DATE(vDATAI)+i,'DY') NOT IN('SÁB','DOM') THEN 1 ELSE 0 END) TT FROM DUAL) LOOP total_dias_uteis:=total_dias_uteis+CUR_ROW.TT; END LOOP; END IF; END LOOP; total_dias:=total_dias+1; RETURN 'TOTAL DIAS:'||total_dias||' - TOTAL FERIADOS:'||total_feriados||' - DIAS UTEIS:'||total_dias_uteis||' - DIAS UTEIS TOTAL:'||(total_dias_uteis-total_feriados); END; O return dela esta como varchar apenas para testar a conta e verificar se esta fazendo certo. Para pegar o resultado final, substitua por: RETURN (total_dias_uteis-total_feriados); Executando um exemplo: SELECT DIAS_UTEIS(2,TO_DATE('2015-02-01'),TO_DATE('2015-02-28'),0) FROM DUAL; A primeira variável da função é o código do estado, no meu caso tenho 2 como GO; A segunda é a data inicial; A terceira é a data final; A quarta é o indicativo para contar ou não sábado e/ou domingo conforme abaixo: 0 conta sábado e domingo 1 não conta domingo 2 não conta sábado e domingo Este SELECT resulta em: TOTAL DIAS:28 - TOTAL FERIADOS:2 - DIAS UTEIS:28 - DIAS UTEIS TOTAL:26 *Os dois dias de feriado é por causa do Carnaval cadastrado para os dias 16 e 17/02/2015. SELECT DIAS_UTEIS(2,TO_DATE('2015-02-01'),TO_DATE('2015-02-28'),1) FROM DUAL; Resultado não conta domingo: TOTAL DIAS:28 - TOTAL FERIADOS:2 - DIAS UTEIS:24 - DIAS UTEIS TOTAL:22 SELECT DIAS_UTEIS(2,TO_DATE('2015-02-01'),TO_DATE('2015-02-28'),2) FROM DUAL; Resultado não conta sábado e domingo: TOTAL DIAS:28 - TOTAL FERIADOS:2 - DIAS UTEIS:20 - DIAS UTEIS TOTAL:18 Espero que ajude muita gente assim como me ajudou e se alguém quiser melhorar ou sugerir algo, fiquem a vontade. Dúvidas, só perguntar. Obrigado aos demais que ajudaram de forma indireta. Tabela de feriados: CREATE TABLE "USER_GIP_HLG"."GIP_TAB_GBL_FERIADOS" ( "COD_UF" NUMBER(*,0), "DIA" NUMBER(*,0), "DATA_FERIADO" DATE, "FERIADO" VARCHAR2(200 BYTE), "NACIONAL" NUMBER(*,0) ) SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "TBL_BASE" ; COMMENT ON COLUMN "USER_GIP_HLG"."GIP_TAB_GBL_FERIADOS"."NACIONAL" IS '0 - NACIONAL | 1 - MUNICIPAL';
×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.