Skip to Content
ReferenceLibrary Notes

Library Notes

Each library speaks one of the dialects but renders its own slice of it — adding tokens, omitting others, or gating some behind runtime configuration. Converting between libraries (rather than dialects) is what surfaces these differences; see Unsupported Tokens for how an unrenderable token is handled.

Localized presets

L… (Moment.js / Day.js) and P…/p… (date-fns) render per the library’s loaded locale. rosetta-date maps them preset → preset (never to a concrete pattern), so the token stays locale-deferred and the target library applies its own locale — including the compound connector (" at ", ", ", …) it picks for that locale.

MeaningmomentjsdayjsdateFns
Date, shortLLP
Date, mediumllllPP
Date, longLLLLPPP
Time, shortLTLTp
Time, with secondsLTSLTSpp
Date + time, mediumllllllPPpp
Date + time, longLLLLLLPPPppp
Date + time, fullLLLLLLLLPPPPpppp

Day.js renders these through its LocalizedFormat plugin.

Locale caveat: conversion rewrites the token, not the date. Matching output needs equivalent locales loaded in both libraries; the conversion only guarantees the token stays the locale’s preset, never a hardcoded pattern. Samples are en-US — e.g. LL vs PPP differ only as June 7, 2024 vs June 7th, 2024, which is each library’s en locale data, not a conversion error.

Match widths: for date + time, use a matched compound preset (PPpp, PPPppp) or a separator (PP p). moment has no mismatched-width compound, so gluing different widths (PPPp) drops the locale connector and can re-lex into a different token — rosetta-date maps each preset faithfully, but a glued mismatched-width input was never valid to begin with.

momentjs

The reference implementation of the moment grammar. It renders every token in the Token Mapping tables, so momentjs carries no supports set and converting to it never flags a grammar token. Its localized L… presets map to date-fns P…; see Localized presets.

dayjs

Day.js speaks the moment grammar but implements only a subset, split across its core formatter and two common plugins. Tokens it does not recognize are mis-rendered at format time rather than rejected, so converting to dayjs routes them through onUnsupportedToken (reason unsupported-by-target) instead of emitting something broken.

Tokens Day.js does not render (and therefore flags):

Token(s)Meaning
N NN NNN NNNN NNNNNEra
Mo Qo Wo DDDoOrdinals beyond Do / wo
DDD DDDDDay of year
e EWeekday number (locale / ISO)
S SSSub-SSS fractional second
gg GGWeek-numbering year, 2-digit

Some tokens Day.js renders only with a plugin loaded — Q, Do, w / wo / ww, W / WW, k / kk, gggg / GGGG, X, x, z need AdvancedFormat; the L… presets need LocalizedFormat. rosetta-date emits these as-is; whether the plugin is actually loaded is the consumer’s concern.

dateFns

date-fns is the reference implementation of the ldml (UTS #35) grammar plus its own extensions — ISO week fields, the Unix epoch, and localized P…/p… presets. These extras convert only through the dateFns library (from: momentjs, to: dateFns); the bare ldml dialect does not define them, so a dialect → dialect conversion literalizes them instead.

MeaningmomentjsdayjsdateFns
ISO week-numbering yearGGGGGGGGRRRR
ISO week-numbering year, 2-digitGGRR
ISO week of yearWWI
ISO week of year, 2-digitWWWWII
ISO week of year, ordinalWoIo
ISO weekday, numberEi
Unix timestamp, secondsXXt
Unix timestamp, millisecondsxxT

marks a date-fns extension Day.js has no token for; converting it to dayjs flags it. The ones Day.js does render here come from its AdvancedFormat plugin.

Option-gated tokens

date-fns guards a few tokens behind options you must enable in its format() call:

  • Day of year (D, DD) requires useAdditionalDayOfYearTokens: true.
  • Local week-year (YY, YYYY) requires useAdditionalWeekYearTokens: true.

rosetta-date produces the standards-correct token; enabling these options is the caller’s responsibility. The converter does not track which options you enabled — if a token needs one you did not pass, date-fns throws at format() time, which is the authoritative signal for your exact version.

Extensions with no moment counterpart

These date-fns extensions have no moment token, so converting them to moment produces an escaped literal rather than a wrong guess:

dateFnsMeaning
PPPPLocalized full date (with weekday)
ppp ppppLocalized time with time zone
PpLocalized short date + time
Last updated on