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:
- Why reconstructing the date is affected by the current date (i.e. why the seed is needed in the moment constructor)?
- How I can fix the logic so the week which is returned is unique and can be reconstructed back to the given date?