message-format-wg
message-format-wg copied to clipboard
[FEEDBACK] Don't include a time zone option, or be strict if you do
Conflicts between time zones coming from different sources has been a persistent pain point that the Temporal champions have worked to avoid. It would be nice for MessageFormat to not repeat the same situation.
The problem is, what do you do if someone passes a ZonedDateTime to a MessageFormat configured with a :datetime field with a timeZone option? There are two time zones to choose from, and none of the resolution options are great:
- Use input time zone
- Bad: the time zone in the message is not respected
- Use message zone with conversion
- Bad: requires TZDB and mutates data in potentially unexpected ways (e.g. daylight saving time)
- Use message zone without conversion
- Bad: displaying an instant that differs from the input
In the Temporal specification, we handle the problem by disallowing a ZonedDateTime to be passed as input.
https://tc39.es/proposal-temporal/#sec-temporal-handledatetimevalue
However, a better design would be to forbid the formatter itself from having a time zone option, a luxury we didn't have when integrating Temporal with the pre-existing Intl.DateTimeFormat.
(as individual contributor)
Omitting support for time zones is super unhelpful for users, who will want to format date and time values and who have needs for managing the time zone used (or not used, in the case of floated or "plain" values) and who do not always have control over the format of the incoming value.
A ZonedDateTime is a moment attached to the timeline. It is a clearly identified moment in time with no ambiguity. It can be formatted for display, and users will want to pass it for formatting. Otherwise, what is the point?
A user can have a ZonedDateTime and wish to use a different time zone for displaying the value. Or they might have done as you seem to be suggesting and have an Instant--in which case they had better have a timeZone option to allow for proper display! The same thing goes for classical date/time values (such as Date), which crave a time zone for proper expression. Or I could make a PlainDateTime out of the ZDT, but then I can't show the time zone with the time value (which is a loss of precision).
The timeZone option allows the message author to override the zone when it is present and perform the conversion (it also allows the value to be "floated"--removed from the timeline so that the digits are constant). Does conversion require the TZDB? Yes, but then the implementation already needs the TZDB in order to render date and time values that include a time zone or to format incremental time values.
Note that the timeZone option does not "mutate the data". The resolved value of an expression might be a different ZonedDateTime than the input, but the input cannot itself be mutated.
Is there some danger that users will do Bad Things using timeZone? Sure. But the tripping hazards seem far smaller to me than providing no control and requiring users to apply everything in the cookbook to do simple formatting.
(as chair)
Please note that this option is PROPOSED for 2.0 and is still open to change. Please file normal issues or (better yet) submit a design document for what we should do.
Does conversion require the TZDB? Yes, but then the implementation already needs the TZDB in order to render date and time values that include a time zone or to format incremental time values.
ICU4X formats datetimes without access to full TZDB. This is possible so long as the datetime is annotated with an offset from elsewhere in the stack. For example, the server can calculate the offset from TZDB and send an annotated IXDTF string to a client running ICU4X that does not need TZDB to format it.
~If you insist on having~ If the WG feels it is beneficial to have a timeZone option, I would like it to have the behavior where it is applied only for Instant formatting. The spec should say something like:
- The timeZone option should be used only if the input value is an instant in time, such as number of seconds since UNIX epoch, not associated with a particular time zone
- If the timeZone option is specified and the input is any other type, such as a ZonedDateTime or PlainDateTime, an input error should be thrown
@sffc notes:
I would like it to have the behavior where it is applied only for Instant formatting.
There are a number of problems here.
One is: MF2 does not have types. We can specify that implementations are allowed to do certain things or allowed to emit certain errors.
If the timeZone option is specified and the input is any other type, such as a ZonedDateTime or PlainDateTime, an input error should be thrown
I agree with your earlier assertion that the operations in question should be carefully defined.
It cannot be an "input error" because there is no such thing in MF2. It can be a Bad Option error or an Unsupported Operation error.
I might be convinced in the case of ZDT, but I'm having a hard time agreeing in the case of PDT. There are obviously different ways that such conversions can occur (does one interpret the PDT 2024-11-25T00:00:00 as being midnight in the requested zone or as being midnight in UTC and the zone's offset adjusting the value?). Specifying these is useful and valuable.
People want timekeeping to be simpler to use, not filled with arduous details.
In any case, I suspect the action item here is for me to go back and write a design document for this option so that we color in all of the details prior to finalizing it (which might include removing or disabling bits of it)
A couple of comments:
If I supply an input parameter like $t being an implementation-defined datatype {datetime=2025-01-21T9:30 timezone=America/Los_Angeles} to the message:
{{The time in Berlin is {$t :datetime timezone=|Europe/Berlin|}}}
I would expect to see the formatted datetime for 2025-01-21T18:30, not 2025-01-21T9:30.
The same with {datetime=2025-01-21T9:30Z}.
This is then different than supplying a currency option to :currency; that needs to be illegal because currencies are not convertible.
A system might also have two separate input parameters:
$t being{datetime=2025-01-21T9:30}
$z being "America/Los_Angeles"
and formatting
{{The time is {$t :datetime timezone=$z}}}
I would expect to see the formatted datetime for 2025-01-21T18:30, not 2025-01-21T9:30.
(as chair of ICU4X-TC)
That's fair; I just want to emphasize that time zone conversion is not free and takes a large amount of data (the TZDB). We have done a pretty good job of keeping MF2 dependencies minimal and I would really like if we didn't add TZDB as a requirement.
It cannot be an "input error" because there is no such thing in MF2. It can be a Bad Option error or an Unsupported Operation error.
This doesn't make a lot of sense to me. What kind of error do I get when I pass the string "hello world" as an input to be formatted as a date? Or a Symbol or a HashMap or some other nonsensical type? You can throw the same type of error if the type to be formatted contains a time zone.
What kind of error do I get when I pass the string "hello world" as an input to be formatted as a date? Or a Symbol or a HashMap or some other nonsensical type?
Probably Bad Operand.
You can throw the same type of error if the type to be formatted contains a time zone.
If the operand were formattable without a timeZone option set, it would probably be more appropriate to emit an Unsupported Operation error.
It would probably be a good idea to include something like what we have under Unit Conversion for timeZone as well: https://github.com/unicode-org/message-format-wg/blob/ec9089dd85cd5d8dc1f68807ab3551383bd74965/spec/registry.md?plain=1#L791-L794
I suspect the action item here is for me to go back and write a design document for this option so that we color in all of the details prior to finalizing it (which might include removing or disabling bits of it)
If it'd be helpful, I'd be happy to review that design doc when it's ready. For context: I'm one of the champions of the Temporal proposal and I was, years ago, responsible for the initial design of Temporal.ZonedDateTime. So I'm fairly familiar with time zone stuff on the Temporal side.
But I'm not as familiar with how time zones are proposed to be used in MF. Would it be possible to share a few examples of message templates (is that the right term?) with time zones, and ideally the use cases that make those templates important? Even if these might change as you evolve a design, it's hard to understand exactly what we're talking about without seeing a few concrete examples and use cases. Thanks!
calendar won't be stable until 48
We should revisit this discussion for CLDR 48.
It seems like multiple MessageFormat WG delegates feel that the timeZone override option is useful. If we aren't removing it entirely, then I would like to see something along the lines of:
- If the option is specified, clarify that Instant-like and ZonedDateTime-like input types, including JS Date and similar, should be converted into the time zone before formatting.
- ICU4X will not be able to support the option with this shape of input, since ICU4X does not intend to ever add support for time zone conversions. Therefore, the option should be OPTIONAL. Or, maybe if the option is specified, ICU4X throws a Bad Operand error if given a type that requires conversion?
- As a Temporal champion, I'm highly skeptical that PlainDateTime-like input types should be supported here, since PlainDateTime is specifically not something that has a time zone, but if the WG feels that such types should be allowed in this position, specify that the wall time is retained when associating the time zone.
- ICU4X could support the option in this context, if the WG wants to support it.
I know you don't like me talking about Temporal types, but I think it's crucial to specify this behavior if we want to make an interoperable standard.
I know you don't like me talking about Temporal types, but I think it's crucial to specify this behavior if we want to make an interoperable standard.
Huh? What gives you that impression? Temporal types are important to getting date/time formatting (and handling in general) correct. The tension you may feel is to not forget classical timekeeping or create a standard that requires Temporal to work, since not all platforms have or can have Temporal.
PlainDateTime-like input types should be supported here, since PlainDateTime is specifically not something that has a time zone, but if the WG feels that such types should be allowed in this position, specify that the wall time is retained when associating the time zone
This seems weird to me? "Plain" date/time values specifically don't have a time zone, but users sometimes need to "unfloat" the value (connect it to the timeline). (It's more common to need to "float" a zoned or instant value.) The ability to float and unfloat date/time values is often useful in the formatting layer because the developer cannot always control what form the data value takes, but does know what the display use case is. I fully agree that we need to clearly and carefully describe what the behaviors are. See, for example, here.
It's not clear to me that MF is the right place to do the "float/unfloat". If the time zone is hard-coded in the message, how do you know how to convert your input PlainDateTime to the correct time zone?
I believe that this was resolved by #1078?
I don't think we've addressed this comment:
It's not clear to me that MF is the right place to do the "float/unfloat". If the time zone is hard-coded in the message, how do you know how to convert your input PlainDateTime to the correct time zone?