8000 Define time zone values and conversions by eemeli · Pull Request #1078 · unicode-org/message-format-wg · GitHub
[go: up one dir, main page]

Skip to content

Define time zone values and conversions #1078

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

eemeli
Copy link
Collaborator
@eemeli eemeli commented Jun 8, 2025

This is proposed as a separate change from #1077, as it was not discussed on the call.

The intent with the text updated here is to clarify what happens when the timeZone option is set on a date/time function.

The SHOULD/MAY language that's proposed is intended to allow for an implementation that does not support time zone conversions, which I believe matches the case in JS Temporal.

Is there prior art of local being used as a time zone value as we're proposing, or are there alternatives that other date/time formatters use?

@eemeli eemeli requested review from aphillips and sffc June 8, 2025 06:47
> into a [floating](https://www.w3.org/TR/timezone/#floating) time value
> (sometimes called a _plain_ or _local_ time value) by removing
> the association with a specific time zone.
The value `local` corresponds to the default time zone.
Copy link
Member

Choose a reason for hiding this comment

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

The value local is meant to remove the time zone (it floats the value). This is different from the default time zone. Consider:

.local $event = {|2025-06-28T19
10000
:00:00Z| :datetime}
{{The Annual Barn Dance will be on {$event :date timeZone=local}.}}

The above formats as "June 28, 2025" regardless of where the message is viewed, vs. potentially formatting as "June 29, 2025" or "June 27, 2025" depending on the default time zone. The name local I find misleading. The Temporal synonym is plain, which I also find unhelpful.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh, so local is effectively "local" to the input value, rather than being "local" to the time zone of the environment where the formatting is being done, yes? I had understood it the other way around.

We should probably use a different term that is more implicitly obvious about its meaning. Maybe input?

Copy link
Member

Choose a reason for hiding this comment

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

As expressed elsewhere, I hate the term local for this. It makes more sense in HTML forms, where presumably the user in inputting local wall time, but no sense in a context like MF. Temporal uses the term plain for this

Comment on lines +287 to +290
If the _operand_ value does not include a time zone,
it is presumed to use the default time zone.
If the _operand_ value does include a time zone and the `timeZone` _option_ is set,
an implementation SHOULD convert the value to the time zone indicated by the _option_.
Copy link
Member

Choose a reason for hiding this comment

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

I think this reads oddly, since the result of the first sentence would be that all operands end up with a time zone.

Lots of operands do not "include" a time zone--all classical date/time values, such as JS Date, for example. It's not helpful to think of assigning a time zone to the value so much as it is to think of assigning a time zone to the expression (so that an incremental time stamp can be converted to wall time). Consider:

When it is {$d :datetime} for you
it is {$d :datetime timeZone=|America/Los_Angeles|} in L.A.

I would say:

Suggested change
If the _operand_ value does not include a time zone,
it is presumed to use the default time zone.
If the _operand_ value does include a time zone and the `timeZone` _option_ is set,
an implementation SHOULD convert the value to the time zone indicated by the _option_.
If the _expression_ includes a valid `timeZone` _option_
and the _operand_'s value also includes a time zone,
an implementation SHOULD convert the _resolved value_ of the _operand_
to the time zone indicated by the _option_.
Otherwise, the time zone indicated by the _option_ should be used to format the value.

Note that it is unclear what "convert" means and the conversion means different things depending on the operand type. See here for examples of types. The conversion is one thing for a floating time or an incremental time/timestamp (you just add the time zone to the value) but requires calculation through a calendar for "zoned" values. The value local for timeZone exists to let the user remove the zone from a "zoned" value (so that the field values are no longer affected by the default--or any other--time zone).

Copy link
Collaborator Author
@eemeli eemeli Jun 9, 2025

Choose a reason for hiding this comment

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

The conversion is one thing for a floating time or an incremental time/timestamp (you just add the time zone to the value) but requires calculation through a calendar for "zoned" values.

This does not match my understanding of what would happen if a time without an explicit timezone (such as a JS Date, which internally is handled as an incremental time/timestamp) would be formatted while explicitly setting timeZone.

With the JS Intl.DateTimeFormat, this happens:

const now = new Date()

new Intl.DateTimeFormat('en-de',{timeStyle:'long'}).format(now)
// "11:10:55 CEST"

new Intl.DateTimeFormat('en-de',{timeZone:'America/Los_Angeles',timeStyle:'long'}).format(now)
// "02:10:55 GMT-7"

So effectively the date being formatted is always considered to use the local/system time zone, and setting timeZone will format the date with conversion through a calendar.

My strong preference would be for the MF2 :datetime to behave similarly to the current JS behaviour, where the input/operand value is always considered to have some timezone (by default, the system default), and for formatting to happen in some timezone (by default, the system default). Setting the timeZone on the expression controls the timezone used for formatting, but does not change the timezone of the input.

Do the ICU datetime formatters use a similar approach, or do they do something different?

Copy link
Member

Choose a reason for hiding this comment

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

No, you're right. And ICU does it the same way. It's my description that is somewhat wonky.

If you have a timestamp, you always need a calendar to format the value, but the application of a time zone (the default or some explicit value) doesn't change the timestamp itself. If you have a "zoned" value, you use a calendar to compute the instant and then modify the value by applying the explicitly provided time zone (you wouldn't use the default zone with a zoned value, presumably).

The value `local` corresponds to the default time zone.

If the _operand_ value does not include a time zone,
it is presumed to use the default time zone.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it's not clear here if "the default time zone" is meant to be the result of accessing the system time zone setting, or a single default time zone (e.g. UTC).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The intent with the proposed language is to match the text from earlier in the same section:

**_<dfn>Date/time override options</dfn>_** 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.

Does that context clarify the meaning here?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
it is presumed to use the default time zone.
it is presumed to use the default time zone specified by the formatting context.

Ah, I missed that. How about this, then?

Copy link
Member
@sffc sffc left a comment

Choose a reason for hiding this comment

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

Fallback algorithm seems ok, since it has an out for an implementation that doesn't support time zone conversion

@@ -282,11 +282,14 @@ the functions `:datetime`, `:date`, and `:time`.
- `local`
Copy link
Member

Choose a reason for hiding this comment

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

Not sure if I like the ident "local"; that word is way overloaded. I think "system" or "default" would be better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0