differenceInBusinessDays.js 2.6 KB

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