Reputation: 614
I'm building a chart where the x-axis should be the four weeks of a month. I would like to display only the four Mondays of that month.
I already have the currentMonth
and the currentYear
variables, and I know how to get the first day of the month. All I need is to get the four Mondays of a month in an array. And all of this in the same JavaScript file.
I'm pretty lost within my programming logic, and I've seen plenty of solutions that don't fit my use case.
Right now, I have:
var date = new Date();
var currentYear = date.getFullYear();
var currentMonth = date.getMonth();
var firstDayofMonth = new Date(currentYear, currentMonth, 1);
var firstWeekDay = firstDayofMonth.getDay();
but I would like to have something like this:
var myDates = [
new Date(firstMonday),
new Date(secondMonday),
new Date(thirdMonday),
new Date(fourthMonday),
];
Upvotes: 15
Views: 26053
Reputation: 9333
I took Jake's code and generalized it to get the next N
occurrences of a particular schedule. (e.g. "Get me the next 10 instances of 2nd Mondays and 1st and 3rd Wednesdays.")
schedule
is an object with keys for day-of-week whose values are
an array of the incident within a month that the DoW falls.
count
is optional (defaults to 6) and represents how many items to show.
nextNthMdays({1: [1, 3]})
nextNthMdays({3: [2], 5: [2]})
nextNthMdays({4: [-1]})
function nextNthMdays(schedule, count) {
var d = new Date(),
month = 999,
nthInMonth,
dates = [];
if (count == undefined) {
count = 6;
}
// start at the beginning of the month
d.setDate(1);
// Iterate until we have enough
while (dates.length < count) {
var day = d.getDay();
// Reset counters each month
if (d.getMonth() !== month) {
month = d.getMonth();
nthInMonth = Object.keys(schedule).reduce(function (obj, x) {
obj[x] = 0;
return obj;
}, {});
}
// When you reach an interesting weekday
if (day in schedule) {
// Increment its counter
nthInMonth[day]++;
// If it's after today
if (d > new Date()) {
// and its counter matches
if (schedule[day].indexOf(nthInMonth[day]) !== -1) {
// Add it
dates.push(new Date(d.getTime()));
}
// or if we want the last one
else if (schedule[day].indexOf(-1) !== -1) {
// verify that 7 days from then is a different month
var sevenAway = new Date(d);
sevenAway.setDate(sevenAway.getDate() + 7);
if (d.getMonth() !== sevenAway.getMonth()) {
// Add it
dates.push(new Date(d.getTime()));
}
}
}
}
// Move on to the next day
d.setDate(d.getDate() + 1);
}
return dates;
}
Expand the snippet to run some examples.
// `schedule` is an object with keys
// for day-of-week whose values are
// an array of the incident within
// a month that the DoW falls.
//
// keys can include numbers from
// 1-5, and -1 for "last."
// items in a value array can include
// numbers from 0-6, where 0 is
// Sunday.
//
// `count` is optional (defaults to 6)
// and represents how many items to
// show.
//
// First and third Mondays would be
// nextNthMdays({1: [1, 3]})
// Second Wed and Fri would be
// nextNthMdays({3: [2], 5: [2]})
// Last Thursdays would be
// nextNthMdays(4: [-1])
function nextNthMdays(schedule, count) {
var d = new Date(),
month = 999,
nthInMonth,
dates = [];
if (count == undefined) {
count = 6;
}
// start at the beginning of the month
d.setDate(1);
// Iterate until we have enough
while (dates.length < count) {
var day = d.getDay();
// Reset counters each month
if (d.getMonth() !== month) {
month = d.getMonth();
nthInMonth = Object.keys(schedule).reduce(function (obj, x) {
obj[x] = 0;
return obj;
}, {});
}
// When you reach an interesting weekday
if (day in schedule) {
// Increment its counter
nthInMonth[day]++;
// If it's after today
if (d > new Date()) {
// and its counter matches
if (schedule[day].indexOf(nthInMonth[day]) !== -1) {
// Add it
dates.push(new Date(d.getTime()));
}
// or if we want the last one
else if (schedule[day].indexOf(-1) !== -1) {
// verify that 7 days from then is a different month
var sevenAway = new Date(d);
sevenAway.setDate(sevenAway.getDate() + 7);
if (d.getMonth() !== sevenAway.getMonth()) {
// Add it
dates.push(new Date(d.getTime()));
}
}
}
}
// Move on to the next day
d.setDate(d.getDate() + 1);
}
return dates;
}
console.log('Next third Wednesdays');
console.log(nextNthMdays({3: [3],}));
console.log('Next first and third Mondays');
console.log(nextNthMdays({1: [1, 3],}, 4));
console.log('Next second Wed/Fridays');
console.log(nextNthMdays({3: [2], 5: [2],}, 3));
console.log('Next "Last Thursdays of the month"');
console.log(nextNthMdays({4: [-1],}, 3));
Upvotes: 0
Reputation: 174
For whoever may need, this is a general function to get every monday, tuesday, etc
getDatesOfDayOfWeek (year, month, dayOfWeek) {
const initialDate = new Date(year, month, 1);
const datesOfDayOfWeek = [];
while (initialDate.getDay() !== dayOfWeek) {
initialDate.setDate(initialDate.getDate() + 1);
}
while (initialDate.getMonth() === month) {
const nextDate = new Date(initialDate.getTime());
datesOfDayOfWeek.push(nextDate.getDate());
initialDate.setDate(initialDate.getDate() + 7);
}
return datesOfDayOfWeek;
}
Upvotes: 1
Reputation: 122906
This would return the fourth last monday of month [m] in year [y]
function lastmonday(y,m) {
var dat = new Date(y+'/'+m+'/1')
,currentmonth = m
,firstmonday = false;
while (currentmonth === m){
firstmonday = dat.getDay() === 1 || firstmonday;
dat.setDate(dat.getDate()+(firstmonday ? 7 : 1));
currentmonth = dat.getMonth()+1;
}
dat.setDate(dat.getDate()-7);
return dat;
}
// usage
lastmonday(2012,3); //=>Mon Mar 26 2012 00:00:00 GMT+0200
lastmonday(2012,2) //=>Mon Feb 27 2012 00:00:00 GMT+0100
lastmonday(1997,1) //=>Mon Jan 27 1997 00:00:00 GMT+0100
lastmonday(2012,4) //=>Mon Apr 30 2012 00:00:00 GMT+0200
To be more generic, this will deliver the last any weekday of a month:
function lastDayOfMonth(y,m,dy) {
var days = {sun:0,mon:1,tue:2,wed:3,thu:4,fri:5,sat:6}
,dat = new Date(y+'/'+m+'/1')
,currentmonth = m
,firstday = false;
while (currentmonth === m){
firstday = dat.getDay() === days[dy] || firstday;
dat.setDate(dat.getDate()+(firstday ? 7 : 1));
currentmonth = dat.getMonth()+1 ;
}
dat.setDate(dat.getDate()-7);
return dat;
}
// usage
lastDayOfMonth(2012,2,'tue'); //=>Tue Feb 28 2012 00:00:00 GMT+0100
lastDayOfMonth(1943,5,'fri'); //=>Fri May 28 1943 00:00:00 GMT+0200
Upvotes: 4
Reputation: 15042
The following function
will return all Mondays for the current month:
function getMondays() {
var d = new Date(),
month = d.getMonth(),
mondays = [];
d.setDate(1);
// Get the first Monday in the month
while (d.getDay() !== 1) {
d.setDate(d.getDate() + 1);
}
// Get all the other Mondays in the month
while (d.getMonth() === month) {
mondays.push(new Date(d.getTime()));
d.setDate(d.getDate() + 7);
}
return mondays;
}
Upvotes: 42