How to Generate a Monthly Calendar Matrix in JavaScript
Building a calendar UI might look simple, but behind the scenes it requires careful handling of dates, weeks, and empty slots. In this guide, we will break down a clean and reusable JavaScript function that generates a 2D calendar matrix for any given month and year.
- How calendar grids work internally
- How to calculate leading and trailing empty days
- How to generate a week-by-week matrix
- How to format dates using Day.js
What Is a Calendar Matrix?
A calendar matrix is a two-dimensional array where:
- Each row represents a week (Sunday to Saturday)
- Each column represents a day of the week
- Empty cells are represented by
null
[ [null, null, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11, 12], ... ]
The JavaScript Function Explained
Below is the complete function that generates the monthly calendar matrix.
It uses native JavaScript Date along with Day.js
for formatting.
import dayjs from "dayjs-ext";
export function getMonthMatrix(year, month) {
const first = new Date(year, month, 1);
const start = first.getDay();
const daysInMonth = new Date(year, month + 1, 0).getDate();
const matrix = [];
let row = [];
for (let i = 0; i < start; i++) {
row.push(null);
}
for (let d = 1; d <= daysInMonth; d++) {
const dateTime = dayjs(new Date(year, month, d));
row.push({
isoDate: dateTime.format('YYYY-MM-DD'),
jsDate: new Date(year, month, d),
day: d
});
if (row.length === 7) {
matrix.push(row);
row = [];
}
}
if (row.length) {
while (row.length < 7) row.push(null);
matrix.push(row);
}
return matrix;
}
Step-by-Step Logic Breakdown
We detect which day the month begins on. This tells us how many empty cells are needed before day 1.
We loop from day 1 to the last day of the month, pushing date objects into the calendar row.
If the last row is incomplete, we add null values so every row
always has exactly 7 columns.
Suggested Reading
Watch the Concept in Action
This short video visually explains how calendar matrices work in real UI components.
This approach is production-ready and perfect for calendar apps, booking systems, expense trackers, and scheduling dashboards. The logic stays clean, predictable, and easy to maintain.