Calculating the last day of a given weekday in the month

The Javacript date object is a thing of wonder. If you are scheduling events in Apps Script, you may want to do something like figure out when the last friday of each month is. 

Here's how to do it in JavaScript.

/**
 * return the date of the last day of the month
 * for a given weekday
 * @param {number} month the month (0-11)
 * @param {number} year the year - eg 2016 
 * @param {dayOfWeek} the day of weej (0-6 .. sun-sat)
 * @return {Date} the date of the last dayofweek
 */
function getLastWeekdayInMonth(year, month, dayOfWeek) {
  // get the last day of the month
  var date = new Date (year , month+1 , 0 , 12);
  // find out what day of week that is and adjust
  date.setDate (date.getDate() - (date.getDay()+7-dayOfWeek) % 7);
  return date;
}

And that's all there is to it. Let's walk through that.

  • Get the last day of the month required by selecting the month after, then using a date of 0. This will set the date to be one day before the 1st of the next month - in other words - the last day of this month.
  var date = new Date (year , month+1 , 0 , 12);

  • Adjust the date in the month, by subtracting the day of the week required, from the day of the week of the last day of the month. In case the day of the week of the last day of the month is smaller than the required day of the week, we can just add 7 to it and take the Mod of the final result.
date.setDate (date.getDate() - (date.getDay()+7-dayOfWeek) % 7);


Testing it. 


