| 1 | | // |
| 2 | | // This is only a SKELETON file for the 'Meetup' exercise. It's been provided as a |
| 3 | | // convenience to get you started writing code faster. |
| 4 | | // |
| 1 | const DAYS_OF_WEEK = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; |
| 5 | 2 | |
| 6 | 3 | /** |
| 7 | | * @param {number} year |
| 8 | | * @param {number} month |
| 9 | | * @param {string} week |
| 10 | | * @param {string} dayOfWeek |
| 11 | | * @returns {Date} |
| 4 | * Calculates the date of a meetup based on year, month, week descriptor, and day of week. |
| 5 | * |
| 6 | * @param {number} year - The year of the meetup |
| 7 | * @param {number} month - The month of the meetup (1-12) |
| 8 | * @param {string} week - The week descriptor ('first', 'second', 'third', 'fourth', 'last', 'teenth') |
| 9 | * @param {string} dayOfWeek - The day of the week ('Sunday' through 'Saturday') |
| 10 | * @returns {Date} - The calculated date of the meetup |
| 11 | * |
| 12 | * @example |
| 13 | * meetup(2018, 1, 'first', 'Monday') // Returns Date for January 1, 2018 |
| 14 | * meetup(1953, 8, 'teenth', 'Saturday') // Returns Date for August 15, 1953 |
| 12 | 15 | */ |
| 13 | 16 | export const meetup = (year, month, week, dayOfWeek) => { |
| 14 | | throw new Error('Remove this line and implement the function'); |
| 17 | // Edge Case: Invalid month input (not between 1-12) |
| 18 | if (month < 1 || month > 12) { |
| 19 | throw new Error('Invalid month'); |
| 20 | } |
| 21 | |
| 22 | // Edge Case: Invalid year input (negative or not a number) |
| 23 | if (year < 1) { |
| 24 | throw new Error('Invalid year'); |
| 25 | } |
| 26 | |
| 27 | // Edge Case: Invalid day of week input |
| 28 | if (!DAYS_OF_WEEK.includes(dayOfWeek)) { |
| 29 | throw new Error('Invalid day of week'); |
| 30 | } |
| 31 | |
| 32 | // Edge Case: Invalid week descriptor |
| 33 | const validWeeks = ['first', 'second', 'third', 'fourth', 'last', 'teenth']; |
| 34 | if (!validWeeks.includes(week)) { |
| 35 | throw new Error('Invalid week descriptor'); |
| 36 | } |
| 37 | |
| 38 | const targetDayIndex = DAYS_OF_WEEK.indexOf(dayOfWeek); |
| 39 | |
| 40 | // JavaScript months are 0-indexed, so we subtract 1 from the input month |
| 41 | const jsMonth = month - 1; |
| 42 | |
| 43 | if (week === 'teenth') { |
| 44 | // Edge Case: Teenth week calculation (days 13-19) |
| 45 | for (let day = 13; day <= 19; day++) { |
| 46 | const date = new Date(year, jsMonth, day); |
| 47 | if (date.getDay() === targetDayIndex) { |
| 48 | return date; |
| 49 | } |
| 50 | } |
| 51 | } else if (week === 'last') { |
| 52 | // Edge Case: Last week calculation (start from last day of month and work backwards) |
| 53 | // Get the last day of the month |
| 54 | const lastDay = new Date(year, month, 0).getDate(); |
| 55 | for (let day = lastDay; day >= 1; day--) { |
| 56 | const date = new Date(year, jsMonth, day); |
| 57 | if (date.getDay() === targetDayIndex) { |
| 58 | return date; |
| 59 | } |
| 60 | } |
| 61 | } else { |
| 62 | // Edge Case: First, second, third, fourth week calculations |
| 63 | const weekIndex = ['first', 'second', 'third', 'fourth'].indexOf(week); |
| 64 | |
| 65 | // Find the first occurrence of the target day |
| 66 | const firstDayOfMonth = new Date(year, jsMonth, 1); |
| 67 | const firstDayIndex = firstDayOfMonth.getDay(); |
| 68 | |
| 69 | // Calculate how many days to add to get to the first occurrence |
| 70 | let daysToAdd = targetDayIndex - firstDayIndex; |
| 71 | if (daysToAdd < 0) { |
| 72 | daysToAdd += 7; |
| 73 | } |
| 74 | |
| 75 | // Calculate the date of the first occurrence |
| 76 | const firstOccurrence = 1 + daysToAdd; |
| 77 | |
| 78 | // Calculate the date for the requested week |
| 79 | const targetDate = firstOccurrence + (weekIndex * 7); |
| 80 | |
| 81 | // Verify the date is valid for the month |
| 82 | const resultDate = new Date(year, jsMonth, targetDate); |
| 83 | |
| 84 | // Edge Case: Check if the calculated date is actually in the correct month |
| 85 | if (resultDate.getMonth() !== jsMonth) { |
| 86 | throw new Error('No meetup found for the specified criteria'); |
| 87 | } |
| 88 | |
| 89 | return resultDate; |
| 90 | } |
| 91 | |
| 92 | // Edge Case: No matching date found (should not normally happen with valid inputs) |
| 93 | throw new Error('No meetup found for the specified criteria'); |
| 15 | 94 | }; |
| 95 | |
| 96 | // Handled Edge Cases: Invalid month input, invalid year input, invalid day of week input, invalid week descriptor, teenth week calculation, last week calculation, first/second/third/fourth week calculations, date validation for month boundaries |