Building a Custom Calendar with React and Day.js: A Step-by-Step Guide.
Oluwadahunsi A.
Posted on June 20, 2024
Welcome!
This is the first of a three-part series on building a custom calendar with React and Day.js. We are going to start with a simple calendar in this first part and go all the way up to a date range picker in the third part.
When you are done with this, you can check the second part here:
Building a simple Date Picker with React and Day.js
Oluwadahunsi A. ・ Jun 20
And the third part here:
Building a Date Range Picker with React and Day.js.
Oluwadahunsi A. ・ Jun 20
Here, we will create a simple, yet functional calendar using React and Day.js, then we will add more features and functionalites in the subsequent parts.
By the end of this part, you will have a basic calendar that looks like this:
By the end of the third part, we will have a Date Range Picker created from this calendar. Here is a sneak peak:
Try to follow along as much as you can. I have also provided the final version for this part at the end of this article. So, let us dive into creating a dynamic calendar application!
Setting up our React project with Vite.
To kickstart our React project using Vite, let's begin by opening our terminal and running the following command:
npm create vite@latest
If you prefer, you can name the project “Calendar”. Otherwise, you are free to choose a name that suits you. Also, make sure to select Typescript while setting up vite for your application.
Project name: Use any name you prefer.
Framework: React.
Language: TypeScript.
Once you are all set, create a Calendar
folder within your src
directory. Inside the Calendar
folder, create two files: Calendar.tsx
for building our Calendar component and style.css
for our styling needs. Your folder structure should resemble the following:
src/
└── Calendar/
├── Calendar.tsx
└── style.css
Installing Day.js
As you already know, we will be using Day.js
library for date manipulation, I recommend visiting their website to familiarize yourself with its capabilities. To install Day.js
for our project, open your terminal and execute the following command:
npm install dayjs
Before proceeding, you might be wondering why we are choosing Day.js for date formatting instead of relying on the built-in Date object. The rationale behind using a third-party library like Day.js includes several advantages, one of which is the fact that Day.js gives simple APIs for date manipulation. I will show this with an example.
Imagine you have to get a date in this format DD.MM.YYYY HH:mm:sss
. Can you try to achieve this on your own using the built-in Date object?
One possible solution is to write a function that accepts a date and returns it in the format we desire. Let’s do that below.
const formatGivenDate = (date) => {
const day = date.getDate();
const month = date.getMonth() + 1; // Add 1 to month because it is zero based
const year = date.getFullYear();
const hours = date.getHours();
const minutes = date.getMinutes();
const seconds = date.getSeconds();
// join with template literal and return formatted date
return `${day < 10 ? "0" + day : day}.${month < 10 ? '0' + month : month}.${year} ${hours}:${minutes}:${seconds}`
}
const date = new Date();
console.log(formatGivenDate(date)) // 15.06.2024 21:48:13
That looks quite straightforward, right? But what if we can achieve the same thing with a lot less than that?
Let us see what it looks like with Day.js.
const date = dayjs();
const formattedDate = date.format('DD.MM.YYYY HH:mm:ss')
Yay, we got the same result in 2 lines of code.
Another reason why we are using Day.js is because it is a really lightweight library compared to a lot of the other available options — it is just 2kb in size.
Okay, back to building our calendar.
Starter files
To save time, I will provide you with the initial content of Calendar.tsx
and the style.css
files.
.calendar__container {
display: flex;
flex-direction: column;
align-items: center;
padding: 25px;
width: max-content;
background: #ffffff;
box-shadow: 5px 10px 10px #dedfe2;
}
.month-year__layout {
display: flex;
margin: 0 auto;
width: 100%;
flex-direction: row;
align-items: center;
justify-content: space-around;
}
.year__layout,
.month__layout {
width: 150px;
display: flex;
padding: 10px;
font-weight: 600;
align-items: center;
text-transform: capitalize;
justify-content: space-between;
}
.back__arrow,
.forward__arrow {
cursor: pointer;
background: transparent;
border: none;
}
.back__arrow:hover,
.forward__arrow:hover {
scale: 1.1;
transition: scale 0.3s;
}
.days {
display: grid;
grid-gap: 0;
width: 100%;
grid-template-columns: repeat(7, 1fr);
}
.day {
flex: 1;
font-size: 16px;
padding: 5px 7px;
text-align: center;
}
.calendar__content {
position: relative;
background-color: transparent;
}
.calendar__items-list {
text-align: center;
width: 100%;
height: max-content;
overflow: hidden;
display: grid;
grid-gap: 0;
list-style-type: none;
grid-template-columns: repeat(7, 1fr);
}
.calendar__items-list:focus {
outline: none;
}
.calendar__day {
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.calendar__item {
position: relative;
width: 50px;
height: 50px;
cursor: pointer;
background: transparent;
border-collapse: collapse;
background-color: white;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
border: 1px solid transparent;
z-index: 200;
}
button {
margin: 0;
display: inline;
box-sizing: border-box;
}
.calendar__item:focus {
outline: none;
}
.calendar__item.selected {
font-weight: 700;
border-radius: 50%;
background: #1a73e8;
color: white;
outline: none;
border: none;
}
.calendar__item.selectDay {
position: relative;
background: #1a73e8;
color: white;
border-radius: 50%;
border: none;
z-index: 200;
}
.calendar__item.gray,
.calendar__item.gray:hover {
color: #c4cee5;
display: flex;
justify-content: center;
align-items: center;
}
.input__container {
display: flex;
justify-content: space-around;
}
.input {
height: 30px;
border-radius: 8px;
text-align: center;
align-self: center;
border: 1px solid #1a73e8;
}
.shadow {
position: absolute;
display: inline-block;
z-index: 10;
top: 0;
background-color: #f4f6fa;
height: 50px;
width: 50px;
}
.shadow.right {
left: 50%;
}
.shadow.left {
right: 50%;
}
//Calendar.tsx
import backArrow from '../assets/images/back.svg';
import forwardArrow from '../assets/images/forward.svg';
import './style.css';
const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
const daysListGenerator = {
day: 15,
prevMonthDays: [26, 27, 28, 29, 30],
days: [
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,
],
remainingDays: [1, 2, 3, 4, 5],
};
export const Calendar = () => {
return (
<div className='calendar__container'>
<div className='control__layer'>
<div className='month-year__layout'>
<div className='year__layout'>
<button className='back__arrow'>
<img src={backArrow} alt='back arrow' />
</button>
<div className='title'>2024</div>
<button className='forward__arrow'>
<img src={forwardArrow} alt='forward arrow' />
</button>
</div>
<div className='month__layout'>
<button className='back__arrow'>
<img src={backArrow} alt='back arrow' />
</button>
<div className='new-title'>June</div>
<button className='forward__arrow'>
<img src={forwardArrow} alt='forward arrow' />
</button>
</div>
</div>
<div className='days'>
{weekDays.map((el, index) => (
<div key={`${el}-${index}`} className='day'>
{el}
</div>
))}
</div>
<div className='calendar__content'>
<div className={'calendar__items-list'}>
{daysListGenerator.prevMonthDays.map((el, index) => {
return (
<div key={`${el}/${index}`} className='calendar__day'>
<button className='calendar__item gray'>
{el}
</button>
</div>
);
})}
{daysListGenerator.days.map((el, index) => {
return (
<div key={`${index}-/-${el}`} className='calendar__day'>
<button
className={`calendar__item
${+el === +daysListGenerator.day ? 'selected' : ''}`}
>
<div className='day__layout'>
<div className='text'>{el.toString()}</div>
</div>
</button>
</div>
);
})}
{daysListGenerator.remainingDays.map((el, idx) => {
return (
<div key={`${idx}----${el}`} className='calendar__day'>
<button className='calendar__item gray' >
{el}
</button>
</div>
);
})}
</div>
</div>
</div>
</div>
);
};
// src/App.tsx
import { Calendar } from './Calendar/Calendar';
function App() {
return (
<>
<Calendar />
</>
);
}
export default App;
You probably have noticed that I imported some svg files in the Calendar component, right?
I got them from svg repo but don’t worry I won’t leave you to source for them yourself. Here you have it.
//back.svg
<?xml version="1.0" encoding="utf-8"?>
<svg width="20px" height="20px" viewBox="0 0 1000 1000" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M768 903.232l-50.432 56.768L256 512l461.568-448 50.432 56.768L364.928 512z" fill="#000000" /></svg>
//forward.svg
<?xml version="1.0" encoding="utf-8"?>
<svg width="20px" height="20px" viewBox="0 0 1000 1000" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M256 120.768L306.432 64 768 512l-461.568 448L256 903.232 659.072 512z" fill="#000000" /></svg>
For no particular reason — other than just following along — create an image folder inside your assets directory and put the two svg files in this folder.
At this point, your file structure should look like this.
src/
└── assets/
└──images/
├── back.svg
└── forward.svg
└── Calendar/
├── Calendar.tsx
└── style.css
The daysListGenerator
object in the Calendar.tsx
file holds the values needed to populate our calendar. Let us look at what each of the property in the object means:
day
is the current day or today. In the picture below, we can see it is 15
.
prevMonthDays
array contains the days in the previous month that will show in the current month. These days are so important as they will also help to offset the days in the current month and ensure that the first day of the current month matches with the corresponding day of the week. In the picture below these days are: [26, 27, 28, 29, 30]
days
array contains the days in the current month, the length of this array will range from 28 to 31.
remainingDays
array contains the days in the next month that will show in the current month. Since we have prevMonthDays, we can as well just have the remaining days as well. In the picture below, the remaining days are: [1, 2, 3, 4, 5, 6, 7]
Provided you have followed everything up to this point, if you start your application, you should have a calendar that looks like this:
The content of our calendar is currently hardcoded,so we need to fix this and make it as dynamic as we can.
Adding functionalities to the calendar.
So far, we have successfully initialized our project, installed DayJs, and hardcoded a basic calendar. Now, the next step is to ensure everything functions correctly. Our calendar should be able to display different months and years, as well as the corresponding days. Let’s focus on implementing these features to ensure our calendar is fully operational and not perpetually stuck in the past.
You would agree with me that in order to achieve our aim, all we need to do is ensure that the daysListGenerator
object is dynamic and each of the properties change with respect to today’s date.
//
const daysListGenerator = {
day: 15,
prevMonthDays: [26, 27, 28, 29, 30],
days: [
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,
],
remainingDays: [1, 2, 3, 4, 5],
};
//
So, instead of hardcoding the properties in this object, we will try to generate them based on our current date (or today’s date).
To do that, let us create a helper function. This function will be responsible for generating all the currently hardcoded values in our calendar, such as day
, prevMonthDays
, days
, and remainingDays
.
In your src directory, create a folder called helper
, inside this folder, create a calendarObjectGenerator.ts
file. Your file structure should now look similar to this:
src/
└── assets/
└──images/
├── back.svg
└── forward.svg
└── Calendar/
├── Calendar.tsx
└── style.css
└── helper
└── calendarObjectGenerator.ts
Inside the calendarObjectGenerator.ts
file, we will create a function called calendarObjectGenerator
. This function will accept the currentDate or (today’s date), and will return an object containing calculated values, based on the current date, for all the properties we previously hardcoded.
This function is provided below:
//calendarObjectGenerator.ts
import dayjs, { Dayjs } from 'dayjs';
import isLeapYear from 'dayjs/plugin/isLeapYear';
import LocaleData from 'dayjs/plugin/localeData';
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.extend(customParseFormat);
dayjs.extend(LocaleData);
type GeneratedObjectType = {
days: number[];
day: number;
prevMonthDays: number[];
remainingDays: number[];
months: string[];
};
export const calendarObjectGenerator = (currentDate: Dayjs): GeneratedObjectType => {
const numOfDaysInPrevMonth = currentDate.subtract(1, 'month').daysInMonth();
const firstDayOfCurrentMonth = currentDate.startOf('month').day()
return {
days: Array.from({ length: currentDate.daysInMonth() }, (_, index) => index + 1),
day: Number(currentDate.format('DD')),
months: currentDate.localeData().months(),
//read explanation
prevMonthDays: Array.from({length:firstDayOfCurrentMonth}, (_,index) => numOfDaysInPrevMonth - index).reverse(),
remainingDays: Array.from(
{ length: 6 - currentDate.endOf('month').day() },
(_, index) => index + 1
),
}
Let me explain how the values for each of the property in the object is calculated.
days: Array.from({length: currentDate.daysInMonth()}, (_,index) => index + 1)
To get the number of days in a month, we can use the daysInMonth()
method from the DayJs object. This method returns the number of days as a numerical value (e.g 30). We can then create an array of integers from 1 to the number of days in currentDate.daysInMonth()
.
day: Number(currentDate.format('DD'))
We can extract the day of the month from our Day.js object by calling format method on the object and specifying what we want to extract.
months: currentDate.localeData().months()
This returns an array of all the months of the year.
prevMonthDays: Array.from({length:firstDayOfCurrentMonth}, (_,index) => numOfDaysInPrevMonth - index).reverse()
Now, let's consider the days from the previous month that we want to display. It's important to include these days as they will serve as an offset for the beginning of our current month, ensuring that the first day of the current month falls on the correct day of the week. Although getting the previous and remaining days can be a bit tricky, we can figure it out with some logic.
Let's break it down:
The method
dayjs().startOf('month').day()
gives us the first day of the current month, where 0 = Sunday and 6 = Saturday.Using this value, we can create an array representing the number of days before the first day of the current month:
Array.from({ length: dayjs().startOf('month').day() })
.DayJs makes it easy to find the last day of the previous month. Simply subtract one month from the current month and get the number of days:
dayjs().subtract(1, 'month').daysInMonth()
.Putting it all together, we can generate the last few days of the previous month:
Array.from({ length: dayjs().startOf('month').day() }, (_, index) => numOfDaysInPrevMonth - index)
.Finally, reverse the array to sort the days in increasing order.
remainingDays: Array.from( { length: 6 - currentDate.endOf('month').day() }, (_, index) => index + 1 )
To fill in the remaining days of our calendar, we can use one of two approaches:
-
Subtract from the Last Day of the Month:
- Subtract the value of the last day of the month (0 = Sunday to 6 = Saturday) from 6.
- Using this result, create an array of numbers in increasing order.
-
Total Days in the Calendar:
remainingDays: 42 - (firstDayOfCurrentMonth + currentDate.daysInMonth())
- Determine the total number of days you want to display in the calendar, for example, 42.
- Calculate the remaining days by subtracting the sum of the total offset and the total number of days in the current month from 42.
- If you're unsure why 42 is used, count the number of days in the hardcoded calendar above. You can choose the total number of days you want to display on your calendar.
Updating the days of the month.
Now that we have completed the calendarObjectGenerator
function, let's put it to use to make our calendar dynamic.
Create a state to hold the current date:
const [currentDate, setCurrentDate] = useState<Dayjs>(dayjs(Date.now()));
Import calendarObjectGenerator
into the Calendar.tsx
file and replace the hardcoded object assinged to the daysListGenerator
variable with calendarObjectGenerator(currentDate)
.
import dayjs, { Dayjs } from 'dayjs';
import backArrow from '../assets/images/back.svg';
import forwardArrow from '../assets/images/forward.svg';
import dayjs, { Dayjs } from 'dayjs';
import { calendarObjectGenerator } from '../helper/calendarObjectGenerator'; // add this line
import './style.css';
const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
export const Calendar = () => {
const [currentDate, setCurrentDate] = useState<Dayjs>(dayjs(Date.now())); // add line
const daysListGenerator = calendarObjectGenerator(currentDate); //add this line
... // other lines are the same as the content of Calendar.tsx above
}
Now your calendar should be updated and match the current month.
Enable click on month and year control arrows.
Even though, we have partly ensured that the calendar is not hardcoded anymore, and we will not get stuck in the past, there is still no way to peep into the future or travel back in time.
So our next challenge is to ensure we can go into the previous and future months and years.
That means we have to activate our arrows to respond to clicks.
Let’s create a function that will handle clicks on our arrows. We will call it dateArrowHandler. We will then use this function to control our months and years.
import dayjs, { Dayjs } from 'dayjs';
import backArrow from '../assets/images/back.svg';
import forwardArrow from '../assets/images/forward.svg';
import dayjs, { Dayjs } from 'dayjs';
import { calendarObjectGenerator } from '../helper/calendarObjectGenerator';
import './style.css';
const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
export const Calendar = () => {
const [currentDate, setCurrentDate] = useState<Dayjs>(dayjs(Date.now()));
const daysListGenerator = calendarObjectGenerator(currentDate);
//add this function
const dateArrowHandler = (date:Dayjs) => {
setCurrentDate(date);
};
return (
<div className='calendar__container'>
<div className='control__layer'>
<div className='month-year__layout'>
<div className='year__layout'>
<button
className='back__arrow'
//add line onClick={() => dateArrowHandler(currentDate.subtract(1, 'year'))}
>
<img src={backArrow} alt='back arrow' />
</button>
//add line <div className='title'>{currentDate.year()}</div>
<button
className='forward__arrow'
//add line onClick={() => dateArrowHandler(currentDate.add(1, 'year'))}
>
<img src={forwardArrow} alt='forward arrow' />
</button>
</div>
... // other lines are the same as the content of Calendar.tsx above
}
If you have been following, try making the months dynamic on your own before proceeding to the solution.
import dayjs, { Dayjs } from 'dayjs';
import backArrow from '../assets/images/back.svg';
import forwardArrow from '../assets/images/forward.svg';
import dayjs, { Dayjs } from 'dayjs';
import { calendarObjectGenerator } from '../helper/calendarObjectGenerator';
import './style.css';
const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
export const Calendar = () => {
const [currentDate, setCurrentDate] = useState<Dayjs>(dayjs(Date.now()));
const daysListGenerator = calendarObjectGenerator(currentDate);
//add this function
const dateArrowHandler = (date:Dayjs) => {
setCurrentDate(date);
};
return (
<div className='calendar__container'>
<div className='control__layer'>
<div className='month-year__layout'>
<div className='year__layout'>
<button
className='back__arrow'
//add line onClick={() => dateArrowHandler(currentDate.subtract(1, 'year'))}
>
<img src={backArrow} alt='back arrow' />
</button>
//add line <div className='title'>{currentDate.year()}</div>
<button
className='forward__arrow'
//add line onClick={() => dateArrowHandler(currentDate.add(1, 'year'))}
>
<img src={forwardArrow} alt='forward arrow' />
</button>
</div>
<div className='month__layout'>
<button
className='back__arrow'
//add line onClick={() => dateArrowHandler(currentDate.subtract(1, 'month'))}
>
<img src={backArrow} alt='back arrow' />
</button>
<div className='new-title'>
//add line {daysListGenerator.months[currentDate.month()]}
</div>
<button
className='forward__arrow'
//add line onClick={() => dateArrowHandler(currentDate.add(1, 'month'))}
>
<img src={forwardArrow} alt='forward arrow' />
</button>
</div>
... // other lines are the same as the content of Calendar.tsx above
}
Enable click on days.
Finally we want to allow the user to click on the days (numbers) on our calendar. We will be adding three main functions for this purspose. One for handling clicks on the prevMonthDays
, the second for handling clicks on the days
of the current month and the last one for handling clicks on the remainingDays
.
...
const handlePreviousMonthClick = (day: number) => {
const dayInPreviousMonth = currentDate.subtract(1, 'month').date(day);
setCurrentDate(dayInPreviousMonth);
};
const handleCurrentMonthClick = (day: number) => {
const dayInCurrentMonth = currentDate.date(day);
setCurrentDate(dayInCurrentMonth);
};
const handleNextMonthClick = (day: number) => {
const dayInNextMonth = currentDate.add(1, 'month').date(day);
setCurrentDate(dayInNextMonth);
};
...
As a little task for you, can you figure out where to put these functions in your code to enable clicks on the various days? Try to do that on your own. And once you are done, ensure your calendar looks somewhat like this:
That's all we need to do for this first part. I have provided the files containing everything we have written so far.
We will build upon this calendar in the subsequent parts. See you in the next one.
Summary.
Below is the whole code for what we have so far:
The complete css file is at the beginning.
// src/Calendar/Calendar.tsx
import dayjs, { Dayjs } from 'dayjs';
import backArrow from '../assets/images/back.svg';
import forwardArrow from '../assets/images/forward.svg';
import './style.css';
import { useState } from 'react';
import { calendarObjectGenerator } from '../helper/calendarObjectGenerator';
const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
export const Calendar = () => {
const [currentDate, setCurrentDate] = useState<Dayjs>(dayjs(Date.now()));
const daysListGenerator = calendarObjectGenerator(currentDate);
const dateArrowHandler = (date: Dayjs) => {
setCurrentDate(date);
};
const handlePreviousMonthClick = (day: number) => {
const dayInPreviousMonth = currentDate.subtract(1, 'month').date(day);
setCurrentDate(dayInPreviousMonth);
};
const handleCurrentMonthClick = (day: number) => {
const dayInCurrentMonth = currentDate.date(day);
setCurrentDate(dayInCurrentMonth);
};
const handleNextMonthClick = (day: number) => {
const dayInNextMonth = currentDate.add(1, 'month').date(day);
setCurrentDate(dayInNextMonth);
};
return (
<div className='calendar__container'>
<div className='control__layer'>
<div className='month-year__layout'>
<div className='year__layout'>
<button
className='back__arrow'
onClick={() => dateArrowHandler(currentDate.subtract(1, 'year'))}
>
<img src={backArrow} alt='back arrow' />
</button>
<div className='title'>{currentDate.year()}</div>
<button
className='forward__arrow'
onClick={() => dateArrowHandler(currentDate.add(1, 'year'))}
>
<img src={forwardArrow} alt='forward arrow' />
</button>
</div>
<div className='month__layout'>
<button
className='back__arrow'
onClick={() => dateArrowHandler(currentDate.subtract(1, 'month'))}
>
<img src={backArrow} alt='back arrow' />
</button>
<div className='new-title'>
{daysListGenerator.months[currentDate.month()]}
</div>
<button
className='forward__arrow'
onClick={() => dateArrowHandler(currentDate.add(1, 'month'))}
>
<img src={forwardArrow} alt='forward arrow' />
</button>
</div>
</div>
<div className='days'>
{weekDays.map((el, index) => (
<div key={`${el}-${index}`} className='day'>
{el}
</div>
))}
</div>
<div className='calendar__content'>
<div className={'calendar__items-list'}>
{daysListGenerator.prevMonthDays.map((el, index) => {
return (
<button
key={`${el}/${index}`}
className='calendar__item gray'
onClick={() => handlePreviousMonthClick(el)}
>
{el}
</button>
);
})}
{daysListGenerator.days.map((el, index) => {
return (
<div
key={`${index}-/-${el}`}
className='calendar__day'
onClick={() => handleCurrentMonthClick(el)}
>
<button
className={`calendar__item
${+el === +daysListGenerator.day ? 'selected' : ''}`}
>
<div className='day__layout'>
<div className='text'>{el.toString()}</div>
</div>
</button>
</div>
);
})}
{daysListGenerator.remainingDays.map((el, idx) => {
return (
<button
className='calendar__item gray'
key={`${idx}----${el}`}
onClick={() => handleNextMonthClick(el)}
>
{el}
</button>
);
})}
</div>
</div>
</div>
</div>
);
};
// src/helper/calendarObjectGenerator.ts
import dayjs, { Dayjs } from 'dayjs';
import LocaleData from 'dayjs/plugin/localeData';
dayjs.extend(LocaleData);
type GeneratedObjectType = {
prevMonthDays: number[];
days: number[];
remainingDays: number[];
day: number;
months: string[];
};
export const calendarObjectGenerator = (
currentDate: Dayjs
): GeneratedObjectType => {
const numOfDaysInPrevMonth = currentDate.subtract(1, 'month').daysInMonth();
const firstDayOfCurrentMonth = currentDate.startOf('month').day();
return {
days: Array.from(
{ length: currentDate.daysInMonth() },
(_, index) => index + 1
),
day: Number(currentDate.format('DD')),
months: currentDate.localeData().months(),
prevMonthDays: Array.from(
{ length: firstDayOfCurrentMonth },
(_, index) => numOfDaysInPrevMonth - index
).reverse(),
remainingDays: Array.from(
{ length: 6 - currentDate.endOf('month').day() },
(_, index) => index + 1
),
};
};
Posted on June 20, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.