social-security-calculator 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ export declare const EARLY_RETIREMENT_AGE = 62;
2
+ export declare const WAGE_INDEX_CUTOFF = 2023;
3
+ export declare const MAX_RETIREMENT_AGE = 70;
4
+ export declare const LOOKBACK_YEARS = 35;
5
+ export declare const BEND_POINT_DIVISOR = 9779.44;
6
+ export declare const FIRST_BEND_POINT_MULTIPLIER = 180;
7
+ export declare const SECOND_BEND_POINT_MULTIPLIER = 1085;
8
+ export declare const PIA_PERCENTAGES: {
9
+ readonly FIRST_BRACKET: 0.9;
10
+ readonly SECOND_BRACKET: 0.32;
11
+ readonly THIRD_BRACKET: 0.15;
12
+ };
13
+ export declare const EARLY_RETIREMENT_REDUCTION_RATES: {
14
+ readonly FIRST_36_MONTHS: number;
15
+ readonly ADDITIONAL_MONTHS: number;
16
+ };
@@ -0,0 +1,17 @@
1
+ // Constants
2
+ export const EARLY_RETIREMENT_AGE = 62;
3
+ export const WAGE_INDEX_CUTOFF = 2023;
4
+ export const MAX_RETIREMENT_AGE = 70;
5
+ export const LOOKBACK_YEARS = 35;
6
+ export const BEND_POINT_DIVISOR = 9779.44;
7
+ export const FIRST_BEND_POINT_MULTIPLIER = 180;
8
+ export const SECOND_BEND_POINT_MULTIPLIER = 1085;
9
+ export const PIA_PERCENTAGES = {
10
+ FIRST_BRACKET: 0.9,
11
+ SECOND_BRACKET: 0.32,
12
+ THIRD_BRACKET: 0.15
13
+ };
14
+ export const EARLY_RETIREMENT_REDUCTION_RATES = {
15
+ FIRST_36_MONTHS: 5 / 9 * 0.01,
16
+ ADDITIONAL_MONTHS: 5 / 12 * 0.01 // 5/12 of 1%
17
+ };
@@ -1,2 +1,2 @@
1
- import { Wages } from '../model';
2
- export declare function getEstimatedEarnings(birthDate: Date, lastWage: number, lastYearWorked?: number, earningGrowthRate?: number): Wages;
1
+ import { Earnings } from '../model';
2
+ export declare function getEstimatedEarnings(birthDate: Date, lastWage: number, lastYearWorked?: number, earningGrowthRate?: number): Earnings;
@@ -1,11 +1,12 @@
1
- import { wageIndex, wageIndexFuture, taxableMaximum, } from '../wage-index';
1
+ import { wageIndex } from '../wage-index';
2
+ import { getEnglishCommonLawDate } from '../index';
2
3
  const YOUTH_FACTOR = 8;
3
4
  const YOUTH_FACTOR_AGE = 21;
4
5
  const WORK_START_AGE = 18;
5
6
  const CURRENT_YEAR = new Date().getFullYear();
6
7
  export function getEstimatedEarnings(birthDate, lastWage, lastYearWorked = CURRENT_YEAR, earningGrowthRate = 0) {
7
8
  var _a;
8
- const birthDateMinusOneDay = new Date(birthDate.getFullYear(), birthDate.getMonth(), birthDate.getDate() - 1);
9
+ const birthDateMinusOneDay = getEnglishCommonLawDate(birthDate);
9
10
  const age = CURRENT_YEAR - birthDateMinusOneDay.getFullYear();
10
11
  if (age <= 22) {
11
12
  // return zero
@@ -30,7 +31,7 @@ export function getEstimatedEarnings(birthDate, lastWage, lastYearWorked = CURRE
30
31
  }
31
32
  // Cap wages at taxable maximum
32
33
  wageResults.forEach(({ year, earnings }) => {
33
- const maxTaxable = taxableMaximum.find((entry) => entry.year === year).earnings;
34
+ const maxTaxable = wageIndex.find((entry) => entry.year === year).taxMax;
34
35
  const currentEarnings = wageResults.find((entry) => entry.year === year).earnings;
35
36
  const maxEarnings = Math.min(currentEarnings, maxTaxable);
36
37
  wageResults.find((entry) => entry.year === year).earnings = maxEarnings;
@@ -38,7 +39,7 @@ export function getEstimatedEarnings(birthDate, lastWage, lastYearWorked = CURRE
38
39
  return wageResults;
39
40
  }
40
41
  function getReductionFactor(year) {
41
- const allIndexes = wageIndex.concat(wageIndexFuture);
42
+ const allIndexes = wageIndex;
42
43
  const lastYear = year - 1;
43
44
  const nextYear = year + 1;
44
45
  if (year === CURRENT_YEAR && !allIndexes.find((entry) => entry.year === lastYear)) {
@@ -48,6 +49,6 @@ function getReductionFactor(year) {
48
49
  return 1;
49
50
  }
50
51
  else {
51
- return ((allIndexes.find((entry) => entry.year === year).earnings) / (allIndexes.find((entry) => entry.year === nextYear).earnings));
52
+ return ((allIndexes.find((entry) => entry.year === year).awi) / (allIndexes.find((entry) => entry.year === nextYear).awi));
52
53
  }
53
54
  }
package/lib/index.d.ts CHANGED
@@ -1,12 +1,7 @@
1
- import { Wages } from './model';
2
- export declare function calc(birthday: Date, retirementDate: Date, earnings: Wages): {
3
- AIME: number;
4
- NormalMonthlyBenefit: number;
5
- };
6
- export declare function calcRetirementBenefit(birthday: Date, retirementDate: Date, AIME: number): {
7
- AIME: number;
8
- NormalMonthlyBenefit: number;
9
- };
1
+ import { BenefitCalculationResult, Earnings } from './model';
2
+ export declare function calc(birthday: Date, retirementDate: Date, earnings: Earnings): BenefitCalculationResult;
3
+ export declare function calcRetirementBenefit(birthday: Date, lastYearEarnings: number, retirementDate: Date, AIME: number): BenefitCalculationResult;
10
4
  export declare function calculatePIA(AIME: number, baseYear?: number): number;
11
- export declare function calculateAIME(earnings: Wages, baseYear?: number): number;
5
+ export declare function calculateAIME(earnings: Earnings, baseYear?: number): number;
6
+ export declare function getEnglishCommonLawDate(date: Date): Date;
12
7
  export declare function getFullRetirementMonths(commonLawBirthDate: Date): number;
package/lib/index.js CHANGED
@@ -1,173 +1,205 @@
1
1
  import { wageIndex } from './wage-index';
2
- const EARLY_RETIREMENT_AGE = 62;
2
+ import { EARLY_RETIREMENT_AGE, WAGE_INDEX_CUTOFF, MAX_RETIREMENT_AGE, LOOKBACK_YEARS, BEND_POINT_DIVISOR, FIRST_BEND_POINT_MULTIPLIER, SECOND_BEND_POINT_MULTIPLIER, PIA_PERCENTAGES, EARLY_RETIREMENT_REDUCTION_RATES } from './constants';
3
+ // Main calculation function
3
4
  export function calc(birthday, retirementDate, earnings) {
4
- const AIME = calculateAIME(earnings);
5
- const results = calcRetirementBenefit(birthday, retirementDate, AIME);
5
+ // Validation
6
+ if (!birthday || !retirementDate) {
7
+ throw new Error('Birthday and retirement date are required');
8
+ }
9
+ if (!earnings || earnings.length === 0) {
10
+ throw new Error('Earnings history cannot be empty');
11
+ }
12
+ if (retirementDate < birthday) {
13
+ throw new Error('Retirement date cannot be before birthday');
14
+ }
15
+ const lastYearEarnings = earnings
16
+ .filter(wage => wage.earnings > 0)
17
+ .reduce((max, wage) => Math.max(max, wage.year), 0);
18
+ const yearAge60 = birthday.getFullYear() + 60;
19
+ const averageIndexedMonthlyEarnings = calculateAIME(earnings, yearAge60);
20
+ const results = calcRetirementBenefit(birthday, lastYearEarnings, retirementDate, averageIndexedMonthlyEarnings);
6
21
  return results;
7
22
  }
8
- export function calcRetirementBenefit(birthday, retirementDate, AIME) {
9
- const eclBirthDate = getEnglishCommonLawDate(birthday);
10
- const fraMonths = getFullRetirementMonths(eclBirthDate);
11
- const fullRetirementDate = new Date(eclBirthDate.getFullYear(), eclBirthDate.getMonth() + fraMonths, eclBirthDate.getDate());
12
- const earliestRetirementDate = new Date(eclBirthDate.getFullYear() + EARLY_RETIREMENT_AGE, eclBirthDate.getMonth(), eclBirthDate.getDate());
13
- const age60Year = eclBirthDate.getFullYear() + 60;
14
- const PIA = calculatePIA(AIME, age60Year);
15
- const earlyRetireMonths = monthsDifference(retirementDate, fullRetirementDate);
16
- let adjustedBenefits = PIA;
17
- if (retirementDate < earliestRetirementDate) {
23
+ export function calcRetirementBenefit(birthday, lastYearEarnings, retirementDate, AIME) {
24
+ const dates = calculateRetirementDates(birthday, retirementDate);
25
+ const age60Year = dates.eclBirthDate.getFullYear() + 60;
26
+ const primaryInsuranceAmount = calculatePIA(AIME, age60Year);
27
+ // Calculate COLA adjustments
28
+ const colaAdjustedPIA = calculateCOLAAdjustments(primaryInsuranceAmount, age60Year + 2);
29
+ // Calculate early/delayed retirement adjustments
30
+ const earlyRetireMonths = monthsDifference(dates.adjusted, dates.fullRetirement);
31
+ let adjustedBenefits = colaAdjustedPIA;
32
+ if (retirementDate < dates.earliestRetirement) {
18
33
  adjustedBenefits = 0;
19
34
  }
20
35
  else if (earlyRetireMonths < 0) {
21
- adjustedBenefits = calculateSocialSecurityReduction(PIA, earlyRetireMonths * -1);
36
+ adjustedBenefits = calculateEarlyRetirementReduction(colaAdjustedPIA, Math.abs(earlyRetireMonths));
22
37
  }
23
38
  else if (earlyRetireMonths > 0) {
24
- adjustedBenefits = calculateSocialSecurityIncrease(eclBirthDate, PIA, earlyRetireMonths);
39
+ adjustedBenefits = calculateDelayedRetirementIncrease(dates.eclBirthDate, colaAdjustedPIA, earlyRetireMonths);
25
40
  }
26
41
  const monthlyBenefit = Math.floor(adjustedBenefits);
27
- const results = {
28
- "AIME": AIME,
29
- "NormalMonthlyBenefit": monthlyBenefit,
42
+ return {
43
+ AIME: AIME,
44
+ NormalMonthlyBenefit: monthlyBenefit,
30
45
  };
31
- return results;
46
+ }
47
+ function calculateRetirementDates(birthday, retirementDate) {
48
+ const eclBirthDate = getEnglishCommonLawDate(birthday);
49
+ const fraMonths = getFullRetirementMonths(eclBirthDate);
50
+ const earliestRetirement = new Date(eclBirthDate.getFullYear() + EARLY_RETIREMENT_AGE, eclBirthDate.getMonth(), eclBirthDate.getDate());
51
+ const fullRetirement = new Date(eclBirthDate.getFullYear(), eclBirthDate.getMonth() + fraMonths, eclBirthDate.getDate());
52
+ const maxRetirement = new Date(eclBirthDate.getFullYear() + MAX_RETIREMENT_AGE, eclBirthDate.getMonth(), eclBirthDate.getDate());
53
+ const adjusted = retirementDate > maxRetirement ? maxRetirement : retirementDate;
54
+ return {
55
+ earliestRetirement,
56
+ fullRetirement,
57
+ maxRetirement,
58
+ adjusted,
59
+ eclBirthDate
60
+ };
61
+ }
62
+ function calculateCOLAAdjustments(PIA, startYear) {
63
+ const currentYear = new Date().getFullYear();
64
+ const colaRates = wageIndex
65
+ .filter(wage => wage.year >= startYear && wage.year < currentYear)
66
+ .map(wage => wage.cola);
67
+ return colaRates.reduce((adjustedAmount, rate) => {
68
+ const multiplier = 1 + (rate / 100);
69
+ return roundToFloorTenCents(adjustedAmount * multiplier);
70
+ }, PIA);
32
71
  }
33
72
  export function calculatePIA(AIME, baseYear) {
34
- var _a;
35
- const mostRecentWageIndex = Math.max(...wageIndex.map(val => val.year));
36
- if (baseYear) {
37
- baseYear = Math.min(baseYear, mostRecentWageIndex);
38
- }
39
- const averageWageLastYear = baseYear || mostRecentWageIndex;
40
- const wageIndexLastYear = ((_a = wageIndex.find(val => val.year === averageWageLastYear)) === null || _a === void 0 ? void 0 : _a.earnings) || 0;
41
- const bendPointDivisor = 9779.44;
42
- const firstBendPointMultiplier = 180;
43
- const secondBendPointMultiplier = 1085;
44
- // https://www.ssa.gov/oact/COLA/piaformula.html
45
- // Per examples, bend points are rounded to the nearest dollar
46
- const firstBendPoint = Math.round(firstBendPointMultiplier * wageIndexLastYear / bendPointDivisor);
47
- const secondBendPoint = Math.round(secondBendPointMultiplier * wageIndexLastYear / bendPointDivisor);
48
- // https://www.ssa.gov/OP_Home/handbook/handbook.07/handbook-0738.html
49
- // Calculations that are not a multiple of 10 cents are rounded to the next lower multiple of 10 cents. For example, $100.18 is rounded down to $100.10.
50
- const PIA = (() => {
51
- let monthlyBenefit = 0;
52
- if (AIME <= firstBendPoint) {
53
- monthlyBenefit = 0.9 * AIME;
54
- }
55
- else {
56
- if (AIME > firstBendPoint && AIME <= secondBendPoint) {
57
- monthlyBenefit = (0.9 * firstBendPoint) + (0.32 * (AIME - firstBendPoint));
58
- }
59
- else {
60
- monthlyBenefit = (0.9 * firstBendPoint) + (0.32 * (secondBendPoint - firstBendPoint)) + (0.15 * (AIME - secondBendPoint));
61
- }
62
- }
63
- return roundToFloorTenCents(monthlyBenefit);
64
- })();
65
- return PIA;
73
+ const effectiveYear = baseYear ? Math.min(baseYear, WAGE_INDEX_CUTOFF) : WAGE_INDEX_CUTOFF;
74
+ const wageIndexEntry = wageIndex.find(val => val.year === effectiveYear);
75
+ if (!wageIndexEntry) {
76
+ throw new Error(`No wage index data found for year ${effectiveYear}`);
77
+ }
78
+ const wageIndexLastYear = wageIndexEntry.awi;
79
+ // Calculate bend points (rounded to nearest dollar per SSA rules)
80
+ const firstBendPoint = Math.round(FIRST_BEND_POINT_MULTIPLIER * wageIndexLastYear / BEND_POINT_DIVISOR);
81
+ const secondBendPoint = Math.round(SECOND_BEND_POINT_MULTIPLIER * wageIndexLastYear / BEND_POINT_DIVISOR);
82
+ let monthlyBenefit;
83
+ if (AIME <= firstBendPoint) {
84
+ monthlyBenefit = PIA_PERCENTAGES.FIRST_BRACKET * AIME;
85
+ }
86
+ else if (AIME <= secondBendPoint) {
87
+ monthlyBenefit =
88
+ PIA_PERCENTAGES.FIRST_BRACKET * firstBendPoint +
89
+ PIA_PERCENTAGES.SECOND_BRACKET * (AIME - firstBendPoint);
90
+ }
91
+ else {
92
+ monthlyBenefit =
93
+ PIA_PERCENTAGES.FIRST_BRACKET * firstBendPoint +
94
+ PIA_PERCENTAGES.SECOND_BRACKET * (secondBendPoint - firstBendPoint) +
95
+ PIA_PERCENTAGES.THIRD_BRACKET * (AIME - secondBendPoint);
96
+ }
97
+ return roundToFloorTenCents(monthlyBenefit);
66
98
  }
67
99
  export function calculateAIME(earnings, baseYear) {
68
- var _a;
69
- const lookbackYears = 35;
70
- const mostRecentWageIndex = Math.max(...wageIndex.map(wag => wag.year));
71
- if (baseYear) {
72
- baseYear = Math.min(baseYear, mostRecentWageIndex);
73
- }
74
- const averageWageLastYear = baseYear || mostRecentWageIndex;
75
- const wageIndexLastYear = ((_a = wageIndex.find(val => val.year === averageWageLastYear)) === null || _a === void 0 ? void 0 : _a.earnings) || 0;
100
+ if (!earnings || earnings.length === 0) {
101
+ return 0;
102
+ }
103
+ const effectiveYear = baseYear ? Math.min(baseYear, WAGE_INDEX_CUTOFF) : WAGE_INDEX_CUTOFF;
104
+ const wageIndexEntry = wageIndex.find(val => val.year === effectiveYear);
105
+ if (!wageIndexEntry) {
106
+ throw new Error(`No wage index data found for year ${effectiveYear}`);
107
+ }
108
+ const wageIndexLastYear = wageIndexEntry.awi;
76
109
  const futureYearsFactor = 1;
77
- // calculate the wage index factors
78
- const wageIndexFactors = wageIndex.reduce((acc, { year, earnings }) => (acc[year] = 1 + (Math.max(0, wageIndexLastYear - earnings)) / earnings, acc), {});
79
- // adjust the earnings according to the wage index factor
110
+ // Calculate wage index factors
111
+ const wageIndexFactors = wageIndex.reduce((acc, { year, awi }) => {
112
+ acc[year] = 1 + (Math.max(0, wageIndexLastYear - awi)) / awi;
113
+ return acc;
114
+ }, {});
115
+ // Adjust earnings according to wage index factor
80
116
  const adjustedEarnings = earnings.reduce((acc, { year, earnings }) => {
81
117
  acc[year] = earnings * (wageIndexFactors[year] || futureYearsFactor);
82
118
  return acc;
83
119
  }, {});
120
+ // Get top 35 years of earnings
84
121
  const top35YearsEarningsArr = Object.values(adjustedEarnings)
85
- .sort((a, b) => b - a) // sort the earnings from highest to lowest amount
86
- .slice(0, lookbackYears); // grab the highest 35 earnings years
87
- const top35YearsEarnings = top35YearsEarningsArr.reduce((partialSum, a) => partialSum + a, 0); // and finally sum them
88
- // https://www.ssa.gov/oact/cola/Benefits.html
89
- // "We then round the resulting average amount down to the next lower dollar amount"
90
- const AIME = Math.floor(top35YearsEarnings / (12 * lookbackYears));
91
- return AIME;
122
+ .sort((a, b) => b - a)
123
+ .slice(0, LOOKBACK_YEARS);
124
+ const totalEarnings = top35YearsEarningsArr.reduce((sum, earnings) => sum + earnings, 0);
125
+ // Calculate AIME (rounded down to next lower dollar)
126
+ const averageIndexedMonthlyEarnings = Math.floor(totalEarnings / (12 * LOOKBACK_YEARS));
127
+ return averageIndexedMonthlyEarnings;
92
128
  }
93
- function calculateSocialSecurityReduction(amount, months) {
94
- const first36Rate = 5 / 9 * 0.01; // 5/9 of 1%
95
- const additionalRate = 5 / 12 * 0.01; // 5/12 of 1%
96
- let reduction = 0;
129
+ function calculateEarlyRetirementReduction(amount, months) {
130
+ if (months <= 0)
131
+ return amount;
132
+ let reduction;
97
133
  if (months <= 36) {
98
- reduction = months * first36Rate;
134
+ reduction = months * EARLY_RETIREMENT_REDUCTION_RATES.FIRST_36_MONTHS;
99
135
  }
100
136
  else {
101
- // 36 months times 5/9 of 1 percent plus 24 months times 5/12 of 1 percent.
102
- reduction = 36 * first36Rate + (months - 36) * additionalRate;
137
+ reduction =
138
+ 36 * EARLY_RETIREMENT_REDUCTION_RATES.FIRST_36_MONTHS +
139
+ (months - 36) * EARLY_RETIREMENT_REDUCTION_RATES.ADDITIONAL_MONTHS;
103
140
  }
104
- return amount - amount * reduction;
141
+ return amount * (1 - reduction);
105
142
  }
106
- function calculateSocialSecurityIncrease(birthday, initialAmount, numberOfMonths) {
143
+ function calculateDelayedRetirementIncrease(birthday, initialAmount, numberOfMonths) {
144
+ if (numberOfMonths <= 0)
145
+ return initialAmount;
107
146
  const birthYear = birthday.getFullYear();
108
- let monthlyRate;
109
- // Determine the monthly rate based on the year of birth
147
+ const monthlyRate = getDelayedRetirementRate(birthYear);
148
+ const totalIncrease = monthlyRate * numberOfMonths;
149
+ return initialAmount * (1 + totalIncrease);
150
+ }
151
+ function getDelayedRetirementRate(birthYear) {
110
152
  if (birthYear < 1933) {
111
153
  throw new Error(`Invalid birth year for delayed retirement: ${birthYear}`);
112
154
  }
113
- else if (birthYear <= 1934) {
114
- monthlyRate = 11 / 24 / 100; // 11/24 of 1%
115
- }
116
- else if (birthYear <= 1936) {
117
- monthlyRate = 0.005; // 1/2 of 1%
118
- }
119
- else if (birthYear <= 1938) {
120
- monthlyRate = 13 / 24 / 100; // 13/24 of 1%
121
- }
122
- else if (birthYear <= 1940) {
123
- monthlyRate = 7 / 12 / 100; // 7/12 of 1%
124
- }
125
- else if (birthYear <= 1942) {
126
- monthlyRate = 5 / 8 / 100; // 5/8 of 1%
127
- }
128
- else {
129
- monthlyRate = 2 / 3 / 100; // 2/3 of 1%
130
- }
131
- // Calculate the new amount
132
- let totalAdjustment = 0;
133
- for (let i = 0; i < numberOfMonths; i++) {
134
- totalAdjustment += monthlyRate;
135
- }
136
- return initialAmount * (1 + totalAdjustment);
155
+ // Rates based on SSA rules
156
+ if (birthYear <= 1934)
157
+ return 11 / 24 / 100; // 11/24 of 1%
158
+ if (birthYear <= 1936)
159
+ return 0.005; // 1/2 of 1%
160
+ if (birthYear <= 1938)
161
+ return 13 / 24 / 100; // 13/24 of 1%
162
+ if (birthYear <= 1940)
163
+ return 7 / 12 / 100; // 7/12 of 1%
164
+ if (birthYear <= 1942)
165
+ return 5 / 8 / 100; // 5/8 of 1%
166
+ return 2 / 3 / 100; // 2/3 of 1%
137
167
  }
138
168
  function roundToFloorTenCents(amount) {
139
- // Convert the amount to fractional dimes
140
- let dimes = amount * 10;
141
- // floor to only whole dimes
142
- dimes = Math.floor(dimes);
143
- // Convert back to dollars and return
144
- return (dimes / 10);
169
+ // Convert to dimes, floor, then convert back to dollars
170
+ return Math.floor(amount * 10) / 10;
145
171
  }
146
- function getEnglishCommonLawDate(date) {
147
- const year = date.getFullYear();
148
- const month = date.getMonth();
149
- const day = date.getDate();
150
- const englishCommonLawDate = new Date(year, month, day - 1);
151
- return englishCommonLawDate;
172
+ export function getEnglishCommonLawDate(date) {
173
+ // Create a new date to avoid mutating the original
174
+ const eclDate = new Date(date);
175
+ eclDate.setDate(eclDate.getDate() - 1);
176
+ return eclDate;
152
177
  }
153
178
  export function getFullRetirementMonths(commonLawBirthDate) {
154
179
  const year = commonLawBirthDate.getFullYear();
155
- switch (true) {
156
- case (year >= 1943 && year <= 1954):
157
- return 66 * 12;
158
- case (year >= 1955 && year <= 1959):
159
- const fra = ((year - 1954) * 2) + (66 * 12);
160
- return fra;
161
- case (year >= 1960):
162
- return 67 * 12;
163
- default:
164
- throw new Error('Invalid birth year');
180
+ if (year <= 1937) {
181
+ return 65 * 12;
182
+ }
183
+ else if (year <= 1942) {
184
+ // Gradual increase from 65 years to 65 years 10 months
185
+ return ((year - 1937) * 2) + (65 * 12);
186
+ }
187
+ else if (year <= 1954) {
188
+ return 66 * 12;
189
+ }
190
+ else if (year <= 1959) {
191
+ // Gradual increase from 66 years to 66 years 10 months
192
+ return ((year - 1954) * 2) + (66 * 12);
193
+ }
194
+ else if (year >= 1960) {
195
+ return 67 * 12;
196
+ }
197
+ else {
198
+ throw new Error(`Invalid birth year: ${year}`);
165
199
  }
166
200
  }
167
201
  function monthsDifference(date1, date2) {
168
- // Calculate the total number of months for each date
169
202
  const months1 = date1.getFullYear() * 12 + date1.getMonth();
170
203
  const months2 = date2.getFullYear() * 12 + date2.getMonth();
171
- // Return the difference in months
172
204
  return months1 - months2;
173
205
  }
package/lib/model.d.ts CHANGED
@@ -1,4 +1,24 @@
1
- export type Wages = {
1
+ export type Earnings = {
2
2
  year: number;
3
3
  earnings: number;
4
4
  }[];
5
+ export type Wage = {
6
+ year: number;
7
+ retirement: number;
8
+ disability: number;
9
+ survivors: number;
10
+ taxMax: number;
11
+ cola: number;
12
+ awi: number;
13
+ };
14
+ export type Wages = Wage[];
15
+ export interface BenefitCalculationResult {
16
+ AIME: number;
17
+ NormalMonthlyBenefit: number;
18
+ }
19
+ export interface RetirementDates {
20
+ earliestRetirement: Date;
21
+ fullRetirement: Date;
22
+ maxRetirement: Date;
23
+ adjusted: Date;
24
+ }
@@ -1,3 +1,3 @@
1
- import { Wages } from '../model';
2
- declare function getWages(fileName: string): Promise<Wages>;
1
+ import { Earnings } from '../model';
2
+ declare function getWages(fileName: string): Promise<Earnings>;
3
3
  export default getWages;
@@ -1,4 +1,3 @@
1
- import { Wages } from './model';
1
+ import { Wage, Wages } from './model';
2
2
  export declare const wageIndex: Wages;
3
- export declare const wageIndexFuture: Wages;
4
- export declare const taxableMaximum: Wages;
3
+ export declare const wageIndexFuture: Partial<Wage>[];