Skip to content
tempo logoTempoDate & Time
Explicit Temporal parsing, timezone-safe arithmetic, and localized date/time formatting for TypeScript.
Version
v2.0.0
Size
3.7 KB gzip
BrowserNode ≥22SSRDeno
TemporalparsenownowInstantisValid View all 35 exports

Why Tempo?

Date/time bugs come from treating an instant and a wall-clock value as interchangeable. Tempo requires an explicit parse target and requires timeZone whenever a wall-clock value becomes an instant.

ts
// Before
const reminder = new Date(meeting.getTime() - 15 * 60_000);

// After
import { parse, shift, toInstant } from '@vielzeug/tempo';

const localMeeting = parse('2026-03-21T10:30:00', { as: 'plainDateTime' });
const meeting = toInstant(localMeeting, { timeZone: 'America/New_York' });
const reminder = shift(meeting, { minutes: -15 }, { timeZone: 'America/New_York' });
FeatureTempodate-fnsNative Date
Bundle size3.7 KB~10 kB0 kB
Zero dependencies @js-temporal/polyfill
Explicit wall-time conversionManual
DST-safe arithmeticManualManual
Localized formatting Intl

Use Tempo when you need Temporal values, explicit timezone rules, and DST-safe operations.

Consider native Date when your data is only elapsed milliseconds and you do not need calendar or timezone behavior.

Installation

sh
pnpm add @vielzeug/tempo
sh
npm install @vielzeug/tempo
sh
yarn add @vielzeug/tempo

Quick Start

Parse a wall-clock input explicitly, attach its timezone, then format it for a user.

ts
import { format, inTimeZone, parse, shift, toInstant } from '@vielzeug/tempo';

const localMeeting = parse('2026-03-21T10:30:00', { as: 'plainDateTime' });
const meeting = toInstant(localMeeting, { timeZone: 'America/New_York' });
const reminder = shift(meeting, { minutes: -15 }, { timeZone: 'America/New_York' });
const text = format(inTimeZone(reminder, 'America/New_York'), {
  locale: 'en-US',
  pattern: 'short',
});

Features

  • parse() — Requires an explicit ISO target: instant, zoned date-time, plain date-time, or plain date.
  • toInstant() / inTimeZone() — Convert wall-clock and absolute values with explicit timezone semantics.
  • shift() / difference() — Perform DST-safe arithmetic and duration calculation.
  • contains() / clamp() — Use named range fields instead of ambiguous positional inputs.
  • classifyExpiry() — Classify fixed elapsed-time thresholds in milliseconds or larger units without month or year approximation.
  • format() / formatRelative() / formatDuration() — Render UI, relative, and duration values through Intl.
  • dateRange() / recurrence() — Lazily generate zoned calendar sequences.

Documentation

See Also

  • Rune — format stable Temporal timestamps before writing structured log records.
  • Vault — derive explicit expiry moments before storing records with TTL policies.