Í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.
Obrigado por compartilhar!
No caso se for mais de um ano, como posso fazer?