1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
import toDate from '../toDate/index'
import requiredArgs from '../_lib/requiredArgs/index'
import { Interval } from '../types'
const MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000
/**
* @name getOverlappingDaysInIntervals
* @category Interval Helpers
* @summary Get the number of days that overlap in two time intervals
*
* @description
* Get the number of days that overlap in two time intervals
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* - The function was renamed from `getOverlappingDaysInRanges` to `getOverlappingDaysInIntervals`.
* This change was made to mirror the use of the word "interval" in standard ISO 8601:2004 terminology:
*
* ```
* 2.1.3
* time interval
* part of the time axis limited by two instants
* ```
*
* Also, this function now accepts an object with `start` and `end` properties
* instead of two arguments as an interval.
* This function now throws `RangeError` if the start of the interval is after its end
* or if any date in the interval is `Invalid Date`.
*
* ```javascript
* // Before v2.0.0
*
* getOverlappingDaysInRanges(
* new Date(2014, 0, 10), new Date(2014, 0, 20),
* new Date(2014, 0, 17), new Date(2014, 0, 21)
* )
*
* // v2.0.0 onward
*
* getOverlappingDaysInIntervals(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 17), end: new Date(2014, 0, 21) }
* )
* ```
*
* @param {Interval} intervalLeft - the first interval to compare. See [Interval]{@link docs/Interval}
* @param {Interval} intervalRight - the second interval to compare. See [Interval]{@link docs/Interval}
* @returns {Number} the number of days that overlap in two time intervals
* @throws {TypeError} 2 arguments required
* @throws {RangeError} The start of an interval cannot be after its end
* @throws {RangeError} Date in interval cannot be `Invalid Date`
*
* @example
* // For overlapping time intervals adds 1 for each started overlapping day:
* getOverlappingDaysInIntervals(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 17), end: new Date(2014, 0, 21) }
* )
* //=> 3
*
* @example
* // For non-overlapping time intervals returns 0:
* getOverlappingDaysInIntervals(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 21), end: new Date(2014, 0, 22) }
* )
* //=> 0
*/
export default function getOverlappingDaysInIntervals(
dirtyIntervalLeft: Interval,
dirtyIntervalRight: Interval
): number {
requiredArgs(2, arguments)
const intervalLeft = dirtyIntervalLeft || {}
const intervalRight = dirtyIntervalRight || {}
const leftStartTime = toDate(intervalLeft.start).getTime()
const leftEndTime = toDate(intervalLeft.end).getTime()
const rightStartTime = toDate(intervalRight.start).getTime()
const rightEndTime = toDate(intervalRight.end).getTime()
// Throw an exception if start date is after end date or if any date is `Invalid Date`
if (!(leftStartTime <= leftEndTime && rightStartTime <= rightEndTime)) {
throw new RangeError('Invalid interval')
}
const isOverlapping =
leftStartTime < rightEndTime && rightStartTime < leftEndTime
if (!isOverlapping) {
return 0
}
const overlapStartDate =
rightStartTime < leftStartTime ? leftStartTime : rightStartTime
const overlapEndDate = rightEndTime > leftEndTime ? leftEndTime : rightEndTime
const differenceInMs = overlapEndDate - overlapStartDate
return Math.ceil(differenceInMs / MILLISECONDS_IN_DAY)
}
|