Date range operations: overlap, gaps, merge, split

Import

import { ... } from 'ts-time-utils/dateRange';

Examples

Merge & Overlap

Merge overlapping ranges and check overlaps

import { mergeDateRanges, dateRangeOverlap, getIntersection } from 'ts-time-utils/dateRange';

// Check overlap
const range1 = {
  start: new Date('2025-01-01'),
  end: new Date('2025-01-15')
};
const range2 = {
  start: new Date('2025-01-10'),
  end: new Date('2025-01-20')
};

console.log(dateRangeOverlap(range1, range2)); // true

// Get intersection
const intersection = getIntersection(range1, range2);
console.log(intersection);
// { start: Jan 10, end: Jan 15 }

// Merge overlapping ranges
const ranges = [
  { start: new Date('2025-01-01'), end: new Date('2025-01-10') },
  { start: new Date('2025-01-05'), end: new Date('2025-01-15') },
  { start: new Date('2025-01-20'), end: new Date('2025-01-25') },
];

const merged = mergeDateRanges(ranges);
console.log(merged.length); // 2 ranges after merge

Find Gaps

Find available time slots between busy periods

import { findGaps, splitRange } from 'ts-time-utils/dateRange';

// Find gaps between busy times (e.g., meetings)
const busyTimes = [
  { start: new Date('2025-01-01T09:00'), end: new Date('2025-01-01T11:00') },
  { start: new Date('2025-01-01T14:00'), end: new Date('2025-01-01T16:00') },
];

const workday = {
  start: new Date('2025-01-01T08:00'),
  end: new Date('2025-01-01T18:00'),
};

const gaps = findGaps(busyTimes, workday);
gaps.forEach(gap => {
  console.log(`Free: ${gap.start.toTimeString().slice(0,5)} - ${gap.end.toTimeString().slice(0,5)}`);
});
// Free: 08:00 - 09:00
// Free: 11:00 - 14:00
// Free: 16:00 - 18:00

// Split range into chunks
const month = {
  start: new Date('2025-01-01'),
  end: new Date('2025-01-31'),
};
const weeks = splitRange(month, 1, 'week');
console.log(`January has ${weeks.length} weeks`);