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;

Facebooktwittergoogle_pluspinterestlinkedin

18 thoughts on “Last Monday of the Month

  1. 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. 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

  3. 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. 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. 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. 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. 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. 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. 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. 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"

  6. 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. 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. 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));
      }
      }

  7. 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));
    }
    }

Leave a Reply

Your email address will not be published. Required fields are marked *