temporal

A Dart implementation of the TC39 Temporal proposal — modern, immutable date and time types with unambiguous ISO 8601 calendar arithmetic, full IANA timezone support, and multi-calendar awareness.

This is the cross-platform umbrella package. A single import works on every target:

Platform Backend
Web (dart2js / dart2wasm) temporal_js — browser native Temporal API via dart:js_interop
Dart VM / Flutter native temporal_native — Rust temporal_rs via FFI

Why not DateTime?

DateTime is either local or UTC — mixing them silently produces wrong results. There is no type for "just a date" or "just a time", so you always carry dead-weight fields. temporal models each concept as its own type, making category errors a compile-time failure instead of a runtime surprise.

Features

  • PlainDate — a calendar date (year, month, day) with no time or timezone
  • PlainTime — a wall-clock time with no date or timezone
  • PlainDateTime — a combined calendar date and wall-clock time
  • PlainYearMonth — a year and month with no day or timezone
  • PlainMonthDay — a month and day with no year or timezone
  • Instant — an exact UTC point in time
  • ZonedDateTime — an exact moment tied to a specific IANA timezone
  • TemporalDuration — a duration spanning calendar units (years, months, days) and time units
  • Calendar — a calendar system (ISO 8601, Buddhist, Hebrew, Japanese, etc.)
  • TimeZone — an IANA timezone identifier

All types are immutable; arithmetic operations return new instances.

Getting started

dependencies:
  temporal: ^0.1.1

For web apps targeting browsers without native Temporal:

dependencies:
  temporal: ^0.1.1
  temporal_js_polyfill: ^0.0.1

Usage

import 'package:temporal/temporal.dart';

// Calendar date — no time, no timezone
final birthday = PlainDate(1990, 6, 15);
final nextBirthday = birthday.add(TemporalDuration(years: 34));
print(nextBirthday); // 2024-06-15

// Wall-clock time — no date, no timezone
final meetingTime = PlainTime(14, 30);

// Exact moment in time — always UTC
final now = Instant.now();
final later = now.add(TemporalDuration(hours: 2));

// Moment tied to a timezone
final inTokyo = ZonedDateTime.now(timeZone: TimeZone('Asia/Tokyo'));
final inNewYork = inTokyo.withTimeZone(TimeZone('America/New_York'));
// same instant, different local representations

// Calendar arithmetic
final inBuddhist = PlainDate.now().withCalendar(Calendar.buddhist);
print(inBuddhist.calendar); // buddhist

Web setup (polyfill)

For browsers that do not yet ship native Temporal, load the polyfill once at startup:

import 'package:temporal/temporal.dart';
import 'package:temporal_js_polyfill/temporal_js_polyfill.dart';

void main() async {
  await loadTemporalPolyfill();
  runApp(MyApp());
}

Additional information

Libraries

temporal
TC39 Temporal date/time API for Dart.