What problem are you trying to solve?
Server side rendered (or statically rendered) HTML does not know what the user’s timezone is. This means you can not server render absolute time correctly. To workaround this, the following are common on the web platform today:
- Use relative time
- Instead of “June 14th 2026”, say “2 days ago”
- Does not work with caching / prerendering or anything else that isn’t per request
- Show and specify one specific timezone
- Show “June 16th 2026 10:00 CEST” to all users
- Users have to do the timezone conversions themselves
- Guess timezone based on IP / locale metadata
- What could go wrong??? (Borders, very imprecise)
- Use JavaScript
- Needs synchronous <script> tag to avoid flash of bad content, hard in many frameworks and bad for perf
We discussed this problem and possible solutions briefly at Web Engines Hackfest 2025, and then at length in a breakout session at Web Engines Hackfest 2026. There was wide consensus among vendors that this is an issue that should be resolved.
How would you solve it?
Considerations
During discussion, the following considerations for the solution were identified:
- Web developer provides a machine readable timestamp à la RFC 9557
- Web developer optionally provides formatting attributes (e.g. 12/24 hours), and locale
- For old browsers or in case of missing locales, a fallback text should be used from the original HTML text
- An HTML element with attributes should be used as the trigger to enable this behaviour. The existing
<time> element looks like a logical contender to be this element, as it does not have behaviour yet.
- Engine implementors consider solutions that involve replacing DOM content (innerText) problematic for various reasons (performance, timing compat risk)
- Engine implementors favor solutions using either CSS
content or a UA shadow root, as these are sufficiently user unobservable to mitigate the risks identified with DOM content replacement
- Using CSS
content would require significant additional work to make text selection (and DOMRange integration) work
- The available formatting surface should be a subset of what is available through
Intl.DateTimeFormat. We should not introduce new capabilities, particularly in terms of user preferences, as this can affect privacy.
- Absolute time formatting was identified as the most important use case. We expect that (live) relative time formatting (
2 seconds ago etc) is also an important use case.
- The ability to individually style certain parts of the date / time string were identified as "nice to have".
Proposed solution
We propose to extend the <time> element with the capability to render a formatted absolute date, time, or date time instead of it's child text node when the user opts into this behaviour using an attribute. We propose that the formatted value is rendered through a UA shadow root.
<time datetime="2026-06-17T08:13:41.099Z" format="datetime">
(fallback display)
</time>
The trigger to enable this behaviour would be a new format attribute on the <time> element, that can be set to either "date", "time", or "date time".
Additionally more attributes are available to customise the formatting of the date / time / date time:
datefields: enumerated value of "weekday", "day-weekday", "month-day", "month-day-weekday", "year-month", "year-month-day" (default), "year-month-day-weekday". This controls which parts of the date are displayed.
datelength: enumerated value of "long" (default), "medium", "short". Controls how the parts of the date are formatted.
timeprecision: enumerated value of "hour", "minute", "second" (default). Controls to which granularity time is shown.
timezonestyle: enumerated value of "long", "short", "" (default). Controls whether and how the timezone is displayed.
hour12: boolean attribute with "" default. Controls whether 12 hour time or 24 hour time, or locale default are used.
calendar: enumerated value of calendars available through AvailableCalendars() AO in ECMA 402, or "input" (default). Controls what calendar the date should be displayed in.
"input" indicates to use the calendar of the provided date time.
timezone: string representing a timezone identifier, the string "input", or the string "" (default). Controls what timezone to convert the provided datetime into for display.
"input" indicates to use the timezone of the provided date time. "" indicates to use the UA's current timezone.
- an attribute to switch between 24 and 12 hour time display (name TBD). Tri-state for 12, 24, or locale default.
To determine the locale, we walk the DOM to find the closest ancestor with a lang attribute (this may be the <time> element itself). When the lang changes, the formatting code should be re-run.
To parse the datetime attribute into a "machine readable equivalent", we use the machine-readable equivalent of the element's contents algorithm. An additional algorithm will be needed to transform the return value of that algorithm into Temporal values for use with ECMA 402's formatting algorithms. Additionally the algorithm will have to be modified to support ZonedDateTime and calendar annotations from RFC 9557 (see also).
The result of parsing the datetime attribute can be one of Temporal.PlainDateTime, Temporal.PlainTime, Temporal.PlainDate, Temporal.PlainYearMonth, or Temporal.PlainMonthDay, Temporal.Instant or Temporal.ZonedDateTime.
The timezone=input option is only supported for Temporal.ZonedDateTime. When the value of timezonestyle is not the empty string, timezone="" is only supported for Temporal.Instant and Temporal.ZonedDateTime.
If a Temporal.ZonedDateTime is provided, the value should be converted to the specified timezone using withTimeZone() and to the specified calendar using withCalendar(). If a Temporal.Instant is provided, it should be converted to a Temporal.ZonedDateTime using toZonedDateTimeISO() and to the specified calendar using withCalendar().
The attribute values map to ECMA-402 formatting options through the following JS algorithm:
const options: Intl.DateTimeFormatOptions = {};
if (format === "date" || format === "datetime") {
const dateFields = new Set(datefields.split("-"));
if (dateFields.has("year")) options.year = "numeric";
if (dateFields.has("month")) {
options.month =
dateLength === "long"
? "long"
: dateLength === "short"
? "numeric"
: "short";
}
if (dateFields.has("day")) options.day = "numeric";
if (dateFields.has("weekday")) {
options.weekday = dateLength === "long" ? "long" : "short";
}
}
if (format === "time" || format === "datetime") {
switch (timeprecision) {
case "hour":
options.hour = "numeric";
break;
case "minute":
options.hour = "numeric";
options.minute = "numeric";
break;
case "second":
options.hour = "numeric";
options.minute = "numeric";
options.second = "numeric";
break;
}
}
if (timezonestyle !== "") {
options.timeZoneName = timeZoneStyle === "long" ? "long" : "short";
}
The time is formatted through Intl.DateTimeFormat#formatToParts. The resulting parts are converted to inline span elements in the UA shadow root with a type such as "weekday", "literal", or "month". CSS pseudo element selectors then allow selecting these span elements based on the type.
Q&A
Why a shadow root instead of CSS content? It makes selection much more straightforward, and enables individual styling for certain parts of the date / time.
Where do the attribute names come from? The attribute names and time skeletons come from Unicode MessageFormat 2 (in technical preview). These are not available directly in ECMA-402 yet, but we are planning to add these to ECMA-402 in due time also. They are a subset of the capabilities of ECMA-402 currently (just different syntax).
What problem are you trying to solve?
Server side rendered (or statically rendered) HTML does not know what the user’s timezone is. This means you can not server render absolute time correctly. To workaround this, the following are common on the web platform today:
We discussed this problem and possible solutions briefly at Web Engines Hackfest 2025, and then at length in a breakout session at Web Engines Hackfest 2026. There was wide consensus among vendors that this is an issue that should be resolved.
How would you solve it?
Considerations
During discussion, the following considerations for the solution were identified:
<time>element looks like a logical contender to be this element, as it does not have behaviour yet.contentor a UA shadow root, as these are sufficiently user unobservable to mitigate the risks identified with DOM content replacementcontentwould require significant additional work to make text selection (andDOMRangeintegration) workIntl.DateTimeFormat. We should not introduce new capabilities, particularly in terms of user preferences, as this can affect privacy.2 seconds agoetc) is also an important use case.Proposed solution
We propose to extend the
<time>element with the capability to render a formatted absolute date, time, or date time instead of it's child text node when the user opts into this behaviour using an attribute. We propose that the formatted value is rendered through a UA shadow root.The trigger to enable this behaviour would be a new
formatattribute on the<time>element, that can be set to either"date","time", or"date time".Additionally more attributes are available to customise the formatting of the date / time / date time:
datefields: enumerated value of"weekday","day-weekday","month-day","month-day-weekday","year-month","year-month-day"(default),"year-month-day-weekday". This controls which parts of the date are displayed.datelength: enumerated value of"long"(default),"medium","short". Controls how the parts of the date are formatted.timeprecision: enumerated value of"hour","minute","second"(default). Controls to which granularity time is shown.timezonestyle: enumerated value of"long","short",""(default). Controls whether and how the timezone is displayed.hour12: boolean attribute with""default. Controls whether 12 hour time or 24 hour time, or locale default are used.calendar: enumerated value of calendars available throughAvailableCalendars()AO in ECMA 402, or"input"(default). Controls what calendar the date should be displayed in."input"indicates to use the calendar of the provided date time.timezone: string representing a timezone identifier, the string"input", or the string""(default). Controls what timezone to convert the provided datetime into for display."input"indicates to use the timezone of the provided date time.""indicates to use the UA's current timezone.To determine the locale, we walk the DOM to find the closest ancestor with a
langattribute (this may be the<time>element itself). When the lang changes, the formatting code should be re-run.To parse the
datetimeattribute into a "machine readable equivalent", we use the machine-readable equivalent of the element's contents algorithm. An additional algorithm will be needed to transform the return value of that algorithm intoTemporalvalues for use with ECMA 402's formatting algorithms. Additionally the algorithm will have to be modified to supportZonedDateTimeand calendar annotations from RFC 9557 (see also).The result of parsing the
datetimeattribute can be one ofTemporal.PlainDateTime,Temporal.PlainTime,Temporal.PlainDate,Temporal.PlainYearMonth, orTemporal.PlainMonthDay,Temporal.InstantorTemporal.ZonedDateTime.The
timezone=inputoption is only supported forTemporal.ZonedDateTime. When the value oftimezonestyleis not the empty string,timezone=""is only supported forTemporal.InstantandTemporal.ZonedDateTime.If a
Temporal.ZonedDateTimeis provided, the value should be converted to the specified timezone usingwithTimeZone()and to the specified calendar usingwithCalendar(). If aTemporal.Instantis provided, it should be converted to aTemporal.ZonedDateTimeusingtoZonedDateTimeISO()and to the specified calendar usingwithCalendar().The attribute values map to ECMA-402 formatting options through the following JS algorithm:
The time is formatted through
Intl.DateTimeFormat#formatToParts. The resulting parts are converted to inline span elements in the UA shadow root with a type such as"weekday","literal", or"month". CSS pseudo element selectors then allow selecting these span elements based on the type.Q&A
Why a shadow root instead of CSS
content? It makes selection much more straightforward, and enables individual styling for certain parts of the date / time.Where do the attribute names come from? The attribute names and time skeletons come from Unicode MessageFormat 2 (in technical preview). These are not available directly in ECMA-402 yet, but we are planning to add these to ECMA-402 in due time also. They are a subset of the capabilities of ECMA-402 currently (just different syntax).