UNPKG

@burglekitt/gmt

Version:

Temporal-based date and time utilities with timezone support and polyfill integration

55 lines (54 loc) 3.38 kB
import { calendarDateParts, } from "./calendarDateString.js"; import { ethiopicFamilyDateParts, isEthiopicFamilyCalendar, } from "./ethiopicFamilyCalendar.js"; /** * Split a Temporal.PlainDate into GMT's calendar-annotated string halves (`{ date, annotation }`) * in a known target CalendarSystem — the shared primitive behind both `formatDateInCalendar` * (`plain/`) and `internal/calendarZonedString.ts`'s `formatZonedInCalendar` (`zoned/`). * * The two namespaces need the halves joined differently — `plain/` concatenates them directly, * while GMT's zoned grammar splices `T<time><offset>` between them and appends `[<timeZone>]` * (see `regex/calendar-zoned-date-time.ts` for why `[u-ca=...]` precedes `[timeZone]`). Sharing * the split rather than string-slicing `formatDateInCalendar`'s output on `"["` keeps the era, * Ethiopic-family and zero-padding logic in exactly one place per calendar family. * * The calendar must always be known up front and passed in explicitly, never re-derived from * `date.calendarId` alone: the Ethiopic family ("ethiopic" / "ethiopic-amete-alem" / "coptic") * is backed by Temporal's single, ambiguous "ethioaa" id, which cannot tell the three variants * apart from the PlainDate object alone (see `ethiopicFamilyCalendar.ts`). * * @param date Temporal.PlainDate to split, already calendared as `calendar` expects * (`"ethioaa"` for any Ethiopic-family member, its own Temporal calendar id otherwise) * @param calendar the CalendarSystem `date` is known to represent * @returns `{ date, annotation }``annotation` is `""` for the "gregorian"/iso8601 case */ export function calendarDateStringParts(date, calendar) { if (isEthiopicFamilyCalendar(calendar)) { return ethiopicFamilyDateParts(date, calendar); } return calendarDateParts(date); } /** * Format a Temporal.PlainDate as a GMT calendar-annotated (or bare ISO) string in a known * target CalendarSystem — companion to `calendarSystemOfDateValue`. * * The calendar must always be known up front and passed in explicitly, never re-derived from * `date.calendarId` alone: the Ethiopic family ("ethiopic" / "ethiopic-amete-alem" / "coptic") * is backed by Temporal's single, ambiguous "ethioaa" id, which cannot tell the three variants * apart from the PlainDate object alone (see `ethiopicFamilyCalendar.ts`). * * Within a known target calendar, though, the *fields* (year, era, month, day) are always * re-derived from the actual resulting `date`, never copied from an input string's tag — * `calendarDateParts`/`ethiopicFamilyDateParts` both already do this per-call, which is * required because calendar-unit arithmetic can cross a leap-month or era boundary (Hebrew * Adar I -> Adar, Japanese Heisei -> Reiwa): a copied tag would describe a date that no longer * exists (E5 decision of record D7). * * @param date Temporal.PlainDate to format, already calendared as `calendar` expects * (`"ethioaa"` for any Ethiopic-family member, its own Temporal calendar id otherwise) * @param calendar the CalendarSystem `date` is known to represent * @returns GMT's calendar-annotated (or bare ISO, for "gregorian") PlainDate string */ export function formatDateInCalendar(date, calendar) { const { date: datePart, annotation } = calendarDateStringParts(date, calendar); return `${datePart}${annotation}`; }