|
1 | | -export default function getCalendarMonthWeeks(month, enableOutsideDays) { |
2 | | - // set utc offset to get correct dates in future (when timezone changes) |
3 | | - const baseDate = month.clone(); |
4 | | - const firstOfMonth = baseDate.clone().startOf('month').hour(12); |
5 | | - const lastOfMonth = baseDate.clone().endOf('month').hour(12); |
| 1 | +import moment from 'moment'; |
6 | 2 |
|
7 | | - const currentDay = firstOfMonth.clone(); |
8 | | - let currentWeek = []; |
9 | | - const weeksInMonth = []; |
| 3 | +const WEEKDAYS = [0, 1, 2, 3, 4, 5, 6]; |
10 | 4 |
|
11 | | - // days belonging to the previous month |
12 | | - for (let i = 0; i < currentDay.weekday(); i += 1) { |
13 | | - const prevDay = enableOutsideDays ? currentDay.clone().subtract(i + 1, 'day') : null; |
14 | | - currentWeek.unshift(prevDay); |
| 5 | +export default function getCalendarMonthWeeks( |
| 6 | + month, |
| 7 | + enableOutsideDays, |
| 8 | + firstDayOfWeek = moment.localeData().firstDayOfWeek(), |
| 9 | +) { |
| 10 | + if (!moment.isMoment(month) || !month.isValid()) { |
| 11 | + throw new TypeError('`month` must be a valid moment object'); |
| 12 | + } |
| 13 | + if (WEEKDAYS.indexOf(firstDayOfWeek) === -1) { |
| 14 | + throw new TypeError('`firstDayOfWeek` must be an integer between 0 and 6'); |
15 | 15 | } |
16 | 16 |
|
17 | | - while (currentDay < lastOfMonth) { |
18 | | - currentWeek.push(currentDay.clone()); |
19 | | - currentDay.add(1, 'd'); |
| 17 | + // set utc offset to get correct dates in future (when timezone changes) |
| 18 | + const firstOfMonth = month.clone().startOf('month').hour(12); |
| 19 | + const lastOfMonth = month.clone().endOf('month').hour(12); |
| 20 | + |
| 21 | + // calculate the exact first and last days to fill the entire matrix |
| 22 | + // (considering days outside month) |
| 23 | + const prevDays = ((firstOfMonth.day() + 7 - firstDayOfWeek) % 7); |
| 24 | + const nextDays = ((firstDayOfWeek + 6 - lastOfMonth.day()) % 7); |
| 25 | + const firstDay = firstOfMonth.clone().subtract(prevDays, 'day'); |
| 26 | + const lastDay = lastOfMonth.clone().add(nextDays, 'day'); |
20 | 27 |
|
21 | | - if (currentDay.weekday() === 0) { |
22 | | - weeksInMonth.push(currentWeek); |
23 | | - currentWeek = []; |
| 28 | + const totalDays = lastDay.diff(firstDay, 'days') + 1; |
| 29 | + |
| 30 | + const currentDay = firstDay.clone(); |
| 31 | + const weeksInMonth = []; |
| 32 | + |
| 33 | + for (let i = 0; i < totalDays; i += 1) { |
| 34 | + if (i % 7 === 0) { |
| 35 | + weeksInMonth.push([]); |
24 | 36 | } |
25 | | - } |
26 | 37 |
|
27 | | - // weekday() returns the index of the day of the week according to the locale |
28 | | - // this means if the week starts on Monday, weekday() will return 0 for a Monday date, not 1 |
29 | | - if (currentDay.weekday() !== 0) { |
30 | | - // days belonging to the next month |
31 | | - for (let k = currentDay.weekday(), count = 0; k < 7; k += 1, count += 1) { |
32 | | - const nextDay = enableOutsideDays ? currentDay.clone().add(count, 'day') : null; |
33 | | - currentWeek.push(nextDay); |
| 38 | + let day = null; |
| 39 | + if ((i >= prevDays && i < (totalDays - nextDays)) || enableOutsideDays) { |
| 40 | + day = currentDay.clone(); |
34 | 41 | } |
35 | 42 |
|
36 | | - weeksInMonth.push(currentWeek); |
| 43 | + weeksInMonth[weeksInMonth.length - 1].push(day); |
| 44 | + |
| 45 | + currentDay.add(1, 'day'); |
37 | 46 | } |
38 | 47 |
|
39 | 48 | return weeksInMonth; |
|
0 commit comments