tc39/ecma402

Cannot output only era or timeZoneName

Opened this issue · 12 comments

Currently, we can use the option in Date.toLocale*String or Intl.DateTimeFormat to output most of the property in "Table 6: Components of date and time formats"
https://ecma-international.org/ecma-402/#datetimeformat-objects

d8> (new Date()).toLocaleString("en", {weekday: "long"})
"Thursday"
d8> (new Date()).toLocaleString("en", {year: "numeric"})
"2020"
d8> (new Date()).toLocaleString("en", {month: "long"})
"June"
d8> (new Date()).toLocaleString("en", {day: "numeric"})
"18"
d8> (new Date()).toLocaleString("en", {hour: "numeric"})
"12 AM"
d8> (new Date()).toLocaleString("en", {hour: "numeric"})
"12 AM"
d8> (new Date()).toLocaleString("en", {minute: "numeric"})
"3"
d8> (new Date()).toLocaleString("en", {second: "numeric"})
"51"

But if we put era or timeZoneName into the option, it will output more than just era / timeZoneName due to the ToDateTimeOptions

d8> (new Date()).toLocaleString("en", {era: "long"})
"6 18, 2020 Anno Domini, 12:01:54 AM"
d8> (new Date()).toLocaleString("en", {timeZoneName: "long"})
"6/18/2020, 12:04:05 AM Pacific Daylight Time"

Should we change ToDateTimeOptions to consider also era and timeZoneName so we can only output era or timeZoneName as the following. Would that be better?

d8> (new Date()).toLocaleString("en", {era: "long"})
"Anno Domini"
d8> (new Date()).toLocaleString("en", {timeZoneName: "long"})
"Pacific Daylight Time"
anba commented

A workaround to get the time zone resp. era name is to invoke formatToParts:

js> new Intl.DateTimeFormat("en", {timeZoneName:"long"}).formatToParts().filter(({type}) => type === "timeZoneName")[0].value               
"Pacific Daylight Time"
js> new Intl.DateTimeFormat("en", {era:"long"}).formatToParts().filter(({type}) => type === "era")[0].value                   
"Anno Domini"

I wonder if there are any meeting notes or es-discuss mails why "era" and "timeZoneName" aren't allowed as standalone elements in ToDateTimeOptions.

A workaround to get the time zone resp. era name is to invoke formatToParts:

js> new Intl.DateTimeFormat("en", {timeZoneName:"long"}).formatToParts().filter(({type}) => type === "timeZoneName")[0].value               
"Pacific Daylight Time"
js> new Intl.DateTimeFormat("en", {era:"long"}).formatToParts().filter(({type}) => type === "era")[0].value                   
"Anno Domini"

I wonder if there are any meeting notes or es-discuss mails why "era" and "timeZoneName" aren't allowed as standalone elements in ToDateTimeOptions.

yea, but that is a very clumsy way to get it, right?

sffc commented

This sounds like something for DisplayNames, no?

DateTimeFormat should be for formatting dates and times. If anything, we should do more to make sure there is enough information in a string to decipher a date, not less.

This sounds like something for DisplayNames, no?

First of all, the reason I raise this is not just for the functionality, but for the coherence / consistency of the Intl.DateTimeFormat
Second, the issue could be solved by DisplayNames IF we also know the timeZone itself. But if we do not know the timeZone ID itself, for example, the following case, how could we get the "Pacific Daylight Time" back?
(new Date()).toLocaleString("en", {timeZoneName: "long"})

sffc commented

In the case, the time zone implicitly defaults to the system time zone, so Temporal.now.timeZone() should suffice to get the time zone ID, and then you can pass that to Intl.DisplayNames.

A workaround to get the time zone resp. era name is to invoke formatToParts:

That assumes the presentation of the era/time zone in broader context, is suitable for use in standalone context as well. That may not be a universal assumption, nor one that will hold in the future, seems like.

anba commented

CLDR doesn't seem to provide standalone formats for time zone resp. era in <availableFormats>. (I'm not even sure there's an explicit standalone support for era and time zones at all in CLDR. https://unicode.org/reports/tr35/tr35-dates.html#months_days_quarters_eras doesn't mention standalone contexts for eras. The same seems to apply for https://unicode.org/reports/tr35/tr35-dates.html#Time_Zone_Names.)

sffc commented

I could imagine that the time zone or era name could be context-dependent, like grammatical case, pluralization rules, etc., although I don't know of this being done in practice.

Just adding to this - it would be amazing if we could obtain only the Timezone name from Date object. It seems strange to me that when we look for timezone name, we get the date thrown in as well, because of the different display options for the date (slashes, dots, spaces, before / after the timezone name) it makes it very difficult to strip out just the timezone name from the resulting string - here's a few examples in different languages:

Here's the code I am using:

    const timezoneFormat = new Intl.DateTimeFormat(userLocale, {
      timeZoneName: 'long',
    });

    const tz = timezoneFormat.format(new Date());
    const tf = timezoneFormat.format(new Date()).split(' ').slice(1).join(' ');

    console.log(`tz: ${tz}`);
    console.log(`tf: ${tf}`);
    console.log(` `);

As you can see, I find it strange that the date is thrown into the result and attempts to split it out are hampered in some timezones due to the formatting. I'm glad to see the workaround above but it would be great to address this :)

Running into this as well while trying to use the longOffset format. Would be useful when presenting the user with a list of time zones and their offsets.