Índice
- Introdução
- E como calcula a Páscoa?
- Função Personalizada na Linguagem M
- Retornando os Feriados Fixos
- Retornando Feriados Móveis
- A função fnFeriados
- A tabela Calendário
Introdução
Dentro da análise de dados, a precisão e a relevância das informações extraídas são fundamentais para a tomada de decisões. No entanto, a presença de variáveis ocultas pode distorcer significativamente os resultados obtidos.
Uma dessas variáveis frequentemente subestimada é o impacto dos feriados.
Feriados, seja em escala nacional, regional ou local, podem influenciar drasticamente padrões de consumo, comportamento de trabalho e fluxos econômicos, fazendo com que atividades normais sofram interrupções significativas.
O objetivo desse artigo é mostrar como obter uma lista de feriados utilizando o Power Query (Linguagem M) sem a necessidade de consultar qualquer tipo de API externa.
A maior dificuldade para calcular feriados estão justamente nos feriados que mudam de ano pra ano, como páscoa, paixão de cristo, corpo de cristo e por aí vai.
O ponto mais importante disso é saber que todos esses feriados são calculados com base no domingo de Páscoa, que sempre ocorre no no primeiro domingo após a primeira lua cheia do equinócio de Outono (no hemisfério norte, Primavera).
Um ciclo lunar leva em média 29 dias, 12 horas e 44 minutos para se completar e isso faz com que o equinócio não seja sempre em uma data exata, pois um ciclo lunar é diferente de um ciclo terreste. Porém, fixou-se a data de início do Outono (Primavera, no hemisfério norte) como base para cálculo da Páscoa.
E a partir daí, calcula-se os demais feriados que são baseados na páscoa.
- A Terça-feira de carnaval ocorre 47 dias antes do Domingo de Páscoa.
- A Paixão de Cristo, ocorre sempre numa Sexta-feira dois dias antes do Domingo de Páscoa.
- O Corpo de Cristo ocorre sempre numa Quinta-Feira, 60 dias após o Domingo de Páscoa.
E como calcula a Páscoa?
A verdade é que você não precisa reinventar a roda e criar um algoritmo próprio pra se chegar a essa data. Existem diversos algoritmos que fazem isso.
Em uma pesquisa rápida no Google eu encontrei uma lista desses deles. Você pode inclusive clicar aqui para acessar a página do Wikipédia que eu consultei para escolher qual algoritmo eu iria replicar na Linguagem M.
Eu usei o “Anonymous Gregorian algorithm” que tem a seguinte sequência de cálculos.
Neste algoritmo, a variável n indica o mês do ano (seja março para n = 3, ou abril para n = 4), enquanto o dia do mês é obtido como (o + 1).
Função Personalizada na Linguagem M
Agora que a gente já sabe o passo a passo para obter a data da Páscoa. Vamos replicar os cálculos na Linguagem M. A função abaixo retorna a data do Domingo de Páscoa, sendo que o único argumento requerido é o ano (y).
Crie uma consulta nula com o nome fnFeriados e vamos replicar o código abaixo.
(y as number) =>
let
/***************************************************************************
Obtém a data do Domingo de Páscoa usando o "Anonymous Gregorian algorithm"
Fonte: https://en.wikipedia.org/wiki/Date_of_Easter
Desenvolvido por Laennder Alves
****************************************************************************/
a = Number.Mod(y, 19),
b = Number.RoundDown(y / 100),
c = Number.Mod(y, 100),
d = Number.RoundDown(b / 4),
e = Number.Mod(b, 4),
f = Number.RoundDown((b + 8) / 25),
g = Number.RoundDown((b - f + 1) / 3),
h = Number.Mod((19 * a + b - d - g + 15), 30),
i = Number.RoundDown(c / 4),
k = Number.Mod(c, 4),
l = Number.Mod((32 + 2 * e + 2 * i - h - k), 7),
m = Number.RoundDown((a + 11 * h + 22 * l) / 451),
n = Number.RoundDown((h + l - 7 * m + 114) / 31),
o = Number.Mod((h + l - 7 * m + 114), 31),
pascoa = #date(y, n, o + 1)
in
pascoa
Retornando os Feriados Fixos
A lista de feriados fixos pode ser obtida usando o construtor #date para gerar cada uma das datas.
Expandindo a função anterior, eu optei por gerar uma lista de registros, onde cada registro retorna os campos Data e Feriado, sendo o nome do feriado.
Note que usei o parâmetro y que será recebido pela função para referir ao ano.
FeriadosFixos = {
[ Data = #date(y, 01, 01), Feriado = "Ano Novo" ],
[ Data = #date(y, 04, 21), Feriado = "Tiradentes" ],
[ Data = #date(y, 05, 01), Feriado = "Dia do Trabalho" ],
[ Data = #date(y, 09, 07), Feriado = "Dia da Independência" ],
[ Data = #date(y, 10, 12), Feriado = "Nossa Sra. Aparecida" ],
[ Data = #date(y, 11, 02), Feriado = "Finados" ],
[ Data = #date(y, 11, 15), Feriado = "Proclamação da República" ],
[ Data = #date(y, 11, 20), Feriado = "Consciência Negra" ],
[ Data = #date(y, 12, 25), Feriado = "Natal" ]
},
Se precisar criar novos feriados é só adaptar a lista.
Retornando Feriados Móveis
Já para a lista de feriados que são calculados a partir da Páscoa eu utilize a função Date.AddDays para adicionar (ou subtrair) os dias.
/* FERIADOS MÓVEIS */
FeriadosMoveis = {
[ Data = Date.AddDays(pascoa, -47), Feriado = "Carnaval" ],
[ Data = Date.AddDays(pascoa, -2), Feriado = "Paixão de Cristo" ],
[ Data = pascoa, Feriado = "Domingo de Páscoa" ],
[ Data = Date.AddDays(pascoa, 60), Feriado = "Corpus Christi" ]
},
A função fnFeriados
O resultado final para a função que estamos criando deve ser uma tabela contendo tanto os feriados fixos quanto móveis. Pra isso vamos usar a função Table.FromRecords, e passar como argumento a junção das duas listas que calculamos anteriormente.
A função completa fica assim:
(y as number) =>
let
/***************************************************************************
Obtém a data do Domingo de Páscoa usando o "Anonymous Gregorian algorithm"
Fonte: https://en.wikipedia.org/wiki/Date_of_Easter
Desenvolvido por Laennder Alves
****************************************************************************/
a = Number.Mod(y, 19),
b = Number.RoundDown(y / 100),
c = Number.Mod(y, 100),
d = Number.RoundDown(b / 4),
e = Number.Mod(b, 4),
f = Number.RoundDown((b + 8) / 25),
g = Number.RoundDown((b - f + 1) / 3),
h = Number.Mod((19 * a + b - d - g + 15), 30),
i = Number.RoundDown(c / 4),
k = Number.Mod(c, 4),
l = Number.Mod((32 + 2 * e + 2 * i - h - k), 7),
m = Number.RoundDown((a + 11 * h + 22 * l) / 451),
n = Number.RoundDown((h + l - 7 * m + 114) / 31),
o = Number.Mod((h + l - 7 * m + 114), 31),
pascoa = #date(y, n, o + 1),
/* FERIADOS FIXOS */
FeriadosFixos = {
[ Data = #date(y, 01, 01), Feriado = "Ano Novo" ],
[ Data = #date(y, 04, 21), Feriado = "Tiradentes" ],
[ Data = #date(y, 05, 01), Feriado = "Dia do Trabalho" ],
[ Data = #date(y, 09, 07), Feriado = "Dia da Independência" ],
[ Data = #date(y, 10, 12), Feriado = "Nossa Sra. Aparecida" ],
[ Data = #date(y, 11, 02), Feriado = "Finados" ],
[ Data = #date(y, 11, 15), Feriado = "Proclamação da República" ],
[ Data = #date(y, 11, 20), Feriado = "Consciência Negra" ],
[ Data = #date(y, 12, 25), Feriado = "Natal" ]
},
/* FERIADOS MÓVEIS */
FeriadosMoveis = {
[ Data = Date.AddDays(pascoa, -47), Feriado = "Carnaval" ],
[ Data = Date.AddDays(pascoa, -2), Feriado = "Paixão de Cristo" ],
[ Data = pascoa, Feriado = "Domingo de Páscoa" ],
[ Data = Date.AddDays(pascoa, 60), Feriado = "Corpus Christi" ]
},
Resultado = Table.FromRecords( FeriadosFixos & FeriadosMoveis )
in
Resultado
O resultado obtido ao usar a função fnFeriados com o parâmetro y = 2024 é o seguinte:
A tabela Calendário
O próximo passo é combinar a tabela Calendário com o resultado dos feriados dos anos do período analisado.
O código a seguir gera uma tabela calendário para os anos 2020 a 2025. E depois calcula os feriados para o mesmo período e faz a junção com a tabela calendário.
let
AnoInicial = 2020,
AnoFinal = 2025,
DataInicial = #date(AnoInicial, 1, 1),
DataFinal = #date(AnoFinal, 12, 31),
QtdeDias = Duration.Days(DataFinal - DataInicial) -1,
Datas = List.Dates(DataInicial, QtdeDias, #duration(1,0,0,0)),
Calendario = #table (
type table [Data=date, Ano=Int32.Type, Nome do Mês=text, Mês=Int32.Type],
List.Transform(Datas, each {
_ ,
Date.Year ( _ ) ,
Date.MonthName( _ ),
Date.Month ( _ )
})
),
Feriados = Table.Combine( List.Transform( { AnoInicial .. AnoFinal } , fnFeriados ) ),
Juncao = Table.NestedJoin( Calendario, "Data", Feriados, "Data", "Feriados" ),
Expandido = Table.ExpandTableColumn(Juncao, "Feriados", {"Feriado"}, {"Feriado"}),
Ordenado = Table.Sort(Expandido,{{"Data", Order.Ascending}})
in
Ordenado
Pronto, agora você já tem uma lista de feriados para qualquer período que desejar.
Download do Arquivo
Para baixar o arquivo completo clique aqui.
Excelente!!! Muito obrigado!
Laender, bom-dia.
Excelente sua aula e planilha, no entanto quando elevei o ano para 2030 aparece um conflito de datas, com o Feriado de TIRADENTES e PASCOA, ambos caindo em 21/04/2030
Darlim, dá pra resolver isso concatenando os dois feriados em uma única linha. Vou fazer uma versão atualizada.