# scheduling-sdk

> Brought to you by Recal - A TypeScript SDK for scheduling functionality

Latest version **0.7.0** (published 2026-09-24) · MIT license · 0 weekly downloads

## Install

```sh
npm install scheduling-sdk
pnpm add scheduling-sdk
yarn add scheduling-sdk
bun add scheduling-sdk
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.7.0 |
| Published | 2026-09-24 |
| First published | 2025-06-20 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 133.9 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 59 |
| Author | Recal |
| Maintainers | tkoehlerlg |
| Keywords | scheduling, calendar, appointment, booking, availability, time-slots, timezone, recal, sdk, typescript, schedule, time-management, date-time, slots, busy-time |

## Links

- npm: https://www.npmjs.com/package/scheduling-sdk
- Repository: https://github.com/recal-dev/scheduling-sdk
- Homepage: https://github.com/recal-dev/scheduling-sdk#readme
- Issues: https://github.com/recal-dev/scheduling-sdk/issues
- npm.io page: https://npm.io/package/scheduling-sdk

## Alternatives

- [@js-joda/timezone](https://npm.io/package/@js-joda/timezone.md) — 383.4K weekly downloads
- [chartjs-adapter-moment](https://npm.io/package/chartjs-adapter-moment.md) — 210.8K weekly downloads
- [strftime](https://npm.io/package/strftime.md) — 171.2K weekly downloads
- [vue-flatpickr-component](https://npm.io/package/vue-flatpickr-component.md) — 115.8K weekly downloads
- [timepicker](https://npm.io/package/timepicker.md) — 51.0K weekly downloads

## Recent versions

- 0.7.0 (latest) — 2026-09-24
- 0.6.0 — 2026-09-24
- 0.5.2 — 2025-11-19
- 0.5.0 — 2025-11-19
- 0.5.1 — 2025-11-19
- 0.4.4 — 2025-11-19
- 0.4.3 — 2025-09-12
- 0.4.2 — 2025-09-09
- 0.4.0 — 2025-09-09
- 0.3.2 — 2025-09-09
- 0.3.0 — 2025-09-08
- 0.2.2 — 2025-09-08
- 0.2.1 — 2025-07-22
- 0.2.0 — 2025-07-22
- 0.1.8 — 2025-06-26
- … 7 more at https://npm.io/package/scheduling-sdk/versions

## README

# Scheduling SDK 📆

[![npm version](https://badge.fury.io/js/scheduling-sdk.svg)](https://badge.fury.io/js/scheduling-sdk)
[![Tests](https://github.com/recal-dev/scheduling-sdk/workflows/Tests/badge.svg)](https://github.com/recal-dev/scheduling-sdk/actions)
[![Test Coverage](https://codecov.io/gh/recal-dev/scheduling-sdk/branch/main/graph/badge.svg)](https://codecov.io/gh/recal-dev/scheduling-sdk)

**Brought to you by [Recal](https://recal.dev)** - Your unified calendar API 🚀

A fast TypeScript Scheduling SDK for finding available time slots with **exceptional developer experience**!

## Features

- **🎯 DX First**: Intuitive APIs that feel intuitive to use
- **🔒 Full TypeScript Support**: Complete type safety with excellent IntelliSense
- **📦 Dual Module Support**: Works with both ESM and CommonJS (NestJS compatible!)
- **📖 Extensive Documentation**: In-depth guides, examples, and API references (With help by Claude)
- **⚡ Blazing Fast Performance**: Optimized algorithms for handling large datasets
- **🔧 Flexible Configuration**: Customizable slot duration, padding, splitting, and offset
- **⏰ Timezone-Aware Daily Windows**: Filter slots to local hours using `timezone`, `earliestTime`, and `latestTime`
- **📅 Weekly Availability Patterns**: Define recurring weekly schedules with automatic break management
- **🏗️ Modular Architecture**: Clean separation of concerns for maintainability and testing
- **🧪 98%+ Test Coverage**: Comprehensive testing with edge case handling (Supported by the [CODE's](https://code.berlin) Automated Testing LU)

> **Note**
> The SDK is fully written in TypeScript and uses Bun as the build and test tool. It requires TypeScript 5.0 or later as a peer dependency. While we use Bun for development, the compiled SDK is compatible with any JavaScript runtime (Node.js, Deno, browsers) and works with both ESM and CommonJS module systems.

## Quick Start 💨

```bash
# Install the SDK
npm install scheduling-sdk
# or
bun add scheduling-sdk
```

**Zero configuration required** - start scheduling in seconds! 🚀

### Module Compatibility

The SDK supports both ESM and CommonJS module systems:

```typescript
// ESM (Modern)
import { Scheduler, AvailabilityScheduler } from 'scheduling-sdk'

// CommonJS (NestJS, older Node.js)
const { Scheduler, AvailabilityScheduler } = require('scheduling-sdk')
```

Both formats provide identical functionality and TypeScript support.

## Core Concepts

- **Busy Times**: Periods when you're NOT available (meetings, appointments, breaks)
- **Available Slots**: Free time periods where new events can be scheduled
- **Time Range**: The window (start/end dates) to search for available slots
- **Slot Options**: Configuration for how slots are generated (duration, padding, etc.)

## Basic Usage

### Standard Scheduling

```typescript
import { Scheduler } from 'scheduling-sdk'

