1

I need to get the first day of the week by using the week number (weeks starting on Monday). I found this piece of code here: https://stackoverflow.com/a/46343917/13498210. However, the code doesn't seem to work. For example, inputing week 34 returns the date 08-22 (the sunday of the previous week) instead of the correct 08-23.

My question is, is it safe to just "add" one day to the result? Or will that create bugs?

function getFirstMondayOfWeek(weekNo) {
    var firstMonday = new Date(new Date().getFullYear(), 0, 4, 0, 0, 0, 0);

    while (firstMonday.getDay() != 1) {
        firstMonday.setDate(firstMonday.getDate() - 1);
    }
    if (1 <= weekNo && weekNo <= 52)
        return firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));

    firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));
    if (weekNo = 53 && firstMonday.getDate() >= 22 && firstMonday.getDate() <= 28)
        return firstMonday; //JUST ADD A DAY HERE
    return null;
}
hampani
  • 129
  • 11

3 Answers3

2

The code works but has some issues.

return firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));

returns a time value (the return from setDate). To return a Date, it should be two separate statements:

firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));
return firstMonday;

Also, looping to find the first Monday is inefficient. It can be calculated from the initial value of firstMonday. Checking for week 53 can also be simplified and the input week number should be tested to ensure it's from 1 to 53.

Lastly, the first couple of days of January may be in the last week of the previous year, so in week 53 getting week 53 with the default year may return the start of week 53 of the wrong year (or undefined, see below). It would be better if the function took two arguments: weekNo and year, where year defaults to the current year and weekNo to the current week.

/* Return date for Monday of supplied ISO week number
 * @param {number|string} weekNo - integer from 1 to 53
 * @returns {Date} Monday of chosen week or
 *                 undefined if input is invalid
 */
function getFirstMondayOfWeek(weekNo) {
  let year = new Date().getFullYear();

  // Test weekNo is an integer in range 1 to 53
  if (Number.isInteger(+weekNo) && weekNo > 0 && weekNo < 54) {

    // Get to Monday of first ISO week of year
    var firstMonday = new Date(year, 0, 4);
    firstMonday.setDate(firstMonday.getDate() + (1 - firstMonday.getDay())); 

    // Add required weeks
    firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));

    // Check still in correct year (e.g. weekNo 53 in year of 52 weeks)
    if (firstMonday.getFullYear() <= year) {
      return firstMonday;
    }
  }
  // If not an integer or out of range, return undefined
  return;
}

// Test weeks, there is no week 53 in 2021
[0, '1', 34, 52, 53, 54, 'foo'].forEach(weekNo => {
  let date = getFirstMondayOfWeek(weekNo);
  console.log(`Week ${weekNo}: ${date? date.toDateString() : date}`);
});

Where an invalid week number is supplied you have a choice of throwing an error, returning undefined or returning an invalid Date:

return new Date(NaN);
RobG
  • 142,382
  • 31
  • 172
  • 209
1

How does this look ?

HTML

<div id="datediv"></div>

JS

var dateDiv=document.getElementById('datediv')

function getDateOfWeek(w, y) {
  let date = new Date(y, 0, (1 + (w - 1) * 7)); // Elle's method
  date.setDate(date.getDate() + (1 - date.getDay())); // 0 - Sunday, 1 - Monday etc
  return date
}

var firstMonday = getDateOfWeek(36,2021)
dateDiv.innerText=firstMonday
  
fuzzybear
  • 2,325
  • 3
  • 23
  • 45
  • Please post working code here. A good answer should explain why the OP has their issue and how your code fixes it. – RobG Aug 28 '21 at 09:44
  • People shouldn't have to go to another site to see the code. It also makes commenting on the code more difficult, and links rot. – RobG Aug 28 '21 at 10:27
  • I get your view RobG but I don't mind clicking a link it helps to proliferate code out there IMHO, what if SO shutdown, etc, there are swings and roundabouts to both I guess? – fuzzybear Aug 28 '21 at 10:31
  • Like [Gary](https://youtu.be/aplSQGHPmvI?t=38), SO will never die… – RobG Aug 30 '21 at 04:03
1

Instead of trying to set the day, month, year, ect.

You could :

  • Create a new Date that is the start of the year.
  • Append the number of milliseconds to get to the weekNo.
  • Remove milleseconds to get to Monday from Friday.
  • Then convert back to a Date object.

Demo:

function getFirstMondayOfWeek(weekNo) {
  return new Date(new Date(new Date().getFullYear(), 0).getTime() + weekNo * 604800000 - 345600000);
}

for (let i = 1; i <= 52; i++)
  console.log(`Week number ${i}:`, getFirstMondayOfWeek(i).toDateString());
lejlun
  • 4,140
  • 2
  • 15
  • 31
  • Adding and removing days as milliseconds is not reliable as not all days are 24 hours long were daylight saving is observed. – RobG Aug 28 '21 at 09:59
  • @RobG I'm not sure I get what you mean. Could you give an example where this function would fail? – lejlun Aug 28 '21 at 10:07
  • Over a daylight saving boundary where a day may be 23 or 25 hours long (or 23.5 or 24.5 if the DST offset is 30 minutes). – RobG Aug 28 '21 at 10:26