goolius_boozler
goolius_boozler

Reputation: 253

How to get all dates between two dates given days of the week?

First off I know this question is very similar to this one: How to get all sundays/mondays/tuesdays between two dates?

What I'm asking is different though, I am trying to make a function where the day of week is a variable and there can be multiple, like this:

function findClassDays(daysOfWeek, firstDay, lastDay) {
  const classDays = [];

  return classDays;
}

The firstDay and lastDay are javascript dates and the daysOfWeek is an array that contains days of the week in the ddd moment format (ex. array could be ['Mon', 'Wed', 'Fri'].

How could I find all of the days between those two dates that fall on the daysOfWeek provided the days of the week are not known before and there could be multiple? I see on the linked question how it works when you know the day and it is only one but I can't find a solution if the array had any combination of days.

Upvotes: 1

Views: 528

Answers (2)

Aaron Plocharczyk
Aaron Plocharczyk

Reputation: 2832

Try this on for size:

function findClassDays(daysOfWeek, firstDay, lastDay) {
    var allDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

    //get indices of days provided
    var firstDayIndex = firstDay.getDay();
    var lastDayIndex = lastDay.getDay();

    //determine which days are acceptable
    var acceptableDays = [];
    for(var i = firstDayIndex; i != lastDayIndex; i = (i + 1) % allDays.length){
        acceptableDays[acceptableDays.length] = allDays[i];
    }
    acceptableDays[acceptableDays.length] = allDays[lastDayIndex];

    //return the intersection (overlap) of daysOfWeek and acceptableDays
    return daysOfWeek.filter(function(d){return acceptableDays.indexOf(d) > -1;});
}

OR, if you need the actual date objects and not just the days of the week as strings:

function findClassDays(daysOfWeek, firstDay, lastDay){
    var allDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];

    var matchingDates = [];
    while(firstDay.getDay() != lastDay.getDay()){
        //if firstDay is in daysOfWeek
        if(daysOfWeek.indexOf(allDays[firstDay.getDay()]) > -1){
            //add it to matchingDates
            matchingDates[matchingDates.length] = firstDay;
        }

        //increment first day
        firstDay = new Date(firstDay.getTime() + 1000 * 60 * 60 * 24);
    }
    //don't forget to check the last day as well
    if(daysOfWeek.indexOf(allDays[lastDay.getDay()]) > -1){
        matchingDates[matchingDates.length] = firstDay;
    }

    return matchingDates;
}

Upvotes: 1

StepUp
StepUp

Reputation: 38094

Based on answer of @JohnHartsock we can create the following function which

  • populates range of dates between firstDay and lastDay
  • filter dates based on of daysOfWeek

var days = {Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri:5, Sat:6};

function findClassDays(daysOfWeek, firstDay, lastDay) {
  let classDays = [];
  let rangeDates = getDates(new Date(firstDay), new Date(lastDay));
  classDays = rangeDates.filter(f => daysOfWeek.some((d, i) => days[d]== f.getDay()));
  return classDays;
}

function getDates(startDate, stopDate) {
  var dateArray = new Array();
  var currentDate = new Date(startDate);
  while (currentDate <= stopDate) {
      dateArray.push(new Date (currentDate));
      currentDate = currentDate.addDays(1);
  }
  return dateArray;
}

Date.prototype.addDays = function(days) {
  var date = new Date(this.valueOf());
  date.setDate(date.getDate() + days);
  return date;
}

console.log(findClassDays(['Mon', 'Wed', 'Fri'], '2019-12-01', '2019-12-15'));

Upvotes: 1

Related Questions