// Initialize scheduler with busy times (existing meetings, appointments, etc.)
// Busy times are periods when you're NOT available
const scheduler = new Scheduler([
    {
        start: new Date('2024-01-15T09:00:00Z'), // Meeting starts at 9:00 AM
        end: new Date('2024-01-15T10:00:00Z'), // Meeting ends at 10:00 AM
    },
])

// Find available time slots in a given time range
// This will return all free slots between 8:00 AM and 5:00 PM, excluding the busy time
const availableSlots = scheduler.findAvailableSlots(
    new Date('2024-01-15T08:00:00Z'), // Search from 8:00 AM
    new Date('2024-01-15T17:00:00Z'), // Search until 5:00 PM
    {
        slotDuration: 30, // Each available slot will be 30 minutes long
        padding: 15, // Add 15-minute buffer before and after busy times
        slotSplit: 15, // Generate overlapping slots every 15 minutes
        offset: 0, // No offset from hour boundaries
    }
)

// Result: availableSlots will contain time slots like:
// [
//   { start: "2024-01-15T08:00:00Z", end: "2024-01-15T08:30:00Z" },
//   { start: "2024-01-15T08:15:00Z", end: "2024-01-15T08:45:00Z" },
//   { start: "2024-01-15T10:15:00Z", end: "2024-01-15T10:45:00Z" }, // Note: starts at 10:15 due to 15-min padding
//   { start: "2024-01-15T10:30:00Z", end: "2024-01-15T11:00:00Z" },
//   ...
// ]
```

### Managing Busy Times

```typescript
import { Scheduler } from 'scheduling-sdk'

const scheduler = new Scheduler()

// Add a single busy time (e.g., a new meeting)
scheduler.addBusyTime({
    start: new Date('2024-01-15T14:00:00Z'), // 2:00 PM
    end: new Date('2024-01-15T15:00:00Z'), // 3:00 PM
})

// Add multiple busy times at once (e.g., imported from calendar)
scheduler.addBusyTimes([
    {
        start: new Date('2024-01-15T10:00:00Z'), // Morning standup
        end: new Date('2024-01-15T11:00:00Z'),
    },
    {
        start: new Date('2024-01-15T16:00:00Z'), // Client call
        end: new Date('2024-01-15T17:00:00Z'),
    },
])

// Clear all busy times (e.g., starting fresh)
scheduler.clearBusyTimes()

// Get current busy times (returns a sorted array)
const currentBusyTimes = scheduler.getBusyTimes()
// Returns: [
//   { start: "2024-01-15T10:00:00Z", end: "2024-01-15T11:00:00Z" },
//   { start: "2024-01-15T14:00:00Z", end: "2024-01-15T15:00:00Z" },
//   ...
// ]
```

### Weekly Availability Scheduling

**Business hours made easy ;)**

```typescript
import { AvailabilityScheduler } from 'scheduling-sdk'

// Define when you're generally available (business hours)
// This creates recurring weekly patterns
const availability = {
    schedules: [
        // Monday-Friday: 9 AM to 12 PM (morning hours)
        { days: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], start: '09:00', end: '12:00' },
        // Monday-Friday: 1 PM to 5 PM (afternoon hours, after lunch)
        { days: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], start: '13:00', end: '17:00' },
        // Saturday: 10 AM to 2 PM
        { days: ['saturday'], start: '10:00', end: '14:00' },
    ],
}

const scheduler = new AvailabilityScheduler(availability)

// Add busy times within your available hours (meetings, appointments, etc.)
scheduler.addBusyTimes([
    {
        start: new Date('2024-01-15T14:00:00Z'), // Monday 2 PM meeting
        end: new Date('2024-01-15T15:00:00Z'),
    },
    {
        start: new Date('2024-01-16T10:00:00Z'), // Tuesday 10 AM appointment
        end: new Date('2024-01-16T11:00:00Z'),
    },
])

// Find available slots only within your defined business hours
// This respects both your availability schedule AND busy times
const slots = scheduler.findAvailableSlots(
    new Date('2024-01-15T08:00:00Z'), // Monday 8 AM
    new Date('2024-01-15T18:00:00Z'), // Monday 6 PM
    {
        slotDuration: 60, // 1-hour slots
    }
)
// Result: Only returns slots during business hours (9-12, 1-5) excluding busy times
// [
//   { start: "2024-01-15T09:00:00Z", end: "2024-01-15T10:00:00Z" },
//   { start: "2024-01-15T13:00:00Z", end: "2024-01-15T14:00:00Z" },
//   { start: "2024-01-15T15:00:00Z", end: "2024-01-15T16:00:00Z" },
//   { start: "2024-01-15T16:00:00Z", end: "2024-01-15T17:00:00Z" },
//   ...
// ]
```

### Daily Time Windows and Timezone Filtering

Restrict generated slots to specific local hours by providing a timezone and a daily window.

Core `Scheduler` usage:

```typescript
import { Scheduler } from 'scheduling-sdk'

