Reconstructing a date from year, isoWeek and day with MomentJS

43 Views Asked by At

I am working on an application which saves events to a NoSQL database which is separated into collections using the year, week and day of the event. The events are saved in such a way that all events for a week are stored in the same collection.

The application needs to reconstruct the event date from the year, week and day. This logic has been in place for a number of years but I noticed today that it has issues.

The code for getting the year, week and day for a date:

function getYear(selectedDate) {
    return moment(selectedDate).startOf('isoWeek').year();
}
    
function getWeek(selectedDate) {
    return moment(selectedDate).startOf('isoWeek').isoWeek(); 
}

function getDay(selectedDate) {
    let day = moment(selectedDate).day();
    if(day === 0) day = 7;
    return day;
}

Function to reconstruct a date:

function getDateFromYearWeekDay(year, week, day) {
    return moment().year(year).isoWeek(week).startOf('isoWeek').day(day);
}

I found today (01-01-2024) that the above logic returns nonsensical dates for a given year, week and day. Adding a fixed reference date for the moment() constructor improves the logic so that the correct date is returned most of the time:

function getDateFromYearWeekDay(year, week, day) {
    return moment('2023-07-15').year(year).isoWeek(week).startOf('isoWeek').day(day);
}

I added some test cases to check this logic for all dates from 2020-01-01 to 2025-12-30 and the above is correct apart from for 15 dates:

Given, Returned, Year, Week, Day
2020-01-01, 2019-01-02, 2019, 1, 3
2020-01-02, 2019-01-03, 2019, 1, 4
2020-01-03, 2019-01-04, 2019, 1, 5
2020-01-04, 2019-01-05, 2019, 1, 6
2020-01-05, 2019-01-06, 2019, 1, 7
2024-12-30, 2024-01-01, 2024, 1, 1
2024-12-31, 2024-01-02, 2024, 1, 2
2025-01-01, 2024-01-03, 2024, 1, 3
2025-01-02, 2024-01-04, 2024, 1, 4
2025-01-03, 2024-01-05, 2024, 1, 5
2025-01-04, 2024-01-06, 2024, 1, 6
2025-01-05, 2024-01-07, 2024, 1, 7
2025-12-29, 2024-12-30, 2025, 1, 1
2025-12-30, 2024-12-31, 2025, 1, 2

The last three columns are the values from the getYear, getWeek and getDay functions - the 15 reconstructed values which do not match the inputs are wrong because the isoWeek being returned has been mapped to the previous year (so the week is 1 not 53).

Does anyone know:

  1. Why reconstructing the date is affected by the current date (i.e. why the seed is needed in the moment constructor)?
  2. How I can fix the logic so the week which is returned is unique and can be reconstructed back to the given date?
0

There are 0 best solutions below