Skip to content

Tempo Cookbook ​

A collection of recipes for solving common date and time challenges using Tempo.

Table of Contents ​

  1. The Basics
  2. Parsing Challenges
  3. Manipulation and Calculations
  4. Timezones and Locales
  5. Business Logic and Terms
  6. Formatting and Localization
  7. Interoperability

The Basics ​

How do I get the current date and time? ​

When invoked without arguments, the constructor initializes to the current date and time.

typescript
const now = new Tempo();
console.log(now.toString()); // e.g. "2026-07-31T14:42:11+10:00[Australia/Sydney]"

Get "Now" in UTC ​

typescript
const utcNow = new Tempo({ timeZone: 'UTC' });

How do I format a date for my UI? ​

Use the placeholder syntax in the .format() method.

typescript
const t = new Tempo('2024-12-25');
t.format('{dd} {mon} {yyyy}');  // "25 December 2024"
t.format('{h12}:{mi}');         // "12:00am"

How do I check if a date is valid? ​

typescript
const t = new Tempo('invalid-date');
if (t.isValid) {
  // ...
}

Global Configuration ​

You can initialize global defaults that apply to all future Tempo instances.

typescript
Tempo.init({
  timeZone: 'UTC',
  locale: 'en-GB',
  silent: true
});

👉 Learn More: Configuration Guide


Parsing Challenges ​

Parsing "Ambiguous" Digits (US vs UK) ​

Tempo intelligently resolves ambiguous dates like 04012026 based on your timezone.

typescript
const us = new Tempo('04012026', { timeZone: 'America/New_York' }); 
console.log(us.format('{mon} {dd}')); // "April 01"

👉 Learn More: Ambiguity Resolution Guide

Handling Relative Strings ​

Tempo natively understands human-readable offsets.

typescript
new Tempo('yesterday');
new Tempo('next Friday');
new Tempo('2 weeks ago');
new Tempo('tomorrow afternoon');

👉 Learn More: You can seamlessly localize relative phrases (e.g. next to prochain) by reading the Internationalized Parsing Guide.

Parsing Unix Timestamps ​

Tempo handles both milliseconds (Number) and nanoseconds (BigInt).

typescript
new Tempo(1716163200000);         // Milliseconds
new Tempo(1716163200000000000n);  // Nanoseconds

Manipulation and Calculations ​

Add or Subtract Time ​

Tempo instances are immutable; add() returns a new instance.

typescript
const deadline = new Tempo().add({ days: 7, hours: 2 });
const past = new Tempo().add({ months: -1 });

// You can also step by semantic Terms using the `#` prefix!
const t1 = new Tempo('2024-05-15'); // Middle of Q2
const t2 = t1.add({ '#quarter': 1 }); // Middle of Q3: "2024-08-14" (approx)

Jumping to Boundaries (start, mid, end) ​

