UNPKG

@everwhen/temporal

Version:
87 lines (86 loc) 2.9 kB
import { Duration } from "./duration.js"; import { parse, stringify } from "./fn/json.js"; import { assertIntervalLike, isIntervalLike, isPoint } from "./is.js"; import {} from "./point.js"; export class Interval { start; end; constructor(start, end) { this.start = start; this.end = end; this.validate(); } static from(value) { let intervalLike; if (typeof value === 'string') { const parsed = parse(value); assertIntervalLike(parsed); intervalLike = parsed; } else { intervalLike = { start: isPoint(value) ? value : value.start, end: isPoint(value) ? value : value.end, }; } return new Interval(intervalLike.start, intervalLike.end); } static compare(a, b) { const startComparison = a.start.compare(b.start); if (startComparison !== 0) { return startComparison; } return a.end.compare(b.end); } static overlaps(a, b, options) { if (options?.inclusive) { return a.start.compare(b.end) <= 0 && a.end.compare(b.start) >= 0; } return a.start.compare(b.end) < 0 && a.end.compare(b.start) > 0; } validate() { if (this.start.compare(this.end) > 0) { throw new Error(`Invalid interval: end (${this.end.toString()}) cannot be before start (${this.start.toString()})`); } } isBefore(other) { const otherPoint = isIntervalLike(other) ? other.start : other; return this.end.compare(otherPoint) < 0; } isAfter(other) { const otherPoint = isIntervalLike(other) ? other.end : other; return this.start.compare(otherPoint) > 0; } equals(other) { return this.start.equals(other.start) && this.end.equals(other.end); } overlaps(other, options) { if (options?.inclusive) { return (this.start.compare(other.end) <= 0 && this.end.compare(other.start) >= 0); } return (this.start.compare(other.end) < 0 && this.end.compare(other.start) > 0); } contains(value) { if (isPoint(value)) { return this.start.compare(value) <= 0 && this.end.compare(value) >= 0; } return (this.start.compare(value.start) <= 0 && this.end.compare(value.end) >= 0); } merge(other) { const start = this.start.compare(other.start) <= 0 ? this.start : other.start; const end = this.end.compare(other.end) >= 0 ? this.end : other.end; return new Interval(start, end); } toJSON() { return stringify({ start: this.start, end: this.end, }); } toString() { return `[${this.start.toString()}, ${this.end.toString()}]`; } get duration() { return this.start.until(this.end); } }