Making a holiday calendar with functional programming

January 06th, 2026 · 9 min read

Ler em português

One of my personal projects is the website Feriados do Brasil, which is a calendar that displays national, state and municipal holidays of many cities in Brazil. While I was developing this project, I found an interesting use case to apply functional programming and wanted to share it in this article, showing how FP can provide unique and elegant solutions.

Fixed and moveable holidays

There are two kinds of holidays: fixed feasts, whose dates always happen in the same day of the same month, and moveable feasts, whose date varies every year. The most common moveable feasts in Brazil are Holy Friday, Carnival and Corpus Christi.

Although less common, there are many other moveable holidays, each with its own determinative rule. The table below shows some of them.

Moveable holidayDate
Holy Fridaycalculated via mathematical formula
Carnival Tuesday*47 days before Easter
Corpus Christi60 days after Easter
Pentecost50 days after Easter
Sacred Heart of Jesus8 days after Corpus Christi
Commerce Day on
Rio de Janeiro
Third Monday of October
State holidays
on Acre**
If within Tuesday and Thursday,
they get transferred to Friday
State holidays on
Santa Catarina
If on work day,
they get transferred to Sunday

* Carnival is not an official holiday, although celebrated in almost the entire country.
** Except for the State Anniversary, on June 15th.

The question is: how can we store holidays in a database, considering that some are fixed and some are moveable? Furthermore, each moveable feast has its own rule?

Solution with functional programming

In this project, the listing and calculation of holidays are done entirely on the frontend, in JavaScript. Basically, a city's holidays are the union between national, state and municipal holidays. In the code, each set of holidays is represented by an array of functions.

const nationalHolidays = [
  ff(JANUARY, 1, "New Year"),
  mf(calculateCarnivalTuesday, "Carnival"),
  mf(calculateHolyFriday, "Holy Friday"),
  ff(APRIL, 21, "Tiradentes"),
  ff(MAY, 1, "Worker's Day"),
  ff(SEPTEMBER, 7, "Independency of Brazil"),
  ff(OCTOBER, 12, "Our Lady the Appeared"),
  ff(OCTOBER, 28, "Public Worker Day"),
  ff(NOVEMBER, 2, "All Souls' Day"),
  ff(NOVEMBER, 15, "Proclamation of the Republic"),
  ff(NOVEMBER, 20, "Black Consciousness Day"),
  ff(DECEMBER, 25, "Christmas")
];

ff and mf respectively represent fixed feast and moveable feast. These functions receive either the day and month or a function to calculate the date, and also a description. They return another function, which receives a numerical year and returns a holiday object, with the description and the exact date (JavaScript Date).

// fixed feast
function ff(month, day, desc) {
  return function (year) {
    return { date: new Date(year, month, day), description: desc };
  }
}

// moveable feast
function mf(funcCalcDate, desc) {
  return function (year) {
    return { date: funcCalcDate(year), description: desc };
  }
}

Here we use two functional programming concepts: higher-order functions and currying.

Higher-order functions are functions that receive other functions as input parameters or that return functions as outputs (or even both things at the same time). mf() receives funcCalcDate as an argument, which will receive a numerical year and return a Date object. Both mf() and ff() return functions.

Currying is a strategy of nesting functions inside other functions. In our case, ff and mf nest the internal function (year) {...}. Check out this other article to learn more about currying.

To obtain the holidays of a year, all we need is to iterate each function in the array, passing the year as argument:

let year = 2026;
let holidays = nationalHolidays.map((func) => func(year));

// returns:
[
  { date: new Date(2026, 1, 1), description: "New Year" },
  { date: new Date(2026, 2, 17), description: "Carnival" },
  { date: new Date(2026, 4, 3), description: "Holy Friday" },
  // ...
]

The website's code is public and is available on GitHub. Comments and variables' names are written in Portuguese.

Interesting reads

A

AlexandreHTRB

Campinas/SP,
Brasil