import toDate from '../toDate/index'
import requiredArgs from '../_lib/requiredArgs/index'
/**
* @name areIntervalsOverlapping
* @category Interval Helpers
* @summary Is the given time interval overlapping with another time interval?
*
* @description
* Is the given time interval overlapping with another time interval? Adjacent intervals do not count as overlapping.
*
* ### 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 `areRangesOverlapping` to `areIntervalsOverlapping`.
* 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
*
* areRangesOverlapping(
* new Date(2014, 0, 10), new Date(2014, 0, 20),
* new Date(2014, 0, 17), new Date(2014, 0, 21)
* )
*
* // v2.0.0 onward
*
* areIntervalsOverlapping(
* { 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/types/Interval}
* @param {Interval} intervalRight - the second interval to compare. See [Interval]{@link docs/types/Interval}
* @param {Object} [options] - the object with options
* @param {Boolean} [options.inclusive=false] - whether the comparison is inclusive or not
* @returns {Boolean} whether the time intervals are overlapping
* @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:
* areIntervalsOverlapping(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 17), end: new Date(2014, 0, 21) }
* )
* //=> true
*
* @example
* // For non-overlapping time intervals:
* areIntervalsOverlapping(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 21), end: new Date(2014, 0, 22) }
* )
* //=> false
*
* @example
* // For adjacent time intervals:
* areIntervalsOverlapping(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 20), end: new Date(2014, 0, 30) }
* )
* //=> false
*
* @example
* // Using the inclusive option:
* areIntervalsOverlapping(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 20), end: new Date(2014, 0, 24) }
* )
* //=> false
* areIntervalsOverlapping(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 20), end: new Date(2014, 0, 24) },
* { inclusive: true }
* )
* //=> true
*/
export default function areIntervalsOverlapping(
dirtyIntervalLeft: Interval,
dirtyIntervalRight: Interval,
options = { inclusive: false }
): boolean {
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')
}
if (options.inclusive) {
return leftStartTime <= rightEndTime && rightStartTime <= leftEndTime
}
return leftStartTime < rightEndTime && rightStartTime < leftEndTime
}