Here's the last day of the month for every weekday for 2015 & 2016.
[
[
["Sun 25-Jan-2015", "Mon 26-Jan-2015", "Tue 27-Jan-2015", "Wed 28-Jan-2015", "Thu 29-Jan-2015", "Fri 30-Jan-2015", "Sat 31-Jan-2015"],
["Sun 22-Feb-2015", "Mon 23-Feb-2015", "Tue 24-Feb-2015", "Wed 25-Feb-2015", "Thu 26-Feb-2015", "Fri 27-Feb-2015", "Sat 28-Feb-2015"],
["Sun 29-Mar-2015", "Mon 30-Mar-2015", "Tue 31-Mar-2015", "Wed 25-Mar-2015", "Thu 26-Mar-2015", "Fri 27-Mar-2015", "Sat 28-Mar-2015"],
["Sun 26-Apr-2015", "Mon 27-Apr-2015", "Tue 28-Apr-2015", "Wed 29-Apr-2015", "Thu 30-Apr-2015", "Fri 24-Apr-2015", "Sat 25-Apr-2015"],
["Sun 31-May-2015", "Mon 25-May-2015", "Tue 26-May-2015", "Wed 27-May-2015", "Thu 28-May-2015", "Fri 29-May-2015", "Sat 30-May-2015"],
["Sun 28-Jun-2015", "Mon 29-Jun-2015", "Tue 30-Jun-2015", "Wed 24-Jun-2015", "Thu 25-Jun-2015", "Fri 26-Jun-2015", "Sat 27-Jun-2015"],
["Sun 26-Jul-2015", "Mon 27-Jul-2015", "Tue 28-Jul-2015", "Wed 29-Jul-2015", "Thu 30-Jul-2015", "Fri 31-Jul-2015", "Sat 25-Jul-2015"],
["Sun 30-Aug-2015", "Mon 31-Aug-2015", "Tue 25-Aug-2015", "Wed 26-Aug-2015", "Thu 27-Aug-2015", "Fri 28-Aug-2015", "Sat 29-Aug-2015"],
["Sun 27-Sep-2015", "Mon 28-Sep-2015", "Tue 29-Sep-2015", "Wed 30-Sep-2015", "Thu 24-Sep-2015", "Fri 25-Sep-2015", "Sat 26-Sep-2015"],
["Sun 25-Oct-2015", "Mon 26-Oct-2015", "Tue 27-Oct-2015", "Wed 28-Oct-2015", "Thu 29-Oct-2015", "Fri 30-Oct-2015", "Sat 31-Oct-2015"],
["Sun 29-Nov-2015", "Mon 30-Nov-2015", "Tue 24-Nov-2015", "Wed 25-Nov-2015", "Thu 26-Nov-2015", "Fri 27-Nov-2015", "Sat 28-Nov-2015"],
["Sun 27-Dec-2015", "Mon 28-Dec-2015", "Tue 29-Dec-2015", "Wed 30-Dec-2015", "Thu 31-Dec-2015", "Fri 25-Dec-2015", "Sat 26-Dec-2015"]
],
[
["Sun 31-Jan-2016", "Mon 25-Jan-2016", "Tue 26-Jan-2016", "Wed 27-Jan-2016", "Thu 28-Jan-2016", "Fri 29-Jan-2016", "Sat 30-Jan-2016"],
["Sun 28-Feb-2016", "Mon 29-Feb-2016", "Tue 23-Feb-2016", "Wed 24-Feb-2016", "Thu 25-Feb-2016", "Fri 26-Feb-2016", "Sat 27-Feb-2016"],
["Sun 27-Mar-2016", "Mon 28-Mar-2016", "Tue 29-Mar-2016", "Wed 30-Mar-2016", "Thu 31-Mar-2016", "Fri 25-Mar-2016", "Sat 26-Mar-2016"],
["Sun 24-Apr-2016", "Mon 25-Apr-2016", "Tue 26-Apr-2016", "Wed 27-Apr-2016", "Thu 28-Apr-2016", "Fri 29-Apr-2016", "Sat 30-Apr-2016"],
["Sun 29-May-2016", "Mon 30-May-2016", "Tue 31-May-2016", "Wed 25-May-2016", "Thu 26-May-2016", "Fri 27-May-2016", "Sat 28-May-2016"],
["Sun 26-Jun-2016", "Mon 27-Jun-2016", "Tue 28-Jun-2016", "Wed 29-Jun-2016", "Thu 30-Jun-2016", "Fri 24-Jun-2016", "Sat 25-Jun-2016"],
["Sun 31-Jul-2016", "Mon 25-Jul-2016", "Tue 26-Jul-2016", "Wed 27-Jul-2016", "Thu 28-Jul-2016", "Fri 29-Jul-2016", "Sat 30-Jul-2016"],
["Sun 28-Aug-2016", "Mon 29-Aug-2016", "Tue 30-Aug-2016", "Wed 31-Aug-2016", "Thu 25-Aug-2016", "Fri 26-Aug-2016", "Sat 27-Aug-2016"],
["Sun 25-Sep-2016", "Mon 26-Sep-2016", "Tue 27-Sep-2016", "Wed 28-Sep-2016", "Thu 29-Sep-2016", "Fri 30-Sep-2016", "Sat 24-Sep-2016"],
["Sun 30-Oct-2016", "Mon 31-Oct-2016", "Tue 25-Oct-2016", "Wed 26-Oct-2016", "Thu 27-Oct-2016", "Fri 28-Oct-2016", "Sat 29-Oct-2016"],
["Sun 27-Nov-2016", "Mon 28-Nov-2016", "Tue 29-Nov-2016", "Wed 30-Nov-2016", "Thu 24-Nov-2016", "Fri 25-Nov-2016", "Sat 26-Nov-2016"],
["Sun 25-Dec-2016", "Mon 26-Dec-2016", "Tue 27-Dec-2016", "Wed 28-Dec-2016", "Thu 29-Dec-2016", "Fri 30-Dec-2016", "Sat 31-Dec-2016"]
]
]



Test Code

And here's how I created that. f
Logger.log(JSON.stringify([2015,2016].map(function(d) {
  return Array.apply(null,new Array(12)).map(function(e,i){
    return Array.apply(null,new Array(7)).map(function(f,j){
      return Utilities.formatDate(
        getLastWeekdayInMonth(d,i,j),
        "GMT","EEE dd-MMM-yyy");
    });
  })
})));


For more like this, see Google Apps Scripts snippets. Why not join our forumfollow the blog or follow me on twitter to ensure you get updates when they are available. 



Comments