1 | import { normalizeDates } from "./_lib/normalizeDates.js";
|
2 | import { addDays } from "./addDays.js";
|
3 | import { differenceInCalendarDays } from "./differenceInCalendarDays.js";
|
4 | import { isSameDay } from "./isSameDay.js";
|
5 | import { isValid } from "./isValid.js";
|
6 | import { isWeekend } from "./isWeekend.js";
|
7 |
|
8 | /**
|
9 | * The {@link differenceInBusinessDays} function options.
|
10 | */
|
11 |
|
12 | /**
|
13 | * @name differenceInBusinessDays
|
14 | * @category Day Helpers
|
15 | * @summary Get the number of business days between the given dates.
|
16 | *
|
17 | * @description
|
18 | * Get the number of business day periods between the given dates.
|
19 | * Business days being days that aren't in the weekend.
|
20 | * Like `differenceInCalendarDays`, the function removes the times from
|
21 | * the dates before calculating the difference.
|
22 | *
|
23 | * @param laterDate - The later date
|
24 | * @param earlierDate - The earlier date
|
25 | * @param options - An object with options
|
26 | *
|
27 | * @returns The number of business days
|
28 | *
|
29 | * @example
|
30 | * // How many business days are between
|
31 | * // 10 January 2014 and 20 July 2014?
|
32 | * const result = differenceInBusinessDays(
|
33 | * new Date(2014, 6, 20),
|
34 | * new Date(2014, 0, 10)
|
35 | * )
|
36 | * //=> 136
|
37 | *
|
38 | * // How many business days are between
|
39 | * // 30 November 2021 and 1 November 2021?
|
40 | * const result = differenceInBusinessDays(
|
41 | * new Date(2021, 10, 30),
|
42 | * new Date(2021, 10, 1)
|
43 | * )
|
44 | * //=> 21
|
45 | *
|
46 | * // How many business days are between
|
47 | * // 1 November 2021 and 1 December 2021?
|
48 | * const result = differenceInBusinessDays(
|
49 | * new Date(2021, 10, 1),
|
50 | * new Date(2021, 11, 1)
|
51 | * )
|
52 | * //=> -22
|
53 | *
|
54 | * // How many business days are between
|
55 | * // 1 November 2021 and 1 November 2021 ?
|
56 | * const result = differenceInBusinessDays(
|
57 | * new Date(2021, 10, 1),
|
58 | * new Date(2021, 10, 1)
|
59 | * )
|
60 | * //=> 0
|
61 | */
|
62 | export function differenceInBusinessDays(laterDate, earlierDate, options) {
|
63 | const [laterDate_, earlierDate_] = normalizeDates(
|
64 | options?.in,
|
65 | laterDate,
|
66 | earlierDate,
|
67 | );
|
68 |
|
69 | if (!isValid(laterDate_) || !isValid(earlierDate_)) return NaN;
|
70 |
|
71 | const diff = differenceInCalendarDays(laterDate_, earlierDate_);
|
72 | const sign = diff < 0 ? -1 : 1;
|
73 | const weeks = Math.trunc(diff / 7);
|
74 |
|
75 | let result = weeks * 5;
|
76 | let movingDate = addDays(earlierDate_, weeks * 7);
|
77 |
|
78 | // the loop below will run at most 6 times to account for the remaining days that don't makeup a full week
|
79 | while (!isSameDay(laterDate_, movingDate)) {
|
80 | // sign is used to account for both negative and positive differences
|
81 | result += isWeekend(movingDate, options) ? 0 : sign;
|
82 | movingDate = addDays(movingDate, sign);
|
83 | }
|
84 |
|
85 | // Prevent negative zero
|
86 | return result === 0 ? 0 : result;
|
87 | }
|
88 |
|
89 | // Fallback for modularized imports:
|
90 | export default differenceInBusinessDays;
|