Skip to content

Instantly share code, notes, and snippets.

@willmanduffy
Last active February 14, 2022 13:44
Show Gist options
  • Select an option

  • Save willmanduffy/a62a88cb2b3902e09d8f333906a65032 to your computer and use it in GitHub Desktop.

Select an option

Save willmanduffy/a62a88cb2b3902e09d8f333906a65032 to your computer and use it in GitHub Desktop.
Calendar Generation
import {
endOfMonth,
getDay,
getDaysInMonth,
getWeeksInMonth,
startOfMonth,
} from 'date-fns';
import takeRight from 'lodash/takeRight';
const NUMBER_OF_CALENDAR_ROWS = 6;
export const daysOfCurrentMonth = (calendarDate: Date): number[] => {
const numberOfDaysInMonth = getDaysInMonth(calendarDate);
// Generate an array of the all of days in the month:
// ex. [1, 2, 3, 4, ..., 31]
return Array.from(Array(numberOfDaysInMonth).keys()).map((day) => day + 1);
};
export const daysOfPreviousMonth = (
calendarDate: Date,
previousMonth: Date
): number[] => {
const numberOfDaysInPreviousMonth = getDaysInMonth(previousMonth);
// Find the number of days in the week before the first day of the current calendar month. For
// example, if the first of the month is on a Tuesday then we will return 2 (referring to Sunday
// and Monday).
const daysBeforeFirstDayOfMonth = getDay(startOfMonth(calendarDate));
// Generate an array of the last days of the previous month using the daysBeforeFirstDayOfMonth
// If the previous month has 31 days and daysBeforeFirstDayOfMonth is 2 we will return [30, 31]
const allDaysOfPreviousMonth = Array.from(
Array(numberOfDaysInPreviousMonth).keys()
).map((day) => day + 1);
return takeRight(allDaysOfPreviousMonth, daysBeforeFirstDayOfMonth);
};
export const daysOfNextMonth = (calendarDate: Date): number[] => {
let daysAfterLastDayOfMonth: number;
const numberOfWeeksInCurrentMonth = getWeeksInMonth(calendarDate);
const lastDayOfTheMonth = endOfMonth(calendarDate);
// Get the number of days in the week after the last day of the month
// The 6 is confusing, but it's just working off of week indicies that start at 0, so it's the
// representation of 7 days in the week: 0, 1, 2, 3, 4, 5, 6
daysAfterLastDayOfMonth = 6 - getDay(lastDayOfTheMonth);
// We always want to display 6 rows in our calendar. Add the number of days that's needed to fill
// out 6 rows if we have not done so yet.
if (numberOfWeeksInCurrentMonth !== NUMBER_OF_CALENDAR_ROWS) {
const weeksToAdd = NUMBER_OF_CALENDAR_ROWS - numberOfWeeksInCurrentMonth;
daysAfterLastDayOfMonth = daysAfterLastDayOfMonth + weeksToAdd * 7;
}
// Generate an array of the first days of the next month. If we want to display the first 8 days
// of the next month we would return [1, 2, 3, 4, 5, 6, 7, 8]
return Array.from(Array(daysAfterLastDayOfMonth).keys()).map(
(day) => day + 1
);
};
const Calendar = () => (
<div className="grid grid-cols-7 justify-items-center gap-0.5">
{daysOfPreviousMonth(calendarDate, previousMonth).map((day) => (
<Day calendarDate={calendarDate} day={day} classes="text-gray-400" />
))}
{daysOfCurrentMonth(calendarDate).map((day) => (
<Day
calendarDate={calendarDate}
selectedDate={selectedDate}
day={day}
/>
))}
{daysOfNextMonth(calendarDate).map((day) => (
<Day calendarDate={calendarDate} day={day} classes="text-gray-400" />
))}
</div>
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment