-1

Am just coding sth where I have to give out the count of weeks in every month of the year, so I need a function with a year- and a month-parameter to give out the amount of weeks in this month as a int.

like function getcalweeks(year, month) { xyz } where the output is just a variable that gives out the count of weeks in this month.

for example: function getcalweeks(2021, 1) { xyz } should return 4.

I looked through the web but just found some codes that wouldnt work, in the best one I found there were just 50 calendar weeks, not 52. (btw am in germany).

the code:

    function getWeeksInMonth(year, month) {
        const weeks = [],
          firstDate = new Date(year, month, 1),
          lastDate = new Date(year, month + 1, 0),
          numDays = lastDate.getDate();

        let dayOfWeekCounter = firstDate.getDay();

        for (let date = 1; date <= numDays; date++) {
          if (dayOfWeekCounter === 0 || weeks.length === 0) {
            weeks.push([]);
          }
          weeks[weeks.length - 1].push(date);
          dayOfWeekCounter = (dayOfWeekCounter + 1) % 7;
        }

        return weeks
          .filter((w) => !!w.length)
          .map((w) => ({
            start: w[0],
            end: w[w.length - 1],
            dates: w,
        }));
    
    }

If somebody could help me I would be really thankful for that.

best regards,

silliton

silliton
  • 3
  • 1
  • 3
  • Welcome to SO! I recommend new or returning contributors read [ask] for tips on forming questions in a way that best enables the community to provide helpful assistance. In this case, I would recommend a few things. Firstly, the question is slightly unclear-- from the description I do not understand the inputs nor the desired outputs. Secondly, you haven't provided any code showing what you have tried so far, which might help provide clarity. Making these changes might invite the community to provide you with guidance. Good luck, and happy coding! – Alexander Nied Sep 07 '21 at 00:32
  • thank you for your help! I just changed the title and given code in the text. – silliton Sep 07 '21 at 00:40
  • is it correct that you want a function that will accept year and month as parameter, and it will return the number of weeks for that year and month? – kvicera Sep 07 '21 at 00:46
  • Thanks for providing your code! This goes a long way towards making the problem answerable on the site! The only thing I would say now is missing is some example inputs and outputs explaining what is supposed to happen. For instance, are the months to be received as an index or a string of the month name? And you are expecting a number of weeks in the given month back? Every month in the year has four weeks and then some extra days-- are you expecting to receive some decimal number to be returned that expresses the fractional week from the additional days (for example `4.42857142857142`)? – Alexander Nied Sep 07 '21 at 00:46
  • well like I wrote, I am looking for the count of weeks in a given month in a given year. also there is a example where the year 2021 and the month 1/january were set as parameters in the function and the output is 4. but there are also months wherein are 5 months. At the end when all 12 months were used in the function there should be a total count of 52 weeks. Its like all about the calendar weeks – silliton Sep 07 '21 at 01:09
  • _"but there are also months wherein are 5 weeks"_ -- I would disagree on this point. A month can have 28, 29 (leap year), 30, or 31 days. There are no months with 35 days (which is 7x5, meaning five weeks)... Now, if you allow decimal months, then you could do this in a manner in which it would add up to (roughly) 52-- but it sounds like you are seeking integers but I am not clear how you are defining a "five week month," nor if the math of it is sound in regards to your requirements. – Alexander Nied Sep 07 '21 at 01:28
  • @AlexanderNied—a month can have 4 or 5 weeks in the same way a year can have 52 or 53 weeks. It depends on how you calculate weeks. – RobG Sep 07 '21 at 01:37
  • How do you calculate weeks in a month? There are 52 or 53 ISO weeks in a year, they start on the week with the first Thursday, i.e. the week where 4 or more days are in the year, ISO weeks start on Monday. Do you want to use the same rule for months? That way you can align week months with ISO weeks. – RobG Sep 07 '21 at 01:40
  • @RobG - Thanks, I do understand that there are _interpretations_ in which you could describe a month as having five weeks-- I am challenging the OP to define how they are doing their math and their inputs and outputs in order to understand their desired results. For instance, if you look at August and September 2021 they both have days in five different weeks, so you could say that they have ten weeks all together, but they have 61 total days and 61÷7≈8.7. I suspect it is exactly this sort of disagreement between two counting/summing methods that is causing the OP's issue. – Alexander Nied Sep 07 '21 at 01:59
  • Glad to see that the answer provided by @RobG worked for you-- please remember to upvote the answer and select it as your chosen answer, to both give credit to the answerer and provide direction to any other visitors to this post that than answer solved the problem. – Alexander Nied Sep 07 '21 at 21:25

1 Answers1

1

You can approach this in a similar manner to getting the week number of the year, e.g.

// Helper: return Monday of first week of given month. 
// Might be in previous month.
// First week of month is the one that contains the 4th of month
function getFirstMondayWeek(date) {
  // Get 4th of month
  let d = new Date(date.getFullYear(), date.getMonth(), 4);
  // Move to Monday on or before 4th
  d.setDate(d.getDate() - (d.getDay() || 7) + 1);
  return d;
}

// Helper: return number of days in month for Date
function getDaysInMonth(date) {
  return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
}

// Helper: return name of month for Date
function getMonthName(date) {
  return date.toLocaleString('default',{month:'long'});
}

// Return week number in month for given Date, 
// may be in last week of previous month.
// First day of week is Monday.
function getWeekOfMonth(date) {

  // Copy date with time set to 00:00:00
  let startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());

  // Get start of week
  let weekStart = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() - (startDate.getDay() || 7) + 1);
  
  // Get start of first week of month (might be in previous month)
  let testWeek = new Date(weekStart.getFullYear(), weekStart.getMonth(), 4);
  let monthStart = getFirstMondayWeek(testWeek);
  // Month start might be in previous month, so get right month name
  let monthName = getMonthName(testWeek);
  
  // If date is three days or less from end of month, might be in first week of next month
  if (startDate.getDate() > (getDaysInMonth(startDate) - 5)) {
    testWeek = new Date(startDate.getFullYear(), startDate.getMonth() + 1, 4);
    let nextMonthStart = getFirstMondayWeek(testWeek);
    
    // If in first week of next month, update related variables
    if (startDate >= nextMonthStart) {
      monthStart = nextMonthStart;
      monthName = getMonthName(testWeek);
    }
  }
  
  // Calc week number
  let weekNum = Math.floor(Math.round((weekStart - monthStart)/8.64e7/7)) + 1;
  return {weekNum, monthName};
}

// Examples
[new Date(2021, 2, 1), //  1 Mar 2021
 new Date(2021, 7, 1), //  1 Aug 2021
 new Date(2021, 7,30), // 30 Aug 2021
 new Date(2021,11,25), // 30 Aug 2021
 new Date(2022,10, 1), //  1 Nov 2021
 new Date(2022, 0, 2), //  2 Jan 2022
 new Date()            //  Today
].forEach(date => {
  let {weekNum, monthName} = getWeekOfMonth(date);
  console.log(`${date.toDateString()} is in ${monthName.slice(0,3)} week ${weekNum}`);
});

// Check that the sum of the weeks in the months
// of a year equals the weeks in the year
// 4th day from end (last day - 3) is always in last week
function getWeeksInMonth(date) {
  let testDate = new Date(date.getFullYear(), date.getMonth(), getDaysInMonth(date) - 3);
  return getWeekOfMonth(testDate).weekNum; 
}

function getWeeksInYear(date) {
  let year = date.getFullYear();
  let yearStart = getFirstMondayWeek(new Date(year, 0, 4));
  let yearEnd = new Date(year, 11, 28);
  yearEnd.setDate(yearEnd.getDate() - (yearEnd.getDay() || 7) + 1);
  return Math.round((yearEnd - yearStart)/8.64e7/7) + 1;
}

// Sum weeks in each month for year of date
function sumWeeksInMonths(date) {
  let d = new Date(date.getFullYear(), 0, 1);
  let sum = 0;
  for (let i=0; i<12; i++) {
    sum += getWeeksInMonth(d);
    d.setMonth(d.getMonth() + 1);
  }
  return sum;
}

for (let i=0, d=new Date(2020, 0),a,b; i<20; i++) {
  a = getWeeksInYear(d);
  b = sumWeeksInMonths(d);
  console.log(`${d.getFullYear()} has ${a} weeks` +
    `, month week sum is ${b}`);
  d.setFullYear(d.getFullYear() + 1);
}

The last part checks if the sum of weeks in months of a year equals the number of weeks in the year. Seems to work for the period 2020 to 2039.

RobG
  • 142,382
  • 31
  • 172
  • 209