const scheduler = new Scheduler()

// Search the whole day in UTC, but only return slots that START between 9:00 and 17:00 New York time
const slots = scheduler.findAvailableSlots(
  new Date('2024-01-15T00:00:00Z'),
  new Date('2024-01-15T23:59:59Z'),
  {
    slotDuration: 60,
    timezone: 'America/New_York',
    earliestTime: '09:00',
    latestTime: '17:00',
  }
)
// In January, America/New_York is UTC-5, so this filters to 14:00–22:00 UTC
```

Availability `AvailabilityScheduler` usage (timezone can be omitted in options; it falls back to the scheduler’s timezone):

```typescript
import { AvailabilityScheduler } from 'scheduling-sdk'

const availability = {
  schedules: [{ days: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], start: '09:00', end: '17:00' }],
}

const scheduler = new AvailabilityScheduler(availability, 'America/New_York')

const slots = scheduler.findAvailableSlots(
  new Date('2024-01-15T00:00:00Z'),
  new Date('2024-01-15T23:59:59Z'),
  {
    slotDuration: 30,
    // No timezone here → uses scheduler's timezone automatically
    earliestTime: 9 * 60,  // numbers = minutes since midnight
    latestTime: '24:00',   // string format supports '24:00' for end of day
  }
)
```

Daily window parameters:

- `timezone` (string, IANA ID, e.g. `"America/New_York"`) — required when using `earliestTime`/`latestTime` with the core `Scheduler`.
- `earliestTime` (string `HH:mm` or number minutes) — lowest local start time to allow.
- `latestTime` (string `HH:mm` or number minutes) — highest local start time to allow; supports `"24:00"` or `1440`.

Notes:

- If you use `AvailabilityScheduler`, you may omit `timezone` in `findAvailableSlots` when using `earliestTime`/`latestTime`; it will default to the scheduler’s timezone.
- If you use the core `Scheduler`, providing `earliestTime`/`latestTime` without `timezone` will throw a validation error.
- Daily windows filter by slot START time.

### Allowing Overlaps (K-overlaps)

You can allow up to K overlapping busy intervals by setting `maxOverlaps` in options. K is how many busy times may cover a moment before it stops being offered, counted after padding, so `maxOverlaps: 0` is the default behaviour and `maxOverlaps: 1` still refuses a moment two busy times cover. This uses an optimized algorithm internally.

```typescript
const slots = scheduler.findAvailableSlots(
  new Date('2024-01-15T09:00:00Z'),
  new Date('2024-01-15T17:00:00Z'),
  {
    slotDuration: 30,
    slotSplit: 15,
    maxOverlaps: 1, // allow 1 collision
  }
)
```

### SchedulingOptions reference

```ts
interface SchedulingOptions {
  // Required
  slotDuration: number

  // Optional
  padding?: number
  slotSplit?: number
  offset?: number
  maxOverlaps?: number

  // Daily window filtering (timezone-aware)
  timezone?: string
  earliestTime?: string | number // 'HH:mm' or minutes since midnight
  latestTime?: string | number   // 'HH:mm' or minutes since midnight; supports '24:00' or 1440
}
```

## Documentation 📚

- **📖 [Getting Started](docs/getting-started.md)** - Installation and basic usage
- **📋 [API Reference](docs/api-reference.md)** - Complete API documentation
- **🧠 [Core Concepts](docs/core-concepts.md)** - Understanding scheduling concepts
- **⏰ [Availability Scheduler](docs/availability-scheduler.md)** - Weekly availability patterns and scheduling
- **💡 [Recipes](docs/recipes.md)** - Practical usage examples
- **⚡ [Performance Guide](docs/performance.md)** - Optimization and benchmarks
- **🤝 [Contributing](docs/contributing.md)** - Development and contribution guidelines

## Development 💻

```bash
# Install dependencies
bun install

# Run in development mode
bun run dev

# Build for production
bun run build

# Run tests
bun test

# Type checking
bun run typecheck
```

## Architecture 🏗️

The SDK is built with a modular architecture:

```
src/
├── types/              # TypeScript type definitions
├── helpers/            # Utility functions organized by domain
│   ├── time/           # Date/time calculations and alignments
│   ├── busy-time/      # Busy time operations (padding, merging, overlap)
│   ├── slot/           # Slot generation and filtering
│   └── availability/   # Weekly availability conversion
├── validators/         # Input validation functions
├── core/              # Main Scheduler class
├── availability/      # AvailabilityScheduler class
└── utils/             # Shared constants and utilities
```

## Performance ⚡

Optimized for speed with target performance:

- < 1ms for 100 busy times
- < 10ms for 1000 busy times
- < 100ms for 10000 busy times

See [Performance Guide](docs/performance.md) for detailed benchmarks.

## License

MIT

## Contributing 🤝

Please read our [Contributing Guide](docs/contributing.md) for development setup and contribution guidelines.

## Credits 👨‍💻

Engineering by [@tkoehlerlg](https://github.com/tkoehlerlg)

---
_Source: https://npm.io/package/scheduling-sdk · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
