Skip to content
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

After ZonedDateTime lands, what should Instant.prototype.toLocaleString output? #1025

Closed
justingrant opened this issue Oct 20, 2020 · 2 comments

Comments

@justingrant
Copy link
Collaborator

Temporal.Instant is narrowly focused on machine readable persistence and interop use cases. Instant has no way to provide any user-facing output with only one exception: toLocaleString. Otherwise, if you want user-facing output, you convert to another Temporal type by supplying a time zone and a calendar.

One of the learnability challenges we'll have with Temporal is teaching developers that Instant has no time zone and that to do anything user-facing with it you need to convert it to another type. A canonical example of this is #1021 where the developer assumed that calling plainDatetime.toInstant(tz) would persist the time zone in the resulting Instant, and was surprised that toLocaleString used the user's system time zone instead of the time zone he explicitly supplied to PlainDateTime.prototype.toInstant.

To prevent errors like this, should we make toLocaleString consistent with all other Instant methods, meaning that no enduser-facing output comes out without first converting it to another Temporal type?

My recommendation would be to output an ISO "Z" string e.g. 2020-01-01T00:00Z, with the goal of helping users understand that Temporal.Instant simply doesn't do enduser-facing output. It needs additional data to be useful to end users. Another option would be to throw with a message encouraging conversion, but I think outputting an ISO string is a less draconian way of achieving the same result.

Another benefit of making this change could be clarifying the difference between Instant and legacy Date. The latter shares Instant's data model (modulo precision) but the output of many Date methods pretends that Date also has a time zone. This muddiness about the data model causes a very common bug where novice JS devs assume that time-zone-relative values will be the same when the system time zone changes (e.g. airplane lands) or when serializing a Date. We don't want users of Instant to make the same assumption.

That said, I probably don't know the full range of use cases that Instant.prototype.toLocaleString is used for. There might be an important reason to show a system timezone-formated output that I'm not aware of. Let's discuss.

P.S. - here's a few other related cases of new-to-Temporal developers being confused about Instant, PlainDateTime, and ZonedDateTime and how they relate. My point isn't that changing toLocaleString output will fix all these problems. Rather, my point is that explaining the difference between these types is probably the hardest teaching challenge we'll have. It'd be good to try to make this easier.

@sffc
Copy link
Collaborator

sffc commented Oct 21, 2020

The current Temporal.Instant.prototype.toLocaleString behavior is among the oldest behaviors in Temporal, and I think it should stay the way it is.

tl;dr: There are legitimate use cases for localized output of an Instant; the behavior is well-defined; and the alternative is verbose and unergonomic.

Instants have a human-readable representation

We've often said that server log timestamps are the canonical use case for instants. Well, we see over and over again that the way people like to represent server log timestamps is by projecting them into the user's local time zone and calendar system. Here is a screenshot from console.cloud.google.com to illustrate:

image

The same type of format can be seen in Apache server logs and many other logging tools.

The time zone and calendar come from the locale

Instants have no time zone. That's why Temporal.Instant.prototype.toLocaleString is the only such function in Temporal that obeys the time zone coming from the locale.

UTS 35 has a well-defined mechanism for the user requesting their preferred time zone. It looks like this: "en-US-u-tz-uschi". The time zone subtags correspond to IANA names; you can find the full list here.

The time zone from the locale can also be overridden with an argument, such as

instant.toLocaleString("pt-BR", { timeZone: "Europe/London" });

Likewise, these functions also project the instant into the user's calendar system.

Converting to ZonedDateTime for formatting is verbose and unergonomic

Currently, you can write:

instant.toLocaleString();

If we force people to transition to ZonedDateTime, the equivalent code would be

instant.toZonedDateTime({
  timeZone: Temporal.now.timeZone(),
  calendar: new Intl.DateTimeFormat().resolvedOptions().calendar,
}).toLocaleString()

Given the decision from #262, one could use toZonedDateTimeISO and save a some characters. However, that line is misleading, since the output will definitively not be on the ISO calendar system, and it is still more verbose, less discoverable, and more prone to error than just using toLocaleString() directly on the Instant.

@sffc sffc added this to the Complete design decisions milestone Oct 22, 2020
@ptomato
Copy link
Collaborator

ptomato commented Oct 22, 2020

Meeting, Oct. 22: this should remain the same. #1021 is about documenting it. Closing since nothing else needs to be changed.

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

No branches or pull requests

3 participants