Skip to content

Commit c84fceb

Browse files
dr-itzspike-rabbit
authored andcommitted
fix(datepicker): fix incorrect week numbers
1 parent 6d7be2e commit c84fceb

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

projects/element-ng/datepicker/date-time-helper.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
getDateSameOrBetween,
1313
getNamedFormat,
1414
getWeekEndDate,
15+
getWeekOfYear,
1516
getWeekStartDate,
1617
isSameDate,
1718
parseDate,
@@ -316,4 +317,19 @@ describe('date time helper', () => {
316317
});
317318
});
318319
});
320+
321+
it('getWeekOfYear', () => {
322+
expect(getWeekOfYear(new Date(2022, 0, 1), 'saturday')).toBe(1);
323+
expect(getWeekOfYear(new Date(2022, 2, 6), 'monday')).toBe(9);
324+
expect(getWeekOfYear(new Date(2022, 2, 6), 'sunday')).toBe(10);
325+
expect(getWeekOfYear(new Date(2022, 2, 12), 'sunday')).toBe(10);
326+
expect(getWeekOfYear(new Date(2022, 11, 26), 'monday')).toBe(52);
327+
expect(getWeekOfYear(new Date(2022, 11, 26), 'sunday')).toBe(52);
328+
expect(getWeekOfYear(new Date(2023, 0, 1), 'monday')).toBe(52);
329+
expect(getWeekOfYear(new Date(2023, 0, 1), 'sunday')).toBe(1);
330+
expect(getWeekOfYear(new Date(2023, 0, 4), 'monday')).toBe(1);
331+
expect(getWeekOfYear(new Date(2023, 0, 4), 'sunday')).toBe(1);
332+
expect(getWeekOfYear(new Date(2025, 2, 31), 'monday')).toBe(14);
333+
expect(getWeekOfYear(new Date(2025, 2, 31), 'sunday')).toBe(14);
334+
});
319335
});

projects/element-ng/datepicker/date-time-helper.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,9 @@ export const getFirstDayInMonth = (year: number, month: number): Date =>
107107
new Date(year, month - 1, 1);
108108

109109
/**
110-
* Gets the week number of the specified date.
111-
* Week number according to the ISO-8601 standard, weeks starting on Monday.
110+
* Returns the ISO-8601 week number for the user's week containing the specified date.
111+
* ISO-8601 weeks always start on Monday. When the user's week starts on Sunday or Saturday,
112+
* the date is adjusted to find the corresponding ISO week (based on the Thursday rule).
112113
* The first week of a year is the week that contains the first Thursday of the year (='First 4-day week').
113114
* The highest week number in a year is either 52 or 53.
114115
*
@@ -117,17 +118,23 @@ export const getFirstDayInMonth = (year: number, month: number): Date =>
117118
* @returns The number of the Week
118119
*/
119120
export const getWeekOfYear = (date: Date, weekStart: WeekStart): number => {
120-
// Algorithm rewritten from C# example given at http://en.wikipedia.org/wiki/Talk:ISO_week_date
121-
const dayOfWeek = getWeekDayOffset(date, weekStart) + 1;
122121
const nearestThu = new Date(date);
123-
nearestThu.setDate(date.getDate() + (UNITS.thursday - dayOfWeek)); // get nearest Thursday (-3..+3 days)
122+
nearestThu.setHours(0, 0, 0, 0);
123+
const offset = weekStart === 'monday' ? 0 : weekStart === 'sunday' ? 1 : 2;
124+
nearestThu.setDate(nearestThu.getDate() + offset);
125+
adjustToThursday(nearestThu);
124126
const year = nearestThu.getFullYear();
125-
const janfirst = getFirstDayInMonth(year, 1);
126-
const days = Math.floor(((nearestThu as any) - (janfirst as any)) / UNITS.millisecondsPerDay);
127+
const weekOne = new Date(year, 0, 4);
128+
adjustToThursday(weekOne);
129+
const days = Math.round((nearestThu.getTime() - weekOne.getTime()) / UNITS.millisecondsPerDay);
127130
const week = 1 + Math.floor(days / UNITS.daysPerWeek); // Count of Thursdays
128131
return week;
129132
};
130133

134+
const adjustToThursday = (date: Date): void => {
135+
date.setDate(date.getDate() + 3 - ((date.getDay() + 6) % 7));
136+
};
137+
131138
export const getWeekDayOffset = (date: Date, weekStart: WeekStart): number => {
132139
const offset = WEEK_START_OFFSET[weekStart ?? 'monday'];
133140
return (date.getDay() + 6 - offset) % 7;

0 commit comments

Comments
 (0)