This subsection describes the functions and options for date/time formatting.
Important
The functions in this section have a status of Draft.
They are proposed for inclusion in a future release and are not Stable.
The options and option values used by :datetime, :date, and :time
are based on Semantic Skeletons, which are in technical preview.
The set of options and option values will be extended by later versions of this specification.
Note
Selection based on date/time types is not required by this release of MessageFormat.
Use care when defining implementation-specific selectors based on date/time types.
The types of queries found in implementations such as java.time.TemporalAccessor
are complex and user expectations might be inconsistent with good I18N practices.
The function :datetime is used to format a date/time value.
Its formatted result will always include both the date and the time,
and optionally a timezone.
If no options are specified, this function defaults to the following:
{$d :datetime}is the same as
{$d :datetime dateFields=year-month-day timePrecision=minute}
Note
The formatting behavior of :datetime is inconsistent with Intl.DateTimeFormat
in JavaScript and with {d,date} in ICU MessageFormat 1.0.
This is because, unlike those implementations, :datetime is distinct from :date and :time.
The operand of the :datetime function is either
an implementation-defined date/time type
or a date/time literal value, as defined in Date and Time Operand.
All other operand values produce a Bad Operand error.
The following options are REQUIRED to be available on the function :datetime:
dateFieldsweekdayday-weekdaymonth-daymonth-day-weekdayyear-month-day(default)year-month-day-weekday
dateLengthlongmedium(default)short
timePrecisionhourminute(default)second
timeZoneStylelongshort
- Date/time override options
If the timeZoneStyle option is not included in the expression,
its formatted result will not include a timezone indicator.
Except for date/time override options,
each :datetime option value MUST be set by a literal.
If such an option value is a variable,
a Bad Option Error is emitted and
the option is ignored when formatting the expression.
If the operand of the expression is an implementation-defined date/time type, it can include other option values. Any date/time override options of the operand are included in the resolved option values of the expression, with options on the expression taking priority over any options of the operand. Any operand options not matching the date/time override options are ignored.
The resolved value of an expression with a :datetime function
contains an implementation-defined date/time value
of the operand of the annotated expression,
together with the resolved options values.
The function :date is used to format the date portion of date/time values.
If no options are specified, this function defaults to the following:
{$d :date}is the same as{$d :date fields=year-month-day length=medium}
The operand of the :date function is either
an implementation-defined date/time type
or a date/time literal value, as defined in Date and Time Operand.
All other operand values produce a Bad Operand error.
The following options are REQUIRED to be available on the function :date:
fieldsweekdayday-weekdaymonth-daymonth-day-weekdayyear-month-day(default)year-month-day-weekday
lengthlongmedium(default)short
- Date/time override options
The fields and length option values MUST each be set by a literal.
If such an option value is a variable,
a Bad Option Error is emitted and
the option is ignored when formatting the expression.
If the operand of the expression is an implementation-defined date/time type, it can include other option values. Any date/time override options of the operand are included in the resolved option values of the expression, with options on the expression taking priority over any options of the operand. Any operand options not matching the date/time override options are ignored.
The resolved value of an expression with a :date function
is implementation-defined.
An implementation MAY emit a Bad Operand or Bad Option error (as appropriate)
when a variable annotated directly or indirectly by a :date annotation
is used as an operand or an option value.
The function :time is used to format the time portion of date/time values.
Its formatted result will always include the time,
and optionally a timezone.
If no options are specified, this function defaults to the following:
{$t :time}is the same as{$t :time precision=minute}
The operand of the :time function is either
an implementation-defined date/time type
or a date/time literal value, as defined in Date and Time Operand.
All other operand values produce a Bad Operand error.
The following options are REQUIRED to be available on the function :time:
precisionhourminute(default)second
timeZoneStylelongshort
- Date/time override options
If the timeZoneStyle option is not included in the expression,
its formatted result will not include a timezone indicator.
The precision and timeZoneStyle option values MUST each be set by a literal.
If such an option value is a variable,
a Bad Option Error is emitted and
the option is ignored when formatting the expression.
If the operand of the expression is an implementation-defined date/time type, it can include other option values. Any date/time override options of the operand are included in the resolved option values of the expression, with options on the expression taking priority over any options of the operand. Any operand options not matching the date/time override options are ignored.
The resolved value of an expression with a :time function
is implementation-defined.
An implementation MAY emit a Bad Operand or Bad Option error (as appropriate)
when a variable annotated directly or indirectly by a :time annotation
is used as an operand or an option value.
The operand of a date/time function is either an implementation-defined date/time type or a date/time literal value, as defined below. All other operand values produce a Bad Operand error.
A date/time literal value is a non-empty string consisting of an ISO 8601 date, or an ISO 8601 datetime optionally followed by a timezone offset. As implementations differ slightly in their parsing of such strings, ISO 8601 date and datetime values not matching the following regular expression MAY also be supported. Furthermore, matching this regular expression does not guarantee validity, given the variable number of days in each month.
(?!0000)[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])(T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\.[0-9]{1,3})?(Z|[+-]((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?)?When the time is not present, implementations SHOULD use 00:00:00 as the time.
When the offset is not present, implementations SHOULD use a floating time type
(such as Java's java.time.LocalDateTime) to represent the time value.
For more information, see Working with Timezones.
Important
The ABNF and syntax of Unicode MessageFormat do not formally define date/time literals. This means that a message can be syntactically valid but produce a Bad Operand error at runtime.
Note
String values passed as variables in the formatting context's input mapping can be formatted as date/time values as long as their contents are date/time literals.
For example, if the value of the variable now were the string
2024-02-06T16:40:00Z, it would behave identically to the local
variable in this example:
.local $example = {|2024-02-06T16:40:00Z| :datetime}
{{{$now :datetime} == {$example}}}
Note
True time zone support in serializations is expected to coincide with the adoption of Temporal in JavaScript. The form of these serializations is known and is a de facto standard. Support for these extensions is expected to be required in the post-tech preview. See: https://datatracker.ietf.org/doc/draft-ietf-sedate-datetime-extended/
Date/time override options are options that allow an expression to override values set by the current locale, or provided by the formatting context (such as the default time zone), or embedded in an implementation-defined date/time operand value.
Note
These options do not have default values because they are only to be used as overrides for locale-and-value dependent implementation-defined defaults.
The following option is REQUIRED to be available on
the functions :datetime, :date, and :time.
timeZone
The default value for timeZone is the default time zone provided by the formatting context.
The value input corresponds to the time zone of the operand.
If it is used and the resolved value of the operand does not include a time zone or offset,
a Bad Operand error is emitted and the default time zone is used to format the expression.
If the resolved value of the operand does not include a time zone or offset,
the resolved value of the timeZone option is used as its time zone.
If the resolved value of the operand includes a time zone or offset,
and the resolved value of the timeZone option is different from that,
an implementation SHOULD convert the resolved value of the operand
to the time zone indicated by the resolved value of the timeZone option.
If such conversion is not supported, an implementation MAY alternatively
emit a Bad Option error and use a fallback value as the resolved value of the expression.
Note
A date/time type that represents a numeric offset from some epoch (such as a "Unix timestamp") is considered to include UTC as its time zone.
The following option is REQUIRED to be available on
the functions :datetime and :time:
hour12truefalse
The following option is RECOMMENDED to be available on
the functions :datetime, :date, and :time.
calendar- A well-formed Unicode Calendar Identifier, i.e. a uvalue.