简体   繁体   中英

How do I get the first day of the first week in a given year, in javascript?

I think these are the correct conditions:

  • Week 1 is the first week with at least 4 days of the new year.
  • Week 53 happens when the new years' first day is a Thursday OR it's a leapyear and the year' first day is a Wednesday.

Examples:

Year (Input) First day of first week (return wanted)
2020 (Leap Year) 30/12/2020
2021 04/01/2021
2022 03/01/2022
2023 02/01/2023
2024 (Leap Year) 01/01/2024
2025 30/12/2025
2026 (Starts on a wednesday, in a year of 53 weeks) 29/12/2026

The year 2026 is a rare case, which happens in year 2032, 2037, 2043...

I believe I've 'solved' half the problem here:

let numOfWeeks = 52;

if (((0 == year % 4 && 0 != year % 100) || 0 == year % 400) && 'first day of first week is a wednesday') {
    numOfWeeks = 53;
} else if ('first day of first week is a thursday') {
    numOfWeeks = 53
}

But I can't for the life of me figure out how to get the first day of the first week in a given year.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM