Olá Pessoal,
Boa tarde.
Neste post rápido, irei demonstrar como criar uma tabela com os feriados nacionais, estaduais e móveis do Brasil. Essa tabela é muito útil para identificar se uma determinada data é feriado ou não, e também é um pré-requisito para a criação da tabela de dias úteis do post Como calcular dias úteis no SQL Server.
Uma outra solução para esse problema, é utilizando OLE Automation ou CLR, consultando a API do site calendario.com.br, que retorna os feriados nacionais, estaduais, municipais e facultativos. Para saber mais sobre essa solução, acesse o post SQL Server – Como consultar os feriados nacionais, estaduais, municipais e facultativos de uma API utilizando OLE Automation e CLR (C#).
Gerando a carga dos dados
O código abaixo irá criar a tabela Feriado, e populá-la com os feriados nacionais, estaduais e móveis (Carnaval, Paixão de Cristo e Corpus Christi).
Visualizar código-fonte| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251  | 
						CREATE PROCEDURE dbo.stpGera_Feriados AS BEGIN     -------------------------------     -- Cria a tabela se não existir     -------------------------------     IF (OBJECT_ID('dbo.Feriado') IS NULL)     BEGIN         -- DROP TABLE dbo.Feriado         CREATE TABLE dbo.Feriado (             Nr_Ano SMALLINT NOT NULL,             Nr_Mes SMALLINT NOT NULL,             Nr_Dia SMALLINT NOT NULL,             Tp_Feriado CHAR(1) NULL,             Ds_Feriado VARCHAR(100) NOT NULL,             Sg_UF CHAR(2) NOT NULL         )         ALTER TABLE dbo.Feriado ADD CONSTRAINT [Pk_Feriado] PRIMARY KEY CLUSTERED  ([Nr_Ano], [Nr_Mes], [Nr_Dia], [Sg_UF]) WITH (FILLFACTOR=90, PAD_INDEX=ON) ON [PRIMARY]     END     -- Apaga os dados se já tiverem sido populados     TRUNCATE TABLE dbo.Feriado     -------------------------------     -- Feriados nacionais     -------------------------------     INSERT INTO dbo.Feriado     SELECT 0, 1, 1, 1, 'Confraternização Universal', ''     UNION     SELECT 0, 4, 21, 1, 'Tiradentes', ''     UNION     SELECT 0, 5, 1, 1, 'Dia do Trabalhador', ''     UNION     SELECT 0, 9, 7, 1, 'Independência', ''     UNION     SELECT 0, 10, 12, 1, 'Nossa Senhora Aparecida', ''     UNION     SELECT 0, 11, 2, 1, 'Finados', ''     UNION     SELECT 0, 11, 15, 1, 'Proclamação da República', ''     UNION     SELECT 0, 12, 25, 1, 'Natal', ''     -------------------------------     -- Feriados estaduais     -------------------------------     -- Acre     INSERT INTO dbo.Feriado     SELECT 0, 1, 23, 2, 'Dia do evangélico', 'AC'     UNION     SELECT 0, 3, 8, 2, 'Alusivo ao Dia Internacional da Mulher', 'AC'     UNION     SELECT 0, 6, 15, 2, 'Aniversário do estado', 'AC'     UNION     SELECT 0, 9, 5, 2, 'Dia da Amazônia', 'AC'     UNION     SELECT 0, 11, 17, 2, 'Assinatura do Tratado de Petrópolis', 'AC'     -- Alagoas     INSERT INTO dbo.Feriado     SELECT 0, 6, 24, 2, 'São João', 'AL'     UNION     SELECT 0, 6, 29, 2, 'São Pedro', 'AL'     UNION     SELECT 0, 9, 16, 2, 'Emancipação política', 'AL'     UNION     SELECT 0, 11, 20, 2, 'Morte de Zumbi dos Palmares', 'AL'     -- Amapá     INSERT INTO dbo.Feriado     SELECT 0, 3, 19, 2, 'Dia de São José, santo padroeiro do Estado do Amapá', 'AP'     UNION     SELECT 0, 9, 13, 2, 'Criação do Território Federal (Data Magna do estado)', 'AP'     -- Amazonas     INSERT INTO dbo.Feriado     SELECT 0, 9, 5, 2, 'Elevação do Amazonas à categoria de província', 'AM'     UNION     SELECT 0, 11, 20, 2, 'Dia da Consciência Negra', 'AM'     -- Bahia     INSERT INTO dbo.Feriado     SELECT 0, 7, 2, 2, 'Independência da Bahia (Data magna do estado)', 'BA'     -- Ceará     INSERT INTO dbo.Feriado     SELECT 0, 3, 25, 2, 'Data magna do estado (data da abolição da escravidão no Ceará)', 'CE'     -- Distrito Federal     INSERT INTO dbo.Feriado     SELECT 0, 4, 21, 2, 'Fundação de Brasília', 'DF'     UNION     SELECT 0, 11, 30, 2, 'Dia do evangélico', 'DF'     -- Maranhão     INSERT INTO dbo.Feriado     SELECT 0, 7, 28, 2, 'Adesão do Maranhão à independência do Brasil', 'MA'     -- Mato Grosso     INSERT INTO dbo.Feriado     SELECT 0, 11, 20, 2, 'Dia da Consciência Negra', 'MT'     -- Mato Grosso do Sul     INSERT INTO dbo.Feriado     SELECT 0, 10, 11, 2, 'Criação do estado', 'MS'     -- Minas Gerais     INSERT INTO dbo.Feriado     SELECT 0, 4, 21, 2, 'Data magna do estado', 'MG'     -- Pará     INSERT INTO dbo.Feriado     SELECT 0, 8, 15, 2, 'Adesão do Grão-Pará à independência do Brasil (data magna)', 'PA'     -- Paraíba     INSERT INTO dbo.Feriado     SELECT 0, 7, 26, 2, 'Homenagem à memória do ex-presidente João Pessoa', 'PB'     UNION     SELECT 0, 8, 5, 2, 'Fundação do Estado em 1585', 'PB'     -- Paraná     INSERT INTO dbo.Feriado     SELECT 0, 12, 19, 2, 'Emancipação política (emancipação do Paraná)', 'PR'     -- Piauí     INSERT INTO dbo.Feriado     SELECT 0, 10, 19, 2, 'Dia do Piauí', 'PI'     -- Rio de Janeiro     INSERT INTO dbo.Feriado     SELECT 0, 4, 23, 2, 'Dia de São Jorge', 'RJ'     UNION     SELECT 0, 11, 20, 2, 'Dia da Consciência Negra', 'RJ'     -- Rio Grande do Norte     INSERT INTO dbo.Feriado     SELECT 0, 10, 3, 2, 'Mártires de Cunhaú e Uruaçu', 'RN'     -- Rio Grande do Sul     INSERT INTO dbo.Feriado     SELECT 0, 9, 20, 2, 'Proclamação da República Rio-Grandense', 'RS'     -- Rondônia     INSERT INTO dbo.Feriado     SELECT 0, 1, 4, 2, 'Criação do estado (data magna)', 'RO'     UNION     SELECT 0, 6, 18, 2, 'Dia do evangélico', 'RO'     -- Roraima     INSERT INTO dbo.Feriado     SELECT 0, 10, 5, 2, 'Criação do estado', 'RR'     -- Santa Catarina     INSERT INTO dbo.Feriado     SELECT 0, 10, 5, 2, 'Dia de Santa Catarina', 'SC'     -- São Paulo     INSERT INTO dbo.Feriado     SELECT 0, 7, 9, 2, 'Revolução Constitucionalista de 1932 (Data magna do estado)', 'SP'     -- Sergipe     INSERT INTO dbo.Feriado     SELECT 0, 3, 17, 2, 'Aniversário de Aracaju', 'SE'     UNION     SELECT 0, 6, 24, 2, 'São João', 'SE'     UNION     SELECT 0, 7, 8, 2, 'Autonomia política de Sergipe', 'SE'     UNION     SELECT 0, 12, 8, 2, 'Nossa Senhora da Conceição', 'SE'     -- Tocantins     INSERT INTO dbo.Feriado     SELECT 0, 10, 5, 2, 'Criação do estado', 'TO'     UNION     SELECT 0, 3, 18, 2, 'Autonomia do Estado (criação da Comarca do Norte)', 'TO'     UNION     SELECT 0, 9, 8, 2, 'Padroeira do Estado (Nossa Senhora da Natividade)', 'TO'     -------------------------------     -- Feriados móveis     -------------------------------     DECLARE         @ano INT,         @seculo INT,         @G INT,         @K INT,         @I INT,         @H INT,         @J INT,         @L INT,         @MesDePascoa INT,         @DiaDePascoa INT,         @pascoa DATETIME      DECLARE          @Dt_Inicial datetime = '1990-01-01',         @Dt_Final datetime = '2099-01-01'     WHILE(@Dt_Inicial <= @Dt_Final)     BEGIN         SET @ano = YEAR(@Dt_Inicial)         SET @seculo = @ano / 100          SET @G = @ano % 19         SET @K = ( @seculo - 17 ) / 25         SET @I = ( @seculo - CAST(@seculo / 4 AS int) - CAST(( @seculo - @K ) / 3 AS int) + 19 * @G + 15 ) % 30         SET @H = @I - CAST(@I / 28 AS int) * ( 1 * -CAST(@I / 28 AS int) * CAST(29 / ( @I + 1 ) AS int) ) * CAST(( ( 21 - @G ) / 11 ) AS int)         SET @J = ( @ano + CAST(@ano / 4 AS int) + @H + 2 - @seculo + CAST(@seculo / 4 AS int) ) % 7         SET @L = @H - @J         SET @MesDePascoa = 3 + CAST(( @L + 40 ) / 44 AS int)         SET @DiaDePascoa = @L + 28 - 31 * CAST(( @MesDePascoa / 4 ) AS int)         SET @pascoa = CAST(@MesDePascoa AS varchar(2)) + '-' + CAST(@DiaDePascoa AS varchar(2)) + '-' + CAST(@ano AS varchar(4))         INSERT INTO dbo.Feriado         SELECT YEAR(DATEADD(DAY , -2, @pascoa)), MONTH(DATEADD(DAY , -2, @pascoa)), DAY(DATEADD(DAY , -2, @pascoa)), 1, 'Paixão de Cristo', ''         INSERT INTO dbo.Feriado         SELECT YEAR(DATEADD(DAY , -48, @pascoa)), MONTH(DATEADD(DAY , -48, @pascoa)), DAY(DATEADD(DAY , -48, @pascoa)), 1, 'Carnaval', ''         INSERT INTO dbo.Feriado         SELECT YEAR(DATEADD(DAY , -47, @pascoa)), MONTH(DATEADD(DAY , -47, @pascoa)), DAY(DATEADD(DAY , -47, @pascoa)), 1, 'Carnaval', ''         INSERT INTO dbo.Feriado         SELECT YEAR(DATEADD(DAY , 60, @pascoa)), MONTH(DATEADD(DAY , 60, @pascoa)), DAY(DATEADD(DAY , 60, @pascoa)), 1, 'Corpus Christi', ''         SET @Dt_Inicial = DATEADD(YEAR, 1, @Dt_Inicial)     END END  | 
					
Após executar a procedure (EXEC dbo.stpGera_Feriados), você terá esses resultados:
Feriados no ES em 2015
Feriados no RJ em 2016
É isso aí,
Até o próximo post, onde falarei sobre cálculos com dias úteis (SPOILER).



																								
																								
Oi, Dirceu! Tudo bem? Usei seu algoritmo aqui adaptado pro MySQL. Vi que você usou o Algoritmo de Gauss pra determinar o feriado de Páscoa, mas em um momento (2013), ele calcula que cai em 2013-04-0 (dia 0). Normalmente, eu trataria este caso pra cair dia 2013-03-31, mas não vi você comentando sobre isso. Aconteceu com você também? Chegou a testar o programa? Muito obrigado, o código está muito bom! Abs!
Diêuler,
Obrigado pelo feedback.
Testei sim, no ano de 2013, esse código informa que a páscoa foi no dia 31/03/2013, que está correto.
Será que esse problema não ocorreu na conversão do código pro MySQL ? Se puder, disponibiliza ele no pastebin.com e envia aqui pra gente analisar.
Abraço!
Opa, obrigado pela resposta. Eu reescrevi o código, usei outro algoritmo para gerar os feriados móveis (Meeus/Jones/Butcher) e funcionou lindamente. Posso disponibilizar pra você:
https://pastebin.com/VqAyLBtv
Abs!
Dirceu, muito bom seu post, porém ao executar o a Stored Procedure gera vários erros, é isso mesmo?
Thiago,
Boa tarde!
Você pode me mostrar qual erro está ocorrendo? Qual a versão do seu SQL Server ?
Boa tarde Dirceu!
Utilizo o SQL Server 2008 R2 como BD e o Management Studio 2014. Sobre os erros são vários como por exemplo: conversão de dados; inserção de valor null não permitido; Violação de restrição Primary Key. Caso queira posso enviar o resultado completo ao Executa-la de outra forma.
Meu, bem legal em SQL, mas eu gosto bastante de usar essa API aqui, que é on-line e retorna um XML com os feriados de todas as cidades do Brasil: http://www.calendario.com.br/api_feriados_municipais_estaduais_nacionais.php
Siri, boa tarde.
Muito obrigado pela dica. Por causa dela, surgiu meu novo post. Dá uma olhada 🙂
http://www.dirceuresende.com/blog/sql-server-como-consultar-os-feriados-nacionais-estaduais-municipais-e-facultativos-de-uma-api-utilizando-ole-automation-e-clr-csharp/
Poxa, que legal que gostou!
Show de bola!