Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 62 additions & 105 deletions spec/functions/datetime.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

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.

> [!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.
Expand All @@ -14,15 +10,14 @@ This subsection describes the _functions_ and _options_ for date/time formatting

#### The `:datetime` function

The function `:datetime` is used to format date/time values, including
the ability to compose user-specified combinations of fields.
The function `:datetime` is used to format both the date and time of a date/time value.

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

- `{$d :datetime}` is the same as `{$d :datetime dateStyle=medium timeStyle=short}`
- `{$d :datetime}` is the same as `{$d :datetime dateFields=year-month-day timePrecision=minute}`

> [!NOTE]
> The default formatting behavior of `:datetime` is inconsistent with `Intl.DateTimeFormat`
> 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`.

Expand All @@ -35,93 +30,39 @@ All other _operand_ values produce a _Bad Operand_ error.

##### Options

The `:datetime` function can use either the appropriate _style options_
or can use a collection of _field options_ (but not both) to control the formatted
output.
_Date/time override options_ can be combined with either _style options_ or _field options_.

If both _style options_ and _field options_ are specified,
a _Bad Option_ error is emitted
and a _fallback value_ used as the _resolved value_ of the _expression_.

If the _operand_ of the _expression_ is an implementation-defined date/time type,
it can include _style options_, _field options_, or other _options_.
These are included in the resolved option values of the _expression_,
with _options_ on the _expression_ taking priority over any options of the _operand_.

> [!NOTE]
> The names of _options_ and their _option values_ were derived from the
> [options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/resolvedOptions#description)
> in JavaScript's `Intl.DateTimeFormat`.

###### Style Options

**_<dfn>Style options</dfn>_** pertain to the overall styling or appearance of the formatted output.

The following _style options_ are REQUIRED to be available on the function `:datetime`:

- `dateStyle`
- `full`
- `long`
- `medium`
- `short`
- `timeStyle`
- `full`
- `long`
- `medium`
- `short`

###### Field Options

**_<dfn>Field options</dfn>_** describe which fields to include in the formatted output
and what format to use for that field.

> [!NOTE]
> _Field options_ do not have default values because they are only to be used
> to compose the formatter.

The following _field options_ are REQUIRED to be available on the function `:datetime`:

- `weekday`
- `long`
- `short`
- `narrow`
- `era`
- `long`
- `short`
- `narrow`
- `year`
- `numeric`
- `2-digit`
- `month`
- `numeric`
- `2-digit`
The following _options_ are REQUIRED to be available on the function `:datetime`:

- `dateFields`
- `day`
- `weekday`
- `day-weekday`
- `month-day`
- `month-day-weekday`
- `year-month-day` (default)
- `year-month-day-weekday`
- `dateLength`
- `long`
- `medium` (default)
- `short`
- `narrow`
- `day`
- `numeric`
- `2-digit`
- `hour`
- `numeric`
- `2-digit`
- `minute`
- `numeric`
- `2-digit`
- `second`
- `numeric`
- `2-digit`
- `fractionalSecondDigits`
- `1`
- `2`
- `3`
- `timeZoneName`
- `timePrecision`
- `hour`
- `minute` (default)
- `second`
- `timeZoneStyle`
- `never` (default)
- `long`
- `short`
- `shortOffset`
- `longGeneric`
- `longOffset`
- `short`
- `shortGeneric`
- `longGeneric`
- `shortOffset`
- _Date/time override options_

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.

##### Resolved Value

Expand All @@ -136,7 +77,7 @@ 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 style=medium}`
- `{$d :date}` is the same as `{$d :date fields=year-month-day length=medium}`

##### Operands

Expand All @@ -147,19 +88,27 @@ All other _operand_ values produce a _Bad Operand_ error.

##### Options

The function `:date` has these _options_:

- `style` \[REQUIRED\]
- `full`
The following _options_ are REQUIRED to be available on the function `:date`:

- `fields`
- `day`
- `weekday`
- `day-weekday`
- `month-day`
- `month-day-weekday`
- `year-month-day` (default)
- `year-month-day-weekday`
- `length`
- `long`
- `medium` (default)
- `short`
- _Date/time override options_

If the _operand_ of the _expression_ is an implementation-defined date/time type,
it can include other option values.
Any _operand_ options matching the `:datetime` _style options_ or _field options_ are ignored,
as is any `style` option.
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.

##### Resolved Value

Expand All @@ -176,7 +125,7 @@ The function `:time` is used to format the time portion of date/time values.

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

- `{$t :time}` is the same as `{$t :time style=short}`
- `{$t :time}` is the same as `{$t :time precision=minute timeZoneStyle=never}`

##### Operands

Expand All @@ -187,19 +136,27 @@ All other _operand_ values produce a _Bad Operand_ error.

##### Options

The function `:time` has these _options_:
The following _options_ are REQUIRED to be available on the function `:time`:

- `style` \[REQUIRED\]
- `full`
- `precision`
- `hour`
- `minute` (default)
- `second`
- `timeZoneStyle`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

timeZoneStyle or zoneStyle?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

timeZoneStyle. As I mention in #1082 (comment),

I'd be fine with timeZoneStyle or timeZoneDisplay. Abbreviating out the "time" part would be a mistake -- it's not at all obvious to anyone who's not worked closely with datetime formatting that an unspecified "zone" is referring to a time zone [1].

[1] Unscientifically just verified this by asking three non-developer relatives about the meaning of the last option in the example at the top post here. They were quite confused, until I changed the name to timeZoneStyle.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The experimental ICU4X syntax uses zoneStyle and the Rust API uses zone

- `never` (default)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the "never" string used elsewhere in MF2? Seems like "hidden" or something might make more sense in this context

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's used for a number of number function options.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little discussion: "never" feels better when used as an adverb in context with always/never

- `long`
- `medium`
- `short` (default)
- `longGeneric`
- `longOffset`
- `short`
- `shortGeneric`
- `shortOffset`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Observation: these are the ECMA names, which are not exactly the same as the names in the experimental ICU4X JSON syntax.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- _Date/time override options_

If the _operand_ of the _expression_ is an implementation-defined date/time type,
it can include other option values.
Any _operand_ options matching the `:datetime` _style options_ or _field options_ are ignored,
as is any `style` option.
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.

##### Resolved Value

Expand Down
12 changes: 6 additions & 6 deletions spec/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -588,18 +588,18 @@ option = identifier o "=" o (literal / variable)

> Examples of _functions_ with _options_
>
> A _message_ using the `:datetime` function.
> The _option_ `weekday` has the literal `long` as its value:
> A _message_ using the `:date` function.
> The _option_ `length` has the literal `long` as its value:
>
> ```
> Today is {$date :datetime weekday=long}!
> Today is {$now :date length=long}!
> ```

> A _message_ using the `:datetime` function.
> The _option_ `weekday` has a variable `$dateStyle` as its value:
> A _message_ using the `:date` function.
> The _option_ `length` has a variable `$dateLength` as its value:
>
> ```
> Today is {$date :datetime weekday=$dateStyle}!
> Today is {$now :date length=$dateLength}!
> ```

### Markup
Expand Down
6 changes: 3 additions & 3 deletions test/tests/functions/date.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
"src": "{|2006-01-02T15:04:06| :date}"
},
{
"src": "{|2006-01-02| :date style=long}"
"src": "{|2006-01-02| :date length=long}"
},
{
"src": ".local $d = {|2006-01-02| :date style=long} {{{$d}}}"
"src": ".local $d = {|2006-01-02| :date length=long} {{{$d}}}"
},
{
"src": ".local $d = {|2006-01-02| :datetime dateStyle=long timeStyle=long} {{{$d :date}}}"
"src": ".local $d = {|2006-01-02| :datetime dateLength=long timePrecision=second} {{{$d :date}}}"
}
]
}
7 changes: 2 additions & 5 deletions test/tests/functions/datetime.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,10 @@
"src": "{|2006-01-02T15:04:06| :datetime}"
},
{
"src": "{|2006-01-02T15:04:06| :datetime year=numeric month=2-digit}"
"src": "{|2006-01-02T15:04:06| :datetime dateLength=long}"
},
{
"src": "{|2006-01-02T15:04:06| :datetime dateStyle=long}"
},
{
"src": "{|2006-01-02T15:04:06| :datetime timeStyle=medium}"
"src": "{|2006-01-02T15:04:06| :datetime timePrecision=second}"
},
{
"src": "{$dt :datetime}",
Expand Down
6 changes: 3 additions & 3 deletions test/tests/functions/time.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@
"src": "{|2006-01-02T15:04:06| :time}"
},
{
"src": "{|2006-01-02T15:04:06| :time style=medium}"
"src": "{|2006-01-02T15:04:06| :time precision=second}"
},
{
"src": ".local $t = {|2006-01-02T15:04:06| :time style=medium} {{{$t}}}"
"src": ".local $t = {|2006-01-02T15:04:06| :time precision=second} {{{$t}}}"
},
{
"src": ".local $t = {|2006-01-02T15:04:06| :datetime dateStyle=long timeStyle=long} {{{$t :time}}}"
"src": ".local $t = {|2006-01-02T15:04:06| :datetime dateLength=long timePrecision=second} {{{$t :time}}}"
}
]
}