Skip to content

Commit 1bcc219

Browse files
authored
Include :date, :datetime, and :time with minimal options (#1083)
* Include :date, :datetime, and :time with minimal options * Add timeZoneStyle=never to {$d :datetime} clarification * Drop "day" from date fields * Updates from 2025-07-07 meeting
1 parent e0bd662 commit 1bcc219

File tree

5 files changed

+92
-114
lines changed

5 files changed

+92
-114
lines changed

spec/functions/datetime.md

Lines changed: 78 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,31 @@ This subsection describes the _functions_ and _options_ for date/time formatting
55
> [!IMPORTANT]
66
> The _functions_ in this section have a status of **Draft**.
77
> They are proposed for inclusion in a future release and are not Stable.
8+
> The _options_ and _option values_ used by `:datetime`, `:date`, and `:time`
9+
> are based on [Semantic Skeletons], which are in technical preview.
10+
> The set of _options_ and _option values_ will be extended by later versions of this specification.
811
912
> [!NOTE]
1013
> Selection based on date/time types is not required by this release of MessageFormat.
1114
> Use care when defining implementation-specific _selectors_ based on date/time types.
1215
> The types of queries found in implementations such as `java.time.TemporalAccessor`
1316
> are complex and user expectations might be inconsistent with good I18N practices.
1417
18+
[Semantic Skeletons]: https://www.unicode.org/reports/tr35/tr35-75/tr35-dates.html#Semantic_Skeletons
19+
1520
#### The `:datetime` function
1621

17-
The function `:datetime` is used to format date/time values, including
18-
the ability to compose user-specified combinations of fields.
22+
The function `:datetime` is used to format a date/time value.
23+
Its formatted result will always include both the date and the time,
24+
and optionally a timezone.
1925

2026
If no options are specified, this function defaults to the following:
2127

22-
- `{$d :datetime}` is the same as `{$d :datetime dateStyle=medium timeStyle=short}`
28+
- `{$d :datetime}` is the same as<br>
29+
`{$d :datetime dateFields=year-month-day timePrecision=minute}`
2330

2431
> [!NOTE]
25-
> The default formatting behavior of `:datetime` is inconsistent with `Intl.DateTimeFormat`
32+
> The formatting behavior of `:datetime` is inconsistent with `Intl.DateTimeFormat`
2633
> in JavaScript and with `{d,date}` in ICU MessageFormat 1.0.
2734
> This is because, unlike those implementations, `:datetime` is distinct from `:date` and `:time`.
2835
@@ -35,93 +42,42 @@ All other _operand_ values produce a _Bad Operand_ error.
3542

3643
##### Options
3744

38-
The `:datetime` function can use either the appropriate _style options_
39-
or can use a collection of _field options_ (but not both) to control the formatted
40-
output.
41-
_Date/time override options_ can be combined with either _style options_ or _field options_.
42-
43-
If both _style options_ and _field options_ are specified,
44-
a _Bad Option_ error is emitted
45-
and a _fallback value_ used as the _resolved value_ of the _expression_.
46-
47-
If the _operand_ of the _expression_ is an implementation-defined date/time type,
48-
it can include _style options_, _field options_, or other _options_.
49-
These are included in the resolved option values of the _expression_,
50-
with _options_ on the _expression_ taking priority over any options of the _operand_.
51-
52-
> [!NOTE]
53-
> The names of _options_ and their _option values_ were derived from the
54-
> [options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/resolvedOptions#description)
55-
> in JavaScript's `Intl.DateTimeFormat`.
56-
57-
###### Style Options
45+
The following _options_ are REQUIRED to be available on the function `:datetime`:
5846

59-
**_<dfn>Style options</dfn>_** pertain to the overall styling or appearance of the formatted output.
60-
61-
The following _style options_ are REQUIRED to be available on the function `:datetime`:
62-
63-
- `dateStyle`
64-
- `full`
47+
- `dateFields`
48+
- `weekday`
49+
- `day-weekday`
50+
- `month-day`
51+
- `month-day-weekday`
52+
- `year-month-day` (default)
53+
- `year-month-day-weekday`
54+
- `dateLength`
6555
- `long`
66-
- `medium`
56+
- `medium` (default)
6757
- `short`
68-
- `timeStyle`
69-
- `full`
58+
- `timePrecision`
59+
- `hour`
60+
- `minute` (default)
61+
- `second`
62+
- `timeZoneStyle`
7063
- `long`
71-
- `medium`
7264
- `short`
65+
- _Date/time override options_
7366

74-
###### Field Options
75-
76-
**_<dfn>Field options</dfn>_** describe which fields to include in the formatted output
77-
and what format to use for that field.
78-
79-
> [!NOTE]
80-
> _Field options_ do not have default values because they are only to be used
81-
> to compose the formatter.
67+
If the `timeZoneStyle` _option_ is not included in the _expression_,
68+
its formatted result will not include a timezone indicator.
8269

83-
The following _field options_ are REQUIRED to be available on the function `:datetime`:
70+
Except for _date/time override options_,
71+
each `:datetime` _option value_ MUST be set by a _literal_.
72+
If such an _option value_ is a _variable_,
73+
a _Bad Option Error_ is emitted and
74+
the _option_ is ignored when formatting the _expression_.
8475

85-
- `weekday`
86-
- `long`
87-
- `short`
88-
- `narrow`
89-
- `era`
90-
- `long`
91-
- `short`
92-
- `narrow`
93-
- `year`
94-
- `numeric`
95-
- `2-digit`
96-
- `month`
97-
- `numeric`
98-
- `2-digit`
99-
- `long`
100-
- `short`
101-
- `narrow`
102-
- `day`
103-
- `numeric`
104-
- `2-digit`
105-
- `hour`
106-
- `numeric`
107-
- `2-digit`
108-
- `minute`
109-
- `numeric`
110-
- `2-digit`
111-
- `second`
112-
- `numeric`
113-
- `2-digit`
114-
- `fractionalSecondDigits`
115-
- `1`
116-
- `2`
117-
- `3`
118-
- `timeZoneName`
119-
- `long`
120-
- `short`
121-
- `shortOffset`
122-
- `longOffset`
123-
- `shortGeneric`
124-
- `longGeneric`
76+
If the _operand_ of the _expression_ is an implementation-defined date/time type,
77+
it can include other option values.
78+
Any _date/time override options_ of the operand are included in the resolved option values of the _expression_,
79+
with _options_ on the _expression_ taking priority over any options of the _operand_.
80+
Any _operand_ options not matching the _date/time override options_ are ignored.
12581

12682
##### Resolved Value
12783

@@ -136,7 +92,7 @@ The function `:date` is used to format the date portion of date/time values.
13692

13793
If no options are specified, this function defaults to the following:
13894

139-
- `{$d :date}` is the same as `{$d :date style=medium}`
95+
- `{$d :date}` is the same as `{$d :date fields=year-month-day length=medium}`
14096

14197
##### Operands
14298

@@ -147,19 +103,31 @@ All other _operand_ values produce a _Bad Operand_ error.
147103

148104
##### Options
149105

150-
The function `:date` has these _options_:
106+
The following _options_ are REQUIRED to be available on the function `:date`:
151107

152-
- `style` \[REQUIRED\]
153-
- `full`
108+
- `fields`
109+
- `weekday`
110+
- `day-weekday`
111+
- `month-day`
112+
- `month-day-weekday`
113+
- `year-month-day` (default)
114+
- `year-month-day-weekday`
115+
- `length`
154116
- `long`
155117
- `medium` (default)
156118
- `short`
157119
- _Date/time override options_
158120

121+
The `fields` and `length` _option values_ MUST each be set by a _literal_.
122+
If such an _option value_ is a _variable_,
123+
a _Bad Option Error_ is emitted and
124+
the _option_ is ignored when formatting the _expression_.
125+
159126
If the _operand_ of the _expression_ is an implementation-defined date/time type,
160127
it can include other option values.
161-
Any _operand_ options matching the `:datetime` _style options_ or _field options_ are ignored,
162-
as is any `style` option.
128+
Any _date/time override options_ of the operand are included in the resolved option values of the _expression_,
129+
with _options_ on the _expression_ taking priority over any options of the _operand_.
130+
Any _operand_ options not matching the _date/time override options_ are ignored.
163131

164132
##### Resolved Value
165133

@@ -173,10 +141,12 @@ is used as an _operand_ or an _option value_.
173141
#### The `:time` function
174142

175143
The function `:time` is used to format the time portion of date/time values.
144+
Its formatted result will always include the time,
145+
and optionally a timezone.
176146

177147
If no options are specified, this function defaults to the following:
178148

179-
- `{$t :time}` is the same as `{$t :time style=short}`
149+
- `{$t :time}` is the same as `{$t :time precision=minute}`
180150

181151
##### Operands
182152

@@ -187,19 +157,30 @@ All other _operand_ values produce a _Bad Operand_ error.
187157

188158
##### Options
189159

190-
The function `:time` has these _options_:
160+
The following _options_ are REQUIRED to be available on the function `:time`:
191161

192-
- `style` \[REQUIRED\]
193-
- `full`
162+
- `precision`
163+
- `hour`
164+
- `minute` (default)
165+
- `second`
166+
- `timeZoneStyle`
194167
- `long`
195-
- `medium`
196-
- `short` (default)
168+
- `short`
197169
- _Date/time override options_
198170

171+
If the `timeZoneStyle` _option_ is not included in the _expression_,
172+
its formatted result will not include a timezone indicator.
173+
174+
The `precision` and `timeZoneStyle` _option values_ MUST each be set by a _literal_.
175+
If such an _option value_ is a _variable_,
176+
a _Bad Option Error_ is emitted and
177+
the _option_ is ignored when formatting the _expression_.
178+
199179
If the _operand_ of the _expression_ is an implementation-defined date/time type,
200180
it can include other option values.
201-
Any _operand_ options matching the `:datetime` _style options_ or _field options_ are ignored,
202-
as is any `style` option.
181+
Any _date/time override options_ of the operand are included in the resolved option values of the _expression_,
182+
with _options_ on the _expression_ taking priority over any options of the _operand_.
183+
Any _operand_ options not matching the _date/time override options_ are ignored.
203184

204185
##### Resolved Value
205186

spec/syntax.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -588,18 +588,18 @@ option = identifier o "=" o (literal / variable)
588588
589589
> Examples of _functions_ with _options_
590590
>
591-
> A _message_ using the `:datetime` function.
592-
> The _option_ `weekday` has the literal `long` as its value:
591+
> A _message_ using the `:date` function.
592+
> The _option_ `length` has the literal `long` as its value:
593593
>
594594
> ```
595-
> Today is {$date :datetime weekday=long}!
595+
> Today is {$now :date length=long}!
596596
> ```
597597
598-
> A _message_ using the `:datetime` function.
599-
> The _option_ `weekday` has a variable `$dateStyle` as its value:
598+
> A _message_ using the `:date` function.
599+
> The _option_ `length` has a variable `$dateLength` as its value:
600600
>
601601
> ```
602-
> Today is {$date :datetime weekday=$dateStyle}!
602+
> Today is {$now :date length=$dateLength}!
603603
> ```
604604
605605
### Markup

test/tests/functions/date.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@
3333
"src": "{|2006-01-02T15:04:06| :date}"
3434
},
3535
{
36-
"src": "{|2006-01-02| :date style=long}"
36+
"src": "{|2006-01-02| :date length=long}"
3737
},
3838
{
39-
"src": ".local $d = {|2006-01-02| :date style=long} {{{$d}}}"
39+
"src": ".local $d = {|2006-01-02| :date length=long} {{{$d}}}"
4040
},
4141
{
42-
"src": ".local $d = {|2006-01-02| :datetime dateStyle=long timeStyle=long} {{{$d :date}}}"
42+
"src": ".local $d = {|2006-01-02| :datetime dateLength=long timePrecision=second} {{{$d :date}}}"
4343
}
4444
]
4545
}

test/tests/functions/datetime.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,10 @@
4545
"src": "{|2006-01-02T15:04:06| :datetime}"
4646
},
4747
{
48-
"src": "{|2006-01-02T15:04:06| :datetime year=numeric month=2-digit}"
48+
"src": "{|2006-01-02T15:04:06| :datetime dateLength=long}"
4949
},
5050
{
51-
"src": "{|2006-01-02T15:04:06| :datetime dateStyle=long}"
52-
},
53-
{
54-
"src": "{|2006-01-02T15:04:06| :datetime timeStyle=medium}"
51+
"src": "{|2006-01-02T15:04:06| :datetime timePrecision=second}"
5552
},
5653
{
5754
"src": "{$dt :datetime}",

test/tests/functions/time.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@
3030
"src": "{|2006-01-02T15:04:06| :time}"
3131
},
3232
{
33-
"src": "{|2006-01-02T15:04:06| :time style=medium}"
33+
"src": "{|2006-01-02T15:04:06| :time precision=second}"
3434
},
3535
{
36-
"src": ".local $t = {|2006-01-02T15:04:06| :time style=medium} {{{$t}}}"
36+
"src": ".local $t = {|2006-01-02T15:04:06| :time precision=second} {{{$t}}}"
3737
},
3838
{
39-
"src": ".local $t = {|2006-01-02T15:04:06| :datetime dateStyle=long timeStyle=long} {{{$t :time}}}"
39+
"src": ".local $t = {|2006-01-02T15:04:06| :datetime dateLength=long timePrecision=second} {{{$t :time}}}"
4040
}
4141
]
4242
}

0 commit comments

Comments
 (0)