Search code examples
javascripthtmlcalculationweek-number

How to calculate the amount of weeks between two week pickers


I created two week pickers (html input type="week"). I want to know how much weeks are in between the two weeks selected. These are my two html week pickers:

<input type="week" id="weekPicker1" required="required" min="1971-W01" max="2071-W52" value="2021-W01">
<input type="week" id="weekPicker2" required="required" min="1971-W01" max="2071-W52" value="2021-W52">

It returns 2021-W01 and 2021-W52 as a string.

In this case there are 52 weeks between the dates. But how can I make Javascript know this as well?

I have this Javascript code to make sure I get the years and weeks as numbers:

// Get dates in usable format.
let startDate = inputFields[0].value.split("-");
let startYear = Number(startDate[0]); //2021
let startWeek = Number(startDate[1].replace("W", "")); //1

let endDate = inputFields[1].value.split("-");
let endYear = Number(endDate[0]); //2021
let endWeek = Number(endDate[1].replace("W", "")); //52

But now, how do I calculate this?

I thought of this:

var yearDiff = endYear - startYear;
var amountOfWeeks = endWeek - startWeek;

amountOfWeeks += yearDiff * 52;

I think it nearly works, except not every year has 52 weeks (leap year). So how should I do this efficiently?

Edit:

I would like to see it in pure JS. No library or things like that. And I want the amount of weeks based on a calendar like this. So calculation based on a 7 day week will not give what I want.

In the end I need to use the weeks to do calculations. So using a date picker to select weeks still seems wrong. I also tested if I could do the calculation based on days etc, but it will give wrong results. Calculation I have to do: (selected length of weeks) : (max amount of weeks in year) * 200.


Solution

  • there are 52 weeks + 1 day in a year and 52 weeks + 2 days in a leap year. So your suggestion amountOfWeeks += yearDiff * 52; does not seem accurate. The below function converts the start and end year and weeks into miliseconds, subract and convert back into weeks. It should work with leap years. I haven't tested it though.

    function compareWeeks(startYear, startWeek, endYear, endWeek) {
        
        const start =
            new Date(startYear, 0).getTime() + startWeek * 7 * 24 * 60 * 60 * 1000
    
        const end = 
            new Date(endYear, 0).getTime() + endWeek * 7 * 24 * 60 * 60 * 1000
    
        const diff = Math.abs(end - start)
        const diffWeeks = diff / 1000 / 60 / 60 / 24 / 7
        return diffWeeks
    }
    

    Update for ISO-week-numbering year (your use case):
    According to the wikipedia, an ISO Year has either 52 or 53(ISO Leap Year) weeks. 53 when it starts or ends with Thirsday else 52. Checkout the below code:

    function weeksInBetween(startYear, startWeek, endYear, endWeek) {
        let diff = 0
        for (let i = startYear; i < endYear; i++) {
            const has53Weeks = isISOLeapYear(i)
            if (has53Weeks) {
                diff += 53
            } else {
                diff += 52
            }
        }
    
        return (diff += endWeek - --startWeek)
        /* 
            the '--startWeek' makes sure the starting week
            is not subtracted from the result, because you
            want the result to be inclusive'
            
        */
    }
    
    function isISOLeapYear(year) {
        const startsWithThursday =
            new Date(year, 0, 1).toString().split(' ')[0] === 'Thu'
        const endsWithThursday =
            new Date(year, 11, 31).toString().split(' ')[0] === 'Thu'
    
        if (startsWithThursday || endsWithThursday) {
            return true
        }
    
        return false
    }
    
    console.log(
        weeksInBetween(2020, 1, 2021, 52), // 105
        weeksInBetween(2009, 1, 2010, 52), // 105
        weeksInBetween(2021, 1, 2021, 52), // 52
        weeksInBetween(2021, 1, 2022, 52), // 104
        weeksInBetween(2021, 1, 2021, 1)   // 1
    )