* Add months to a date with proper month-end handling. * If the original day exceeds the days in the target month, clamp to the last day. * For example: January 31 + 1 month = February 28 (or 29 in leap year)
( year: number, month: number, day: number, monthsToAdd: number, )
| 1426 | * For example: January 31 + 1 month = February 28 (or 29 in leap year) |
| 1427 | */ |
| 1428 | function addMonthsToDate( |
| 1429 | year: number, |
| 1430 | month: number, |
| 1431 | day: number, |
| 1432 | monthsToAdd: number, |
| 1433 | ): { year: number; month: number; day: number } { |
| 1434 | // Calculate target year and month |
| 1435 | let totalMonths = year * 12 + (month - 1) + monthsToAdd; |
| 1436 | const targetYear = Math.floor(totalMonths / 12); |
| 1437 | const targetMonth = (totalMonths % 12) + 1; |
| 1438 | |
| 1439 | // Handle negative months |
| 1440 | let finalYear = targetYear; |
| 1441 | let finalMonth = targetMonth; |
| 1442 | if (finalMonth <= 0) { |
| 1443 | finalYear -= 1; |
| 1444 | finalMonth += 12; |
| 1445 | } |
| 1446 | |
| 1447 | // Clamp day to last day of target month if necessary |
| 1448 | const lastDay = getLastDayOfMonth(finalYear, finalMonth); |
| 1449 | const finalDay = Math.min(day, lastDay); |
| 1450 | |
| 1451 | return { year: finalYear, month: finalMonth, day: finalDay }; |
| 1452 | } |
| 1453 | |
| 1454 | /** |
| 1455 | * Add a duration to a temporal value. |
no test coverage detected