Skip to content

Temporal integration

This API is available since Optique 0.4.0.

The @optique/temporal package provides value parsers for the Temporal API, a modern JavaScript proposal for working with dates and times. These parsers offer type-safe parsing of various temporal values including instants, durations, dates, times, and time zones.

IMPORTANT

These parsers require globalThis.Temporal at runtime. If your runtime does not ship the Temporal API yet, install and initialize a polyfill such as @js-temporal/polyfill before parsing.

deno add --jsr @optique/temporal
npm add @optique/temporal
pnpm add @optique/temporal
yarn add @optique/temporal
bun add @optique/temporal

instant() parser

The instant() parser validates ISO 8601 timestamp strings and returns Temporal.Instant objects representing precise moments in time:

import { 
instant
} from "@optique/temporal";
// Basic instant parser const
timestamp
=
instant
();
// Instant with custom metavar const
createdAt
=
instant
({
metavar
: "TIMESTAMP" });

The parser accepts ISO 8601 strings with timezone information:

// Valid instant formats
"2023-12-25T10:30:00Z"                    // UTC
"2023-12-25T10:30:00+09:00"              // With timezone offset
"2023-12-25T10:30:00.123456789Z"         // With nanosecond precision
"2023-12-25T10:30:00-05:00"              // Negative timezone offset

duration() parser

The duration() parser validates ISO 8601 duration strings and returns Temporal.Duration objects for representing spans of time:

import { 
duration
} from "@optique/temporal";
// Basic duration parser const
timeout
=
duration
();
// Duration with custom metavar const
interval
=
duration
({
metavar
: "INTERVAL" });

The parser accepts ISO 8601 duration format:

// Valid duration formats
"PT30M"           // 30 minutes
"P1D"             // 1 day
"PT1H30M"         // 1 hour 30 minutes
"P1Y2M3DT4H5M6S"  // 1 year, 2 months, 3 days, 4 hours, 5 minutes, 6 seconds
"PT0.123S"        // 123 milliseconds

zonedDateTime() parser

The zonedDateTime() parser validates ISO 8601 datetime strings with timezone information and returns Temporal.ZonedDateTime objects:

import { 
zonedDateTime
} from "@optique/temporal";
// Basic zoned datetime parser const
appointment
=
zonedDateTime
();
// Zoned datetime with custom metavar const
meetingTime
=
zonedDateTime
({
metavar
: "MEETING_TIME" });

The parser accepts ISO 8601 strings with timezone identifiers or offsets:

// Valid zoned datetime formats
"2023-12-25T10:30:00[Asia/Seoul]"         // With IANA timezone
"2023-12-25T10:30:00+09:00[Asia/Seoul]"   // With offset and timezone
"2023-12-25T10:30:00-05:00[America/New_York]" // Different timezone

plainDate() parser

The plainDate() parser validates ISO 8601 date strings and returns Temporal.PlainDate objects representing calendar dates without time information:

import { 
plainDate
} from "@optique/temporal";
// Basic date parser const
birthDate
=
plainDate
();
// Date with custom metavar const
deadline
=
plainDate
({
metavar
: "DEADLINE" });

The parser accepts ISO 8601 date format:

// Valid date formats
"2023-12-25"      // Basic date format
"2023-01-01"      // New Year's Day
"1999-12-31"      // Y2K eve

plainTime() parser

The plainTime() parser validates ISO 8601 time strings and returns Temporal.PlainTime objects representing wall-clock time without date or timezone:

import { 
plainTime
} from "@optique/temporal";
// Basic time parser const
startTime
=
plainTime
();
// Time with custom metavar const
alarmTime
=
plainTime
({
metavar
: "ALARM_TIME" });

The parser accepts ISO 8601 time format:

// Valid time formats
"10:30:00"           // Hour, minute, second
"14:15"              // Hour, minute (seconds default to 00)
"09:30:00.123"       // With milliseconds
"23:59:59.999999999" // With nanosecond precision

plainDateTime() parser

The plainDateTime() parser validates ISO 8601 datetime strings without timezone information and returns Temporal.PlainDateTime objects:

import { 
plainDateTime
} from "@optique/temporal";
// Basic datetime parser const
localTime
=
plainDateTime
();
// Datetime with custom metavar const
eventTime
=
plainDateTime
({
metavar
: "EVENT_TIME" });

The parser accepts ISO 8601 datetime format:

// Valid datetime formats
"2023-12-25T10:30:00"       // Basic datetime
"2023-12-25T14:15"          // Without seconds
"2023-12-25T09:30:00.123"   // With milliseconds
"2023-12-25 10:30:00"       // Space separator (also valid)

plainYearMonth() parser

The plainYearMonth() parser validates year-month strings and returns Temporal.PlainYearMonth objects for representing specific months:

import { 
plainYearMonth
} from "@optique/temporal";
// Basic year-month parser const
reportMonth
=
plainYearMonth
();
// Year-month with custom metavar const
billingPeriod
=
plainYearMonth
({
metavar
: "BILLING_PERIOD" });

The parser accepts year-month format:

// Valid year-month formats
"2023-12"         // December 2023
"2024-01"         // January 2024
"1999-06"         // June 1999

plainMonthDay() parser

The plainMonthDay() parser validates month-day strings and returns Temporal.PlainMonthDay objects for representing recurring dates:

import { 
plainMonthDay
} from "@optique/temporal";
// Basic month-day parser const
birthday
=
plainMonthDay
();
// Month-day with custom metavar const
holiday
=
plainMonthDay
({
metavar
: "HOLIDAY_DATE" });

The parser accepts month-day format:

// Valid month-day formats
"12-25"           // Christmas (December 25)
"01-01"           // New Year's Day (January 1)
"07-04"           // Independence Day (July 4)
"02-29"           // Leap day (February 29)
"--12-25"         // ISO 8601 format with -- prefix is also accepted

timeZone() parser

The timeZone() parser validates timezone identifiers and returns the TimeZone union type exported by @optique/temporal:

import { 
timeZone
} from "@optique/temporal";
// Basic timezone parser const
userTimezone
=
timeZone
();
// Timezone with custom metavar const
displayTimezone
=
timeZone
({
metavar
: "DISPLAY_TZ" });

The parser accepts valid two-segment and three-segment IANA identifiers, plus a curated set of single-segment identifiers for cross-runtime compatibility:

// Valid timezone identifiers
"UTC"                 // Coordinated Universal Time
"GMT"                 // Greenwich Mean Time alias
"EST"                 // POSIX-style single-segment identifier
"Japan"               // Deprecated alias still accepted
"Cuba"                // Deprecated alias still accepted
"Asia/Seoul"          // South Korea
"America/New_York"    // Eastern Time (US)
"Europe/London"       // Europe/London
"America/Argentina/Buenos_Aires" // Three-segment identifier

Single-segment identifiers are matched case-insensitively and normalized to their canonical casing, so inputs like utc, gmt, and japan parse as "UTC", "GMT", and "Japan".

Error messages

All temporal parsers provide clear, specific error messages for different validation failures:

$ myapp --timestamp "not-a-timestamp"
Error: Invalid instant: not-a-timestamp. Expected ISO 8601 format like 2020-01-23T17:04:36Z.

$ myapp --duration "invalid-duration"
Error: Invalid duration: invalid-duration. Expected ISO 8601 format like PT1H30M.

$ myapp --timezone "Invalid/Timezone"
Error: Invalid timezone identifier: Invalid/Timezone. Must be a valid IANA timezone like "Asia/Seoul" or "UTC".

Integration with Temporal API

The temporal parsers return native Temporal objects with rich functionality:

const 
timestampArg
=
argument
(
instant
());
const
result
=
parse
(
timestampArg
, ["2023-12-25T10:30:00Z"]);
if (
result
.
success
) {
const
instant
=
result
.
value
;
console
.
log
(`Epoch milliseconds: ${
instant
.
epochMilliseconds
}`);
console
.
log
(`UTC string: ${
instant
.
toString
()}`);
console
.
log
(`In timezone: ${
instant
.
toZonedDateTimeISO
("Asia/Seoul")}`);
} const
timeoutArg
=
argument
(
duration
());
const
durationResult
=
parse
(
timeoutArg
, ["PT1H30M"]);
if (
durationResult
.
success
) {
const
duration
=
durationResult
.
value
;
console
.
log
(`Total seconds: ${
duration
.
total
("seconds")}`);
console
.
log
(`Hours: ${
duration
.
hours
}, Minutes: ${
duration
.
minutes
}`);
}

The temporal parsers provide comprehensive date and time handling capabilities with full type safety and integration with the modern Temporal API.