The .set() method allows you to jump to the boundaries of native units (like months or years) or semantic Terms (using the # prefix). You can specify whether to land on the inclusive start, inclusive end, or the exact center.

typescript
// Native Units
const monthStart = new Tempo().set({ month: 'start' });

// Semantic Terms (Lands on 30-Sep 23:59:59.999... Inclusive End)
const qtrEnd = new Tempo('2024-07-15').set({ '#quarter': 'end' });

// Lands on the arithmetic nanosecond midpoint of the period
const qtrMid = new Tempo().set({ '#quarter': 'mid' });

Slick Object Mutations ​

You can navigate relative to your current date by using Slick Shorthand operators directly inside .set(). Use the snippet shorthand keys (yy, mm, ww, dd, wkd, etc.) and provide a string payload containing a directional modifier:

typescript
const t = new Tempo('2024-05-20'); // Monday
t.set({ mm: '>2' });               // July 20th
t.set({ wkd: '>Fri' });            // May 24th

👉 Learn More: To read about advanced chaining, order-of-operations, and architectural limitations, see the Slick Object Mutations Deep Dive.

How long until a deadline? (until) ​

typescript
const t = new Tempo();
const daysLeft = t.until('2025-01-01', 'days');
console.log(`${daysLeft} days remaining`);

Relative Time (since) ​

Generate human-readable relative time strings instantly.

typescript
const t = new Tempo('yesterday');
console.log(t.since()); // "1d ago"

Timezones and Locales ​

Convert Time to Another Zone ​

typescript
const nyc = new Tempo('2024-05-20 10:00', { timeZone: 'America/New_York' });
const london = nyc.set({ timeZone: 'Europe/London' });

console.log(nyc.format('{hh}:{mi}'));    // "10:00"
console.log(london.format('{hh}:{mi}')); // "15:00"

Dynamic / Multi-Tenant Context (Functional Options) ​

Context options (timeZone, locale, calendar, sphere) accept supplier functions (() => string). Tempo resolves suppliers at instantiation time to construct an immutable, frozen instance:

typescript
import { AsyncLocalStorage } from 'node:async_hooks';

const requestContext = new AsyncLocalStorage<{ timeZone: string; locale: string }>();

// Configure dynamic suppliers that evaluate against current request context
const t = new Tempo('now', {
  timeZone: () => requestContext.getStore()?.timeZone || 'UTC',
  locale: () => requestContext.getStore()?.locale || 'en-US'
});

👉 Learn More: See the Configuration Guide for details on functional options and immutability guarantees.


Business Logic and Terms ​

Is it the weekend? ​

For simple ISO checks, Saturday is 6 and Sunday is 7:

typescript
const t = new Tempo();
const isWeekend = t.dow >= 6; // Saturday = 6, Sunday = 7

For international applications, use the locale-aware t.intl.weekend array (backed by Intl.Locale.prototype.getWeekInfo() and its fallback resolver), which reflects regional weekend days (e.g. [5, 6] for Friday & Saturday in Middle Eastern locales like ar-SA):

typescript
// Standard weekend ([6, 7] for Saturday and Sunday in en-US)
const us = new Tempo({ locale: 'en-US' });
const isUsWeekend = us.intl.weekend.includes(us.dow);

// Regional weekend ([5, 6] for Friday and Saturday in ar-SA)
const sa = new Tempo({ locale: 'ar-SA' });
const isSaWeekend = sa.intl.weekend.includes(sa.dow);

What Fiscal Quarter are we in? ​

Using the qtr Term plugin (term.qtr is a convenient alias for the full term.quarter property).

typescript
const t = new Tempo();
console.log(`Current Quarter: ${t.term.qtr}`); // "Q1", "Q2", etc.

Hemispheric Seasons ​

Tempo Terms are hemisphere-aware.

typescript
const sydney = new Tempo('2024-07-01', { sphere: 'south' });
console.log(sydney.term.szn); // "Winter"

const london = new Tempo('2024-07-01', { sphere: 'north' });
console.log(london.term.szn); // "Summer"

// or even via the timeZone setting
console.log(new Tempo({ timeZone: 'America/New_York' }).term.szn); // "Summer"
console.log(new Tempo({ timeZone: 'Australia/Sydney' }).term.szn); // "Winter"

Formatting and Localization ​

Semantic Formatting ​

Use specific Term tokens like {#quarter} or {#season} to automatically embed a Term's label (or key) into a format string.

typescript
const t = new Tempo();
console.log(t.format('We are currently in the {#quarter}')); // "We are currently in the First Quarter"

Format Modifiers & Localization ​

Format strings support chained colon-modifiers (e.g., :upper, :locale, :ord) to dynamically change the presentation casing or delegate to the native Intl API. You can stack them to get the exact presentation required!

typescript
const t = new Tempo('2024-05-15 15:30', { locale: 'fr-FR' });

t.format('{mon:upper}');             // "MAY" (English Default -> UpperCase)
t.format('{mon:long}');              // "mai" (Native French Intl output via styling bridge)
t.format('{mon:long:upper} {dd}');   // "MAI 15" (Native French Intl output)

👉 Learn More: See the Smart Formatting Guide for the complete list of available modifiers.

TIP

Tired of typing styling modifiers?
If you find yourself repeatedly writing :long or :short for the same localized date structure, save it to the global FORMATS registry! This creates a clean, reusable shortcut:

typescript
Tempo.init({
    locale: 'fr-FR',
    registry: {
        formats: {
            'ui-date': '{wkd:long}, {dd:raw} {mon:long} {yyyy}'
        }
    }
});

t.format('ui-date'); // Resolved with all modifiers intact!

Note: Format keys are resolved case-sensitively from the global registry.formats object. If the requested key is not found, Tempo will simply treat the provided string as a literal layout string rather than throwing an error.

👉 Learn More: To build custom zero-overhead logic evaluators (like Fiscal Years or native Intl bridges), read the Custom Format Tokens Deep Dive.

👉 Learn More:


Ticker Plugin ​

The Ticker engine is a community plugin for precisely driving business logic (like recurring billing or reporting cycles) on specific date boundaries.

typescript
// Drive internal reporting precisely when a new quarter begins
await using quarterly = Tempo.ticker({ '#quarter': 1 });

for await (const t of quarterly) {
  generateReport(t.term.qtr);
}

👉 Learn More: See the Ticker Plugin Documentation for detailed configuration, term-driven intervals, and await using syntax requirements.


Format & Parse Dialects Plugin (Moment, Luxon, SQL, POSIX, PHP) ​

If you are migrating existing code or layouts from Moment.js, Luxon, date-fns, POSIX strftime, PHP, or SQL, use the @magmacomputing/tempo-plugin-dialects community plugin.

typescript
// Zero-config drop-in import automatically mounts dialect shims:
import '@magmacomputing/tempo-plugin-dialects/install';

const t = new Tempo('2026-10-24T15:30:00');

// Luxon convenience shim (.toFormat)
t.toFormat('yyyy-MM-dd HH:mm:ss');          // "2026-10-24 15:30:00"

// LDML & Moment parsing
Tempo.fromFormat('2026-10-24', 'yyyy-MM-dd'); // LDML parsing via Luxon shim
Tempo.dialects.parse('2026-10-24', 'YYYY-MM-DD', 'moment'); // Moment layout parsing

// Direct dialect formatters
t.dialects.sql('YYYY-MM-DD HH24:MI:SS');     // Oracle / PostgreSQL TO_CHAR
t.dialects.php('Y-m-d H:i:s');               // PHP date()
t.dialects.go('2006-01-02 15:04:05');        // Go reference layout

👉 Learn More: See the Dialects Plugin Documentation for full token specifications, multi-candidate parsing fallbacks, and cross-ecosystem translation.


Interoperability ​

Converting to / from Native Date ​

typescript
const date = new Tempo().toDate();
const tempo = new Tempo(new Date());

Converting to Temporal Objects ​

typescript
const zdt = new Tempo().zdt;             // Temporal.ZonedDateTime (or .toDateTime())
const instant = new Tempo().toInstant(); // Temporal.Instant
const pdt = new Tempo().toPlainDate();   // Temporal.PlainDate

Sorting an array of Tempos ​

typescript
const dates = [new Tempo('tomorrow'), new Tempo('yesterday'), new Tempo('today')];
dates.sort(Tempo.compare); // Sorts chronologically

Released under the MIT License.