# Last Monday of the Month

Closing this one off - there are solutions in here and thanks to all.

I thought I’d kluged this function together correctly but apparently not. I’m looking to be able to enter the 4th Monday of the month (ie today) as an example – and get true – getting false every other time – well, I’m getting false every time and I’ve tried a couple of variations.

Anyone feeling clever this morning (once it works – it is going into BigTimer which has just seen some other improvements).

function dayinmonth(weekday,n)
{
var date=new Date();
if (n > 0)
{
var first = new Date(date.Year, date.Month, 1);
return ((date.Day - first.Day)/ 7 == n - 1) && (date.DayOfWeek == weekday);

}
else
{
var last = new Date(date.Year, date.Month, 1).AddMonths(1).AddDays(-1);
return ((last.Day - date.Day) / 7 == (Math.Abs(n) - 1)) && (date.DayOfWeek == weekday);
}
}

msg.payload=dayinmonth(2,3); // assuming Monday day two – week 3 (0-3) – I’ve tried variations – I get FALSE every time
return msg;

## 18 thoughts on “Last Monday of the Month”

1. Juan C Galvez says:

Peter, I don't understand what you want to do when "n" is less than zero.

For "n > 0" you can code:

if (n > 0)
{
var first = new Date(date.getYear(), date.getMonth(), 1);
return ((Math.ceil((date.getDate() - first.getDate()) / 7) == n) && (date.getDay() == weekday - 1));

}

Assuming first week is 1 and first day (Sunday) is 1.

2. Juan C Galvez says:

I guess I understood what you wantes to do.

This would be the complete code:

var date=new Date();
if (n > 0)
{
var first = new Date(date.getYear(), date.getMonth(), 1);
return ((Math.ceil((date.getDate() - first.getDate()) / 7) == n) && (date.getDay() == weekday - 1));

}
else
{
var last = new Date(date.getYear(), date.getMonth() + 1, 0);
return (((last.getDate()- date.getDate()) / 7 == n) && (date.getDay() == weekday - 1));
}

Again, assuming first week being 1 and first day (Sunday) being 1

1. Peter Scargill says:

This one appears to work - just testing a couple of days.

3. Juan C Galvez says:

Peter, excuse me for so many replies

I think this code works better:

var date=new Date();
if (n > 0)
{
return ((Math.ceil((date.getDate()) / 7) == n) && (date.getDay() == weekday - 1));
}
else
{
var last = new Date(date.getFullYear(), date.getMonth() + 1, 0);
return (Math.ceil(last.getDate()/7) == Math.ceil(date.getDate()/7) && (date.getDay() == weekday - 1));
}

One more time, assuming first week is 1 and first day (Sunday) is 1

1. Peter Scargill says:

This version comes up with 2 errors on the return lines.... node-red function does not like it!

2. Peter Scargill says:

Can you try your second example - produced big red crosses for me....

3. Peter Scargill says:

Juan - I struggled with that second version of yours (which does work) - for ages - always getting errors. Then I noticed part of the code giving trouble - was the same as the original.

It turns out the MINUS sign was a special character - not an actual minus sign. Fixed that and it seems to work a treat - which saves me having to include a library - many thanks.

4. Darren says:

Today is the fifth Monday of the month which might explain your false results? This code works if I specify the fifth week:

const moment = require('moment');

function dayInMonth(weekday, n) {
let firstDayYouWant = moment().startOf('month').day(weekday); // e.g. this will get the Monday in the same week as the first day of the month (i.e. 26 Sept for 1 Oct)
if (firstDayYouWant.date() > 7) { firstDayYouWant.add(7,'d'); } // so we add 7 days to get the day you want within the month you want if it's last month
firstDayYouWant.add(7 * (n-1),'d').format(); // add the number of days we want based on the week (n)
return (moment().date() === firstDayYouWant.date()) // check if it's today
}

1. Darren says:

Sorry, I should have mentioned, it also works with either the day as a number or string, i.e. dayInMonth(1,5) or dayInMonth("Monday",5)

2. Peter Scargill says:

Hi there Darren - well, to test, I replaced the "require" as you can't do that in Node-Red - and taking into account this used day 0 for Sunday, it APPEARS to work... I'll just have to figure out how to force including moment into the NODE.... (only ever relied on one external component before).

But yes that seems to do it.. thanks.

1. Darren says:

I'm not too familiar with building node-red modules, but typically you'd perform a 'npm install moment --save' which would add the 'moment' module to your package.json file and install the module to the node_modules folder. I just tried dayInMonth(2,1) for first Tuesday on mine which seems to work...

1. Peter Scargill says:

A no Darren - I would and have done that for me - but for anyone else npn installing the node, I'd need to ensure it was automatically loaded for them - as it happens I'm storing this for posterity as the second version of Juan's code works - I've updated node-red-contrib-bigtimer accordingly and documented it. Thanks for all your help - well to everyone really.

5. Andi says:

Hi Pete

Had a simmilar question (every monday in a month) and found here a solution to my problem: http://stackoverflow.com/questions/9481158/how-to-get-the-4-monday-of-a-month-with-js

maybe you can adapt to your problem by comparing the last entry in the array to current date?

best regards
Andi

6. Lny says:

its not C but Lua. It might help:

startdayofmonth = 1
num2days = {"mo", "th", "we", "tr", "fr", "sa", "su"}

for i=1,31 do
actlday = (startdayofmonth+i-2)%7+1
print(i-actlday, num2days[actlday])
pirnt

weekday is the n-th one in the month if

(i-actlday > (n-1)*7) and (i-actlday < n*7) and ( num2days[actlday] == "weekday"

7. Peter Scargill says:

Argh, having failed to get Juan's second version to work - I was just saying how well the first version worked - until I tried this morning (3,1) i.e first Tuesday of the month... failed. 🙁

1. Alessandro Malatesta says:

Hi Pete, what about something like this:
return (Math.max(Math.ceil((date.getDate() - first.getDate()) / 7), 1) == n) && (date.getDay() == weekday - 1);

...of course just a compact version of
return (date.getDate() != first.getDate() ? Math.ceil((date.getDate() - first.getDate()) / 7) == n : n == 1) && (date.getDay() == weekday - 1);

2. Juan C Galvez says:

Peter, I don't know what if wrong with the third script and node red. Probably Math.ceil.

I replaced it with pauseInt(). Please try this code.

function dayinmonth(weekday,n)
{
var date=new Date(parseInt(document.all["year1"].value), parseInt(document.all["month1"].value - 1), parseInt(document.all["day1"].value));
if (n > 0)
{
return ((parseInt((date.getDate()) / 7) == n - 1) && (date.getDay() == weekday - 1));
}
else
{
var last = new Date(date.getFullYear(), date.getMonth() + 1, 0);
return (parseInt(last.getDate()/7) == parseInt(date.getDate()/7) && (date.getDay() == weekday - 1));
}
}

8. Juan C Galvez says:

I``m sorry. Wrong code. That is the one I tested in a browser. This is it:

function dayinmonth(weekday,n)
{
var date=new Date();
if (n > 0)
{
return ((parseInt((date.getDate()) / 7) == n – 1) && (date.getDay() == weekday – 1));
}
else
{
var last = new Date(date.getFullYear(), date.getMonth() + 1, 0);
return (parseInt(last.getDate()/7) == parseInt(date.getDate()/7) && (date.getDay() == weekday – 1));
}
}