Skip to content
Open
Changes from all commits
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
129 changes: 73 additions & 56 deletions spec/functions/datetime.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,31 @@ If no options are specified, this function defaults to the following:
##### `:datetime` Operands

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](#date-and-time-operands).
an implementation-defined date/time type,
or a string matching the `date-time-ext` rule of
[RFC 9557](https://www.rfc-editor.org/rfc/rfc9557#name-abnf).
All other _operand_ values produce a _Bad Operand_ error.

If the _resolved value_ of the _operand_ does not include a time,
`00:00:00` is used as the time.
Comment on lines +44 to +45

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Note that time 00:00 is not guaranteed to exist for every date in any particular time zone, although that is also true for e.g. 02:xx.


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.

> [!NOTE]
> String values passed as variables in the _formatting context_'s
> _input mapping_ can be formatted as datetime values as long as their
> contents match the `date-time-ext` rule.
>
> 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}}}
> ```

##### `:datetime` Options

The following _options_ are REQUIRED to be available on the function `:datetime`:
Expand Down Expand Up @@ -97,10 +118,33 @@ If no options are specified, this function defaults to the following:
##### `:date` Operands

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](#date-and-time-operands).
an implementation-defined date/time type,
or a string matching the `date-time-ext` rule of
[RFC 9557](https://www.rfc-editor.org/rfc/rfc9557#name-abnf),
or a string matching the `full-date` rule of
[RFC 3339](https://www.rfc-editor.org/rfc/rfc3339#section-5.6).
All other _operand_ values produce a _Bad Operand_ error.

@rxaviers rxaviers Mar 18, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@eemeli said: For (time), the proposal specifically includes this:

If the resolved value of the operand does not include a time,
a Bad Operand error is produced.

@eemeli, for consistency, shall we include the analogous here?

Suggested change
All other _operand_ values produce a _Bad Operand_ error.
All other _operand_ values produce a _Bad Operand_ error.
If the _resolved value_ of the _operand_ does not include a date,
a _Bad Operand_ error is produced.

... to guarantee this edge case also produces Bad Operand


If the _resolved value_ of the _operand_ does not include a time,
`00:00:00` is used as the time.
Comment on lines +128 to +129

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Here in :date, nonexistence probably matters more.

Suggested change
If the _resolved value_ of the _operand_ does not include a time,
`00:00:00` is used as the time.
If the _resolved value_ of the _operand_ does not include a time,
`12:00:00` is used as the time.


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.

> [!NOTE]
> String values passed as variables in the _formatting context_'s
> _input mapping_ can be formatted as date values as long as their
> contents match the `full-date` rule.
>
> For example, if the value of the variable `now` were the string
> `2024-02-06`, it would behave identically to the local
> variable in this example:
>
> ```
> .local $example = {|2024-02-06| :date}
> {{{$now :date} == {$example}}}
> ```

##### `:date` Options

The following _options_ are REQUIRED to be available on the function `:date`:
Expand Down Expand Up @@ -151,10 +195,33 @@ If no options are specified, this function defaults to the following:
##### `:time` Operands

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](#date-and-time-operands).
an implementation-defined date/time type,
or a string matching the `date-time-ext` rule of
[RFC 9557](https://www.rfc-editor.org/rfc/rfc9557#name-abnf),
or a string matching the `time` rule of
[RFC 3339](https://www.rfc-editor.org/rfc/rfc3339#section-5.6).
Comment on lines +201 to +202

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I do not see a time rule in RFC 3339 section 5.6. There is one in RFC 3339 Appendix A, although it allows values like "1023:42"/"-23"/"-23:42"/"--42"/"10-05" so I don't think we should use it.

All other _operand_ values produce a _Bad Operand_ error.

If the _resolved value_ of the _operand_ does not include a time,
a _Bad Operand_ error is produced.

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.

> [!NOTE]
> String values passed as variables in the _formatting context_'s
> _input mapping_ can be formatted as time values as long as their
> contents match the `time` rule.
>
> For example, if the value of the variable `now` were the string
> `16:40:00`, it would behave identically to the local
> variable in this example:
>
> ```
> .local $example = {|16:40:00| :time}
> {{{$now :time} == {$example}}}
> ```

##### `:time` Options

The following _options_ are REQUIRED to be available on the function `:time`:
Expand Down Expand Up @@ -191,56 +258,6 @@ 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_.

#### Date and Time Operands

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 **_<dfn>date/time literal value</dfn>_** 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.

```regexp
(?!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](https://w3c.github.io/timezone).

> [!IMPORTANT]
> The [ABNF](/spec/message.abnf) and [syntax](/spec/syntax.md) 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 and Time Override Options

**_<dfn>Date/time override options</dfn>_** are _options_ that allow an _expression_ to
Expand Down