temporal-kit
v0.2.0
Published
A modern, functional utility library for the Temporal API - experiment with Temporal today.
Maintainers
Readme
Temporal Kit
Modern, functional utilities for the Temporal API. Experiment with the future of JavaScript dates today.
Temporal Kit is a lightweight, tree-shakable library that fills the gap between the raw Temporal API and the ergonomic needs of daily development. It provides the missing helper functions—like startOf, isBetween, or formatRelative—in a pure, functional, and type-safe way.
Quick Start
Installation
npm install temporal-kitBasic Usage
import { isPlainDate, add, startOf } from 'temporal-kit';
// Or with polyfill for legacy environments:
import { isPlainDate } from 'temporal-kit/polyfilled';💡 See it in action: Check out the
examplesfor runnable code samples covering type guards, polyfill usage, TypeScript integration, and more.
Common Recipes
import { formatRelative, startOf, endOf, add, nextDay, isBetween } from 'temporal-kit';
import { Temporal } from 'temporal-polyfill';
const now = Temporal.Now.zonedDateTimeISO();
// 1. Relative Time
formatRelative(now.subtract({ minutes: 5 })); // "5 minutes ago"
// 2. Find next Friday
const nextFriday = nextDay(now, 5); // 5 = Friday
// 3. Check if date is in range
isBetween(now, startOf(now, 'year'), endOf(now, 'year')); // true
// 4. Business Days
import { addBusinessDays, isWeekend } from 'temporal-kit';
const monday = addBusinessDays(friday, 1); // Skips weekendDocumentation
- API Reference - Complete function reference with examples
- Usage Examples - Practical examples for common use cases
- Best Practices - Comprehensive guide for using temporal-kit effectively
1. Why Temporal Kit?
Temporal is arriving as the modern standard for date/time handling in JavaScript, with precise primitives (Instant, ZonedDateTime, PlainDate/Time). By design, Temporal focuses on correctness and intentionally leaves out many convenience helpers—things like startOf/endOf, humanized formatting, or common comparison utilities. This is deliberate: Temporal provides the foundation, but everyday ergonomics are better handled by libraries.
Temporal Kit fills this gap with a focused, Temporal-first toolkit that provides:
- Common Ergonomic Helpers: The everyday utilities teams need (
startOf,endOf,add,subtract,isBefore,isAfter) - Intl-First Formatting: Locale-aware formatting without massive locale files
- Functional-First Design: Pure functions, tree-shakable, composable—no hidden state
- Universal Compatibility: Runs anywhere JavaScript runs (Browsers, Node.js, Edge) with native Temporal or polyfill
- Explicit over Magic: No global config, no implicit conversions, no surprises
The Goal: Stop reinventing the same small, error-prone utilities across projects. Instead, share a well-tested, modern implementation that covers 95% of everyday needs while staying lightweight and stable.
2. Core Philosophy
A. Narrow Scope, High Quality
Rather than replicating every feature from older libraries, Temporal Kit focuses on:
- The 95% Use Case: Common helpers that most projects need
- Well-Tested Primitives: Battle-tested implementations to avoid subtle bugs
- Lightweight Core: Keep it fast and stable by staying focused
The remaining 5%—specialized needs like complex recurring patterns, custom calendar systems, or advanced timezone logic—are better served by dedicated libraries that can focus deeply on those specific domains. For example, rrule-temporal handles recurring date calculations with iCalendar RRULE support.
B. "Temporal First" & ISO Compliance
- We work directly with
Temporalobjects (ZonedDateTime,PlainDate, etc.) - Clean Break: No legacy
Datequirks. Months are 1-indexed. No timezone surprises. - Intl-First: Formatting uses
Intl.DateTimeFormatby default—correct localization without massive locale files.
C. Functional-First API
A pure functional API optimized for composition, tree-shaking, and modern JavaScript patterns.
import { add, startOf, pipe } from 'temporal-kit'
// Direct composition
const result = add(startOf(date, 'day'), { hours: 1 })
// With pipe utility
const result = pipe(
date,
d => startOf(d, 'day'),
d => add(d, { hours: 1 })
)Benefits:
- Perfect tree-shaking - only bundle what you use
- Composable and testable
- Modern functional patterns
- Future-ready for JS pipeline operator (
|>)
Why no method chaining? Fluent APIs (like
moment().add().startOf()) are convenient but break tree-shaking because the wrapper object must bundle all available methods. By sticking to pure functions,temporal-kitremains tiny (~11KB) and aligns with the future of JavaScript (Pipeline Operator).
D. Polyfill Strategy (Explicit Opt-in)
We adopt a robust strategy for compatibility:
temporal-kit: Lean. ExpectsTemporalto exist. Throws helpful error if missing.temporal-kit/polyfilled: Importstemporal-polyfillautomatically for legacy environments (requirestemporal-polyfillpeer dependency).
3. Architecture
Directory Structure
src/
├── types/ # Core type definitions (DateLike, TimeLike unions)
├── guards/ # Type guards (isPlainDate, isZonedDateTime, etc.)
├── compare/ # Comparison functions (isBefore, isAfter, min, max)
├── convert/ # Creation & conversion (now, fromISO, explicit conversions)
├── format/ # Intl-based formatting (format, formatTime, formatDateTime, formatRelative)
├── math/ # Arithmetic (add, subtract, startOf, endOf)
├── utils/ # Utilities (pipe, compose)
├── index.ts # Main entry (expects native Temporal)
└── polyfilled.ts # Auto-loads polyfill for legacy environmentsImplementation Details
- Zero Runtime Dependencies: We build directly on native
TemporalAPIs. Polyfill is optional. - Type-Safe: Full TypeScript support with strict mode and cutting-edge compiler options.
- Dual Entry Points:
temporal-kit- Expects native Temporaltemporal-kit/polyfilled- Auto-loads polyfill
- Perfect Tree-Shaking:
sideEffects: falseensures optimal bundle sizes. - Modern Tooling:
- Biome - Fast linting/formatting with performance rules
- Vitest - Type-checked tests with 100% coverage threshold
- tsup - ESNext bundling with optimized tree-shaking
- TypeScript 5.x - Latest compiler features enabled
- Testing Strategy: 100% code coverage including:
- Type guards and runtime checks
- Comparison and conversion functions
- Calendar arithmetic and boundary operations
- Intl-based formatting with locale support
- Functional composition utilities
- Error handling and edge cases
4. Features & Capabilities
- Comparison:
isBefore,isAfter,isSame,isBetween,min,max,clamp - Arithmetic:
add,subtract,startOf,endOf - Formatting:
format,formatTime,formatDateTime,formatRelative(Intl-based) - Conversion:
now,fromISO - Ranges:
rangesOverlap,eachDayOfInterval,stepInterval - Collections:
sortAsc,sortDesc,closestTo - Validation:
isValidDateString,isValidTimezone,getTimezoneName - Functional Utils:
pipe,compose
5. Contributing
We welcome contributions! Please see our Contributing Guide for details on:
Development setup
Quality checks (Linting, Typechecking, Testing)
Release process
Project standards
ESNext target - No legacy transpilation, minimal output
6. Comparison
| Feature | date-fns | Luxon | Native Temporal | Temporal Kit |
| :--- | :--- | :--- | :--- | :--- |
| Base Object | Legacy Date ⚠️ | Custom Class | Temporal | Temporal |
| Paradigm | Functional | OO / Immutable | OO / Verbose | Functional |
| Timezones | Separate Helpers | Built-in | Native | Native |
| Tree-Shaking| ✅ Yes | ❌ No | N/A | ✅ Yes |
| Polyfill Needed?| No | No | No (Native) | Optional |
| Best For... | Legacy Projects | Heavy Date Apps | Low-level Logic | Modern Apps |
