so I have two solutions to offer
1 quite simple (making use of the Date object - basically doing what barrycarter suggested in a comment)
Creating a Date object for the first of our desired year ... and then based on which day of the week that is, adjusting the date to end up with the first monday of the first week of the year
As you might notice when running the code. The answers are off by (mostly 1 hour) - I don't know why, and so far I only encountered this when running my code on here - in VS Code and several Online JS Playgrounds the code returned exactly what I intended it to return. So yeah there's that.
(date.getDay() + 6) % 7 // 0 - 6 for Mon - Sun
function getDateOfFirstDayOfFirstWeek(year) {
const date = new Date(year, 0, 1)
if ((date.getDay() + 6) % 7 === 0) return date
if ((date.getDay() + 6) % 7 < 4) {
date.setDate(date.getDate() - (date.getDay() + 6) % 7)
return date
} else {
date.setDate(8 - (date.getDay() + 6) % 7)
return date
}
}
console.log(getDateOfFirstDayOfFirstWeek(2020))
console.log(getDateOfFirstDayOfFirstWeek(2021))
console.log(getDateOfFirstDayOfFirstWeek(2022))
console.log(getDateOfFirstDayOfFirstWeek(2100))
console.log(getDateOfFirstDayOfFirstWeek(3567))
console.log(getDateOfFirstDayOfFirstWeek(2002))
console.log(getDateOfFirstDayOfFirstWeek(1845))
the 2nd option is a tad more complicated (and I mostly wrote it just for fun - but I'll share it nonetheless maybe there's something you can take away from it)
Since I did not once use the Date object the missing hour problem does not happen here. (I want to say again I've only encountered the missing hour on stackoverflow so far - so you should be fine using the above function)
When we look at neighboring years we can see, that the date changes by 1 per year (and 2 if the year is a leap year) - so what we do is ... starting at an arbitrary point (I have chosen the year 2020 with the 30th of Dec being the Monday) we calculate the next/previous year (by adding/subtracting 1 or 2 from our date) ... we do that so long until we reach our desired year ...
until the very end (where we convert everything into day/month/year) we store our date in a value x (which can become any integer)
x % 7 = 0 -> 29/12
x % 7 = 1 -> 30/12
x % 7 = 2 -> 31/12
x % 7 = 3 -> 01/01
x % 7 = 4 -> 02/01
x % 7 = 5 -> 03/01
x % 7 = 6 -> 04/01
This thing here is to add a proper modulo method ... because % in Javascript only returns the remainder not modulo (which matters when using negative values) see this answer for more information on that: https://stackoverflow.com/a/4467559/19529102 (that's also where I got this little bit of code from)
Number.prototype.mod = function (n) {
"use strict";
return ((this % n) + n) % n;};
Number.prototype.mod = function (n) {
"use strict";
return ((this % n) + n) % n;
};
function isLeapYear(year) {
if (year % 4 !== 0) return false;
if (year % 100 !== 0) return true;
if (year % 400 !== 0) return false;
return true
}
function getFirstDayForNplus1(year, value) {
if (isLeapYear(year)) return [year + 1, value - 2]
return [year + 1, value - 1]
}
function getFirstDayForNminus1(year, value) {
if (isLeapYear(year - 1)) return [year - 1, value + 2]
return [year - 1, value + 1]
}
function getDateOfFirstDayOfFirstWeek(year) {
if (year < 1583) return
let baseLine = [2020, 1]
if (year > baseLine[0]) {
while (baseLine[0] !== year) {
baseLine = getFirstDayForNplus1(...baseLine);
}
} else {
while (baseLine[0] !== year) {
baseLine = getFirstDayForNminus1(...baseLine);
}
}
const month = baseLine[1].mod(7) < 2 ? 12 : 1;
const day = (baseLine[1].mod(7) + 29) % 31 || 1
const retYear = month === 12 ? baseLine[0] - 1 : baseLine[0]
return day + "/" + month + "/" + retYear
}
console.log(getDateOfFirstDayOfFirstWeek(2020))
console.log(getDateOfFirstDayOfFirstWeek(2021))
console.log(getDateOfFirstDayOfFirstWeek(2022))
console.log(getDateOfFirstDayOfFirstWeek(2100))
console.log(getDateOfFirstDayOfFirstWeek(3567))
console.log(getDateOfFirstDayOfFirstWeek(2002))
console.log(getDateOfFirstDayOfFirstWeek(1845))
since you have a year, month, day variable in the function, you could easily create a Date object using that function (if needed)