API Reference
Everything below is exported from the package root (rosetta-date) unless noted. Dialects and
libraries are exported from rosetta-date/dialects and rosetta-date/libraries.
convert
function convert(format: string, options: ConvertOptions): stringConvert a date-format token string from one endpoint to another. Direction travels with the call.
import { convert } from 'rosetta-date'
import { ldml, moment } from 'rosetta-date/dialects'
convert('DD/MM/YYYY', { from: moment, to: ldml }) // 'dd/MM/yyyy'createConverter
function createConverter(
from: Dialect | Library,
to: Dialect | Library,
options?: ConverterOptions,
): ConverterBind a fixed direction once and return a reusable Converter.
import { createConverter } from 'rosetta-date'
import { ldml, moment } from 'rosetta-date/dialects'
const toLdml = createConverter(moment, ldml)
toLdml('YYYY-MM-DD') // 'yyyy-MM-dd'describe
function describe(format: string, endpoint: Dialect | Library): DescribedSegment[]The read-only counterpart to convert: parse a format and return its segments with the canonical
semantics conversion keeps internal. See the Describing Formats guide.
import { describe } from 'rosetta-date'
import { moment } from 'rosetta-date/dialects'
describe('DD/MM', moment)
// [ { kind: 'field', token: 'DD', canonical: 'day-of-month/2-digit', field: 'day-of-month', style: '2-digit', qualifiers: [] },
// { kind: 'literal', value: '/' },
// { kind: 'field', token: 'MM', canonical: 'month/2-digit', field: 'month', style: '2-digit', qualifiers: [] } ]decodeCanonical
function decodeCanonical(token: CanonicalToken): DecodedCanonicalSplit a canonical symbol into its field / style / qualifiers parts — the same decoding
describe applies, for when you already hold a CanonicalToken.
describe types
interface DecodedCanonical {
readonly field: string
readonly style: string
readonly qualifiers: readonly string[]
}
interface DescribedField extends DecodedCanonical {
readonly kind: 'field'
readonly token: string
readonly canonical: CanonicalToken
}
type DescribedSegment =
| { readonly kind: 'literal', readonly value: string }
| DescribedField
| { readonly kind: 'unknown', readonly value: string }explain
function explain(format: string, options: ExplainOptions): ExplainedSegment[]A read-only dry run of convert: report, per field, whether the target can render it (and as which
token) or why it cannot. Builds on describe. See the Explaining Conversions guide.
import { explain } from 'rosetta-date'
import { dayjs, momentjs } from 'rosetta-date/libraries'
explain('DDD', { from: momentjs, to: dayjs })
// [ { kind: 'field', token: 'DDD', canonical: 'day-of-year/numeric', field: 'day-of-year', style: 'numeric', qualifiers: [], status: 'unsupported', reason: 'unsupported-by-target' } ]explain types
interface ExplainOptions {
readonly from: Dialect | Library
readonly to: Dialect | Library
}
// The subset of `UnsupportedTokenReason` a per-token `explain` can produce.
type ExplainedReason = 'unmappable' | 'unsupported-by-target'
type ExplainedField = DescribedField & (
| { readonly status: 'converted', readonly target: string }
| { readonly status: 'unsupported', readonly reason: ExplainedReason }
)
type ExplainedSegment =
| { readonly kind: 'literal', readonly value: string }
| ExplainedField
| { readonly kind: 'unknown', readonly value: string }Intl adapter — rosetta-date/intl
Bridges token strings and native Intl.DateTimeFormat options. See the Intl Options
guide for behaviour.
toIntlOptions
function toIntlOptions(format: string, options: ToIntlOptions): Intl.DateTimeFormatOptionsRead a format string into an Intl.DateTimeFormatOptions bag. Literals and field order are dropped —
the locale decides layout.
import { toIntlOptions } from 'rosetta-date/intl'
import { moment } from 'rosetta-date/dialects'
toIntlOptions('YYYY-MM-DD', { from: moment }) // { year: 'numeric', month: '2-digit', day: '2-digit' }fromIntlOptions
function fromIntlOptions(intlOptions: Intl.DateTimeFormatOptions, options: FromIntlOptions): stringTranslate Intl options into a target’s tokens. dateStyle / timeStyle map to the target’s
localized presets; components reconstruct a CLDR-canonical-order skeleton.
import { fromIntlOptions } from 'rosetta-date/intl'
import { dayjs } from 'rosetta-date/libraries'
fromIntlOptions({ dateStyle: 'short' }, { to: dayjs }) // 'L'Intl adapter types
type IntlUnsupportedPolicy = 'throw' | 'drop'
interface ToIntlOptions {
readonly from: Dialect | Library
readonly onUnsupportedToken?: IntlUnsupportedPolicy
}
interface FromIntlOptions {
readonly to: Dialect | Library
readonly onUnsupportedToken?: IntlUnsupportedPolicy
}The policy is narrower than UnsupportedTokenPolicy: across the Intl boundary there is no output
string to 'literalize' and no target dialect for a handler, so only 'throw' and 'drop' (the
default) apply. A field with no Intl equivalent is otherwise dropped.
Types
Converter
type Converter = (format: string) => stringConverterOptions
interface ConverterOptions {
readonly onUnsupportedToken?: UnsupportedTokenPolicy
}ConvertOptions
interface ConvertOptions extends ConverterOptions {
readonly from: Dialect | Library
readonly to: Dialect | Library
}Each side may be a Dialect (pure grammar) or a Library (a concrete tool) — mix them freely.
Defining endpoints
defineDialect
function defineDialect(definition: {
name: string
syntax: TokenSyntax
tokens: TokenRule[]
composites?: CompositeRule[]
}): DialectValidates the definition once and returns a stable, cacheable Dialect. See
Custom Dialects & Libraries.
A CompositeRule is a parse-time macro — one spelling that expands to a sub-pattern (e.g. strftime
%T → %H:%M:%S). Rendering produces the expansion, never the composite, so a composite normalizes
on a round trip.
interface CompositeRule {
readonly token: string // the composite spelling, e.g. '%T'
readonly expandsTo: string // its sub-pattern, in this dialect's grammar, e.g. '%H:%M:%S'
}TokenSyntax is a discriminated union over tokenization families:
interface DelimitedSyntax {
readonly kind: 'delimited'
readonly open: string // e.g. '[' or "'"
readonly close: string // e.g. ']' or "'"
readonly escapedDelimiter?: string // a doubled quote, for quote-style literals
}
interface DirectiveSyntax {
readonly kind: 'directive'
readonly marker: string // e.g. '%'; doubling it is a literal marker
}
type TokenSyntax = DelimitedSyntax | DirectiveSyntaxdefineLibrary
function defineLibrary(definition: LibraryDefinition): LibraryBuilds a Library on top of a dialect, optionally adding tokens via extends.
The canonical vocabulary
Canonical
An object of stable, semver-versioned canonical symbols shaped as field/style
(e.g. Canonical.YearNumeric, Canonical.MonthTwoDigit). Map your tokens to these so they
interoperate with every dialect. The CanonicalToken type names the union of these values.
Unsupported tokens
Unsupported
const Unsupported: { readonly drop: unique symbol, readonly literalize: unique symbol }Two unique-symbol sentinels returned from an onUnsupportedToken handler — Unsupported.drop
omits the token, Unsupported.literalize defers to the default. They are the named members of
UnsupportedTokenResult.
UnsupportedTokenError
Thrown when onUnsupportedToken: 'throw' meets a token that cannot be converted. Carries token
and reason fields.
Policy & handler types
| Type | Shape |
|---|---|
UnsupportedTokenPolicy | 'literalize' | 'throw' | UnsupportedTokenHandler |
UnsupportedTokenHandler | (token, info) => UnsupportedTokenResult | undefined |
UnsupportedTokenResult | string | typeof Unsupported.drop | typeof Unsupported.literalize |
UnsupportedTokenInfo | { reason, from, to, fromLibrary?, toLibrary? } |
UnsupportedTokenReason | 'unrecognized' | 'unmappable' | 'unsupported-by-target' | 'unrepresentable-adjacency' |
See Unsupported Tokens for behaviour.
Built-in dialects — rosetta-date/dialects
The importable surface. For what each dialect is — its grammar, literals, and examples — see Dialects.
| Export | Type |
|---|---|
moment | Dialect |
ldml | Dialect |
getDialect | (name: DialectName) => Dialect |
DialectName | type — union of built-in dialect names |
getDialect resolves a name string to its Dialect object for a name-driven path. By design it
pulls in every built-in, so reach for it only when the direction is dynamic — otherwise import the
specific dialect to stay tree-shakeable.
Built-in libraries — rosetta-date/libraries
The importable surface. For each library’s coverage and tool-specific behaviour, see Libraries.
| Export | Type |
|---|---|
momentjs | Library |
dayjs | Library |
dateFns | Library |
getLibrary | (name: LibraryName) => Library |
LibraryName | type — union of built-in library names |
getLibrary mirrors getDialect — name-driven resolution that pulls in every built-in.