| 4 | 4 | // |
| 5 | 5 | |
| 6 | 6 | /** |
| 7 | | * @param {number} year |
| 8 | | * @param {number} month |
| 9 | | * @param {string} week |
| 10 | | * @param {string} dayOfWeek |
| 11 | | * @returns {Date} |
| 7 | * Calculates the date of a meetup based on year, month, week descriptor, and day of week. |
| 8 | * |
| 9 | * @param {number} year - The year of the meetup |
| 10 | * @param {number} month - The month of the meetup (1-12) |
| 11 | * @param {string} week - The week descriptor ('first', 'second', 'third', 'fourth', 'last', 'teenth') |
| 12 | * @param {string} dayOfWeek - The day of the week ('Sunday', 'Monday', etc.) |
| 13 | * @returns {Date} - The calculated date of the meetup |
| 12 | 14 | */ |
| 13 | 15 | export const meetup = (year, month, week, dayOfWeek) => { |
| 14 | | throw new Error('Remove this line and implement the function'); |
| 16 | // Map day names to their corresponding index (0-6) |
| 17 | const days = { |
| 18 | 'Sunday': 0, |
| 19 | 'Monday': 1, |
| 20 | 'Tuesday': 2, |
| 21 | 'Wednesday': 3, |
| 22 | 'Thursday': 4, |
| 23 | 'Friday': 5, |
| 24 | 'Saturday': 6 |
| 25 | }; |
| 26 | |
| 27 | // Edge Case: Invalid day of week |
| 28 | if (!(dayOfWeek in days)) { |
| 29 | throw new Error('Invalid day of week'); |
| 30 | } |
| 31 | |
| 32 | const targetDay = days[dayOfWeek]; |
| 33 | |
| 34 | // Edge Case: Invalid month (should be 1-12) |
| 35 | if (month < 1 || month > 12) { |
| 36 | throw new Error('Invalid month'); |
| 37 | } |
| 38 | |
| 39 | // Create a date object for the first day of the given month |
| 40 | const firstDay = new Date(year, month - 1, 1); |
| 41 | |
| 42 | // Edge Case: Invalid year (Date constructor handles this, but we validate for clarity) |
| 43 | if (isNaN(firstDay.getTime())) { |
| 44 | throw new Error('Invalid date'); |
| 45 | } |
| 46 | |
| 47 | // For 'last' week, we start from the last day of the month |
| 48 | if (week === 'last') { |
| 49 | // Get the last day of the month |
| 50 | const lastDay = new Date(year, month, 0); |
| 51 | |
| 52 | // Edge Case: Invalid date calculation |
| 53 | if (isNaN(lastDay.getTime())) { |
| 54 | throw new Error('Invalid date'); |
| 55 | } |
| 56 | |
| 57 | // Find the last occurrence of the target day |
| 58 | const diff = (lastDay.getDay() - targetDay + 7) % 7; |
| 59 | const result = new Date(lastDay); |
| 60 | result.setDate(lastDay.getDate() - diff); |
| 61 | |
| 62 | // Edge Case: Result date is not in the correct month |
| 63 | if (result.getMonth() !== month - 1) { |
| 64 | throw new Error('No valid date found'); |
| 65 | } |
| 66 | |
| 67 | return result; |
| 68 | } |
| 69 | |
| 70 | // For 'teenth' week, we check days 13-19 |
| 71 | if (week === 'teenth') { |
| 72 | for (let day = 13; day <= 19; day++) { |
| 73 | const date = new Date(year, month - 1, day); |
| 74 | |
| 75 | // Edge Case: Invalid date during iteration |
| 76 | if (isNaN(date.getTime())) { |
| 77 | throw new Error('Invalid date'); |
| 78 | } |
| 79 | |
| 80 | if (date.getDay() === targetDay) { |
| 81 | return date; |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | // Edge Case: No matching date found in teenth range |
| 86 | throw new Error('No valid date found'); |
| 87 | } |
| 88 | |
| 89 | // For first, second, third, fourth weeks |
| 90 | const weekNumbers = { |
| 91 | 'first': 1, |
| 92 | 'second': 2, |
| 93 | 'third': 3, |
| 94 | 'fourth': 4 |
| 95 | }; |
| 96 | |
| 97 | // Edge Case: Invalid week descriptor |
| 98 | if (!(week in weekNumbers)) { |
| 99 | throw new Error('Invalid week descriptor'); |
| 100 | } |
| 101 | |
| 102 | const weekNumber = weekNumbers[week]; |
| 103 | |
| 104 | // Find the first occurrence of the target day |
| 105 | const firstDayOfWeek = firstDay.getDay(); |
| 106 | const diff = (targetDay - firstDayOfWeek + 7) % 7; |
| 107 | const firstOccurrence = new Date(firstDay); |
| 108 | firstOccurrence.setDate(1 + diff); |
| 109 | |
| 110 | // Edge Case: First occurrence calculation failed |
| 111 | if (isNaN(firstOccurrence.getTime())) { |
| 112 | throw new Error('Invalid date calculation'); |
| 113 | } |
| 114 | |
| 115 | // Calculate the target occurrence |
| 116 | const targetDate = new Date(firstOccurrence); |
| 117 | targetDate.setDate(firstOccurrence.getDate() + (weekNumber - 1) * 7); |
| 118 | |
| 119 | // Edge Case: Target date is not in the correct month |
| 120 | if (targetDate.getMonth() !== month - 1) { |
| 121 | throw new Error('No valid date found'); |
| 122 | } |
| 123 | |
| 124 | // Edge Case: Target date calculation failed |
| 125 | if (isNaN(targetDate.getTime())) { |
| 126 | throw new Error('Invalid date'); |
| 127 | } |
| 128 | |
| 129 | return targetDate; |
| 15 | 130 | }; |
| 131 | |
| 132 | // Handled Edge Cases: Invalid day of week, Invalid month, Invalid year, Invalid date during iteration, Result date not in correct month, No matching date in teenth range, Invalid week descriptor, First occurrence calculation failure, Target date not in correct month, Target date calculation failure |