formatCalendar
Signature
Section titled “Signature”formatCalendar(value: string, locale?: string | string[], options?: FormatCalendarOptions): stringFormat a plain date-time as a relative day label plus time-of-day, e.g. “Tomorrow at 2:30 PM”. The formatRelativeDateTime family does not cover this: it renders “in 1 day”, an elapsed-time phrase, not a day label + clock time.
- Within
±6days ofreference(default: now), renders<day label>joined to the localized time using the locale’s own connector — never a hardcoded “at”. The day label comes fromIntl.RelativeTimeFormat(numeric: "auto"), so it reads “Today”/“Tomorrow”/“Yesterday” near the boundary and “in N days”/“N days ago” further out, all locale-native. - Beyond
±6days, falls back to an absolutedateStyle: "long"+timeStylestring with no relative wording. The one-week limit is GMT’s own rule, not a standard’s: from 7 days out a date is easier to place than a day count. - Comparison: Moment’s
.calendar()switches to a date at the same distance (itssameElsecase); its wording inside the week differs. - The connector between the day label and the time is read from CLDR’s own combined date+time pattern for the locale (see
internal/joinDateTimeConnector.ts), not hardcoded — this is what letsformatCalendaravoid the i18n objection that excludes a token formatter. - The time never carries a zone name: a plain value has none.
- Use
formatCalendarfor user-facing schedules (“Tomorrow at 2:30 PM”); useformatRelativeDateTimefor elapsed-time displays (“in 1 day”). optionsmust be an object or omitted:nullor any other primitive returns"", as Temporal’s GetOptionsObject rejects it.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
value | string | ISO PlainDateTime string to format |
locale | string | string[] | optional: BCP 47 locale tag, or a preference list of tags (ECMA-402) |
Options
Section titled “Options”options
What the value is compared with and how the time is written
Options for formatCalendar: the date-time the value is compared with, and the style of the time-of-day half.
import type { FormatCalendarOptions } from "@northguild/gmt";| Option | Type | Default | Description |
|---|---|---|---|
timeStyle? | "short" | "medium" | "short" | The length of the time-of-day part, as the timeStyle of Intl.DateTimeFormat. “long” and “full” are not offered: they differ from “medium” only by a timeZoneName, and a plain value has no zone. Passed anyway (from untyped code), they format as “medium” — Temporal’s PlainDateTime format drops timeZoneName (AdjustDateTimeStyleFormat). |
reference? | string | The current date and time. | The moment the day label is measured from, as an ISO string in the same form as the value being formatted. A value on the same calendar day reads “today”, one on the next day “tomorrow”. |
Returns
Section titled “Returns”the formatted calendar string, or "" on invalid input
Related types
Section titled “Related types”Examples
Section titled “Examples”import { formatCalendar } from "@northguild/gmt/plain/format";
formatCalendar("2026-03-16T14:30:00", "en-US", { reference: "2026-03-15T09:00:00" }) // "tomorrow at 2:30 PM"