UNPKG

2.42 kBJavaScriptView Raw
1import { getTimezoneOffsetInMilliseconds } from "./_lib/getTimezoneOffsetInMilliseconds.js";
2import { millisecondsInDay } from "./constants.js";
3import { toDate } from "./toDate.js";
4
5/**
6 * @name getOverlappingDaysInIntervals
7 * @category Interval Helpers
8 * @summary Get the number of days that overlap in two time intervals
9 *
10 * @description
11 * Get the number of days that overlap in two time intervals. It uses the time
12 * between dates to calculate the number of days, rounding it up to include
13 * partial days.
14 *
15 * Two equal 0-length intervals will result in 0. Two equal 1ms intervals will
16 * result in 1.
17 *
18 * @param intervalLeft - The first interval to compare.
19 * @param intervalRight - The second interval to compare.
20 * @param options - An object with options
21 *
22 * @returns The number of days that overlap in two time intervals
23 *
24 * @example
25 * // For overlapping time intervals adds 1 for each started overlapping day:
26 * getOverlappingDaysInIntervals(
27 * { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
28 * { start: new Date(2014, 0, 17), end: new Date(2014, 0, 21) }
29 * )
30 * //=> 3
31 *
32 * @example
33 * // For non-overlapping time intervals returns 0:
34 * getOverlappingDaysInIntervals(
35 * { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
36 * { start: new Date(2014, 0, 21), end: new Date(2014, 0, 22) }
37 * )
38 * //=> 0
39 */
40
41export function getOverlappingDaysInIntervals(intervalLeft, intervalRight) {
42 const [leftStart, leftEnd] = [
43 +toDate(intervalLeft.start),
44 +toDate(intervalLeft.end),
45 ].sort((a, b) => a - b);
46 const [rightStart, rightEnd] = [
47 +toDate(intervalRight.start),
48 +toDate(intervalRight.end),
49 ].sort((a, b) => a - b);
50
51 // Prevent NaN result if intervals don't overlap at all.
52 const isOverlapping = leftStart < rightEnd && rightStart < leftEnd;
53 if (!isOverlapping) return 0;
54
55 // Remove the timezone offset to negate the DST effect on calculations.
56 const overlapLeft = rightStart < leftStart ? leftStart : rightStart;
57 const left = overlapLeft - getTimezoneOffsetInMilliseconds(overlapLeft);
58 const overlapRight = rightEnd > leftEnd ? leftEnd : rightEnd;
59 const right = overlapRight - getTimezoneOffsetInMilliseconds(overlapRight);
60
61 // Ceil the number to include partial days too.
62 return Math.ceil((right - left) / millisecondsInDay);
63}
64
65// Fallback for modularized imports:
66export default getOverlappingDaysInIntervals;