1
\$\begingroup\$

I am working on a calendar widget for a project. For any given date, I need to build a 2D array representing the "Month" that the date falls in, where the rows represent weeks in the month and the cells in those rows are individual days. The weeks must start on Monday, and if the month does not start on a Monday, it must "backfill" in the days from the previous month. Similarly, if the last week in the month isn't "full" because it didn't end on a Sunday, fill the last week with the beginning of the following month.

For example, let's use today, May 26th of 2016. Given an input of new Date(2016, 04, 26), I would want an output of an array with 6 elements (the weeks), each element itself an array containing 7 date objects (the days). Because May started on a Sunday, the first date in the first week would actually be April 25th (the previous Monday). Because May ends on a Tuesday, the last date in the last week would be June 5th (the following Sunday).

function getCalendarMatrix(date){
 var calendarMatrix = []
 var startDay = new Date(date.getFullYear(), date.getMonth(), 1)
 var lastDay = new Date(date.getFullYear(), date.getMonth()+1, 0)
 // Modify the result of getDay so that we treat Monday = 0 instead of Sunday = 0
 var startDow = (startDay.getDay() + 6) % 7;
 var endDow = (lastDay.getDay() + 6) % 7;
 // If the month didn't start on a Monday, start from the last Monday of the previous month
 startDay.setDate(startDay.getDate() - startDow);
 // If the month didn't end on a Sunday, end on the following Sunday in the next month
 lastDay.setDate(lastDay.getDate() + (6-endDow));
 var week = []
 while(startDay <= lastDay){
 week.push(new Date(startDay));
 if (week.length === 7){
 calendarMatrix.push(week);
 week = []
 }
 startDay.setDate(startDay.getDate() + 1)
 }
 return calendarMatrix;
}

My code seems like it's working well, but I'm seeking input on any flaws this might have or how I could go about this in a "better" way.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked May 26, 2016 at 20:03
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I have only minor comments.


This logic appears twice, do is a good candidate to extract to a helper function to eliminate duplicate code:

(startDay.getDay() + 6) % 7;

Instead of this:

// If the month didn't start on a Monday, start from the last Monday of the previous month
startDay.setDate(startDay.getDate() - startDow);

It would be slightly more readable to move this code into a helper function with a descriptive name, for example:

function getStartingMonday(startDay, startDow) {
 // If the month didn't start on a Monday, start from the last Monday of the previous month
 return new Date(startDay.getDate() - startDow));
}

This way, the code in the caller will be shorter, and the implementation detail is not really important, it's enough to know that the returned date is the sizing day and it's a Monday.

The same goes for getting the last Sunday.


You're using semicolons inconsistently, sometimes omitting it. It would be better to use a consistent style, for example put it always.


The === is redundant here:

 if (week.length === 7){

You create week yourself, inside the function, so you know it's an array, and therefore must have an integer .length property, so a simple == is enough.

answered May 26, 2016 at 20:35
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.