ComponentsLumos 0.0.1Open component

FormattedDate

A date rendered in the site's locale, without the off-by-one-day bug.

Formatting a date is one of those jobs that looks trivial and has a trap in it. FormattedDate renders one in the site's locale, and defaults to UTC so a date-only value never shifts by a day depending on which machine built the site.

astro
<FormattedDate date={post.date} />

Props

PropTypeDefaultWhat it does
daterequiredDateNoneThe date to render. Nothing renders if it is missing or invalid, and a warning appears in development.
localestringSITE_LOCALEA BCP 47 locale tag, such as en-GB or fr-FR.
timeZonestring"UTC"An IANA time zone. UTC by default, so a date without a time does not move.
formatIntl.DateTimeFormatOptions{ dateStyle: "long" }Formatting options, passed straight to Intl.DateTimeFormat.

The trap, explained

A date written as 2026-03-01 is midnight UTC. Format it in a timezone behind UTC and it renders as the 28th of February, so a post can appear to be published a day before it was, but only for some readers. Defaulting to UTC removes the whole class of problem.

astro
<FormattedDate
  date={event.start}
  locale="en-GB"
  timeZone="Europe/London"
  format={{ dateStyle: "full", timeStyle: "short" }}
/>