UNPKG

1.79 kBJavaScriptView Raw
1import { normalizeDates } from "./_lib/normalizeDates.js";
2import { compareAsc } from "./compareAsc.js";
3import { differenceInCalendarMonths } from "./differenceInCalendarMonths.js";
4import { isLastDayOfMonth } from "./isLastDayOfMonth.js";
5
6/**
7 * The {@link differenceInMonths} function options.
8 */
9
10/**
11 * @name differenceInMonths
12 * @category Month Helpers
13 * @summary Get the number of full months between the given dates.
14 *
15 * @param laterDate - The later date
16 * @param earlierDate - The earlier date
17 * @param options - An object with options
18 *
19 * @returns The number of full months
20 *
21 * @example
22 * // How many full months are between 31 January 2014 and 1 September 2014?
23 * const result = differenceInMonths(new Date(2014, 8, 1), new Date(2014, 0, 31))
24 * //=> 7
25 */
26export function differenceInMonths(laterDate, earlierDate, options) {
27 const [laterDate_, workingLaterDate, earlierDate_] = normalizeDates(
28 options?.in,
29 laterDate,
30 laterDate,
31 earlierDate,
32 );
33
34 const sign = compareAsc(workingLaterDate, earlierDate_);
35 const difference = Math.abs(
36 differenceInCalendarMonths(workingLaterDate, earlierDate_),
37 );
38
39 if (difference < 1) return 0;
40
41 if (workingLaterDate.getMonth() === 1 && workingLaterDate.getDate() > 27)
42 workingLaterDate.setDate(30);
43
44 workingLaterDate.setMonth(workingLaterDate.getMonth() - sign * difference);
45
46 let isLastMonthNotFull = compareAsc(workingLaterDate, earlierDate_) === -sign;
47
48 if (
49 isLastDayOfMonth(laterDate_) &&
50 difference === 1 &&
51 compareAsc(laterDate_, earlierDate_) === 1
52 ) {
53 isLastMonthNotFull = false;
54 }
55
56 const result = sign * (difference - +isLastMonthNotFull);
57 return result === 0 ? 0 : result;
58}
59
60// Fallback for modularized imports:
61export default differenceInMonths;