js-temporal/temporal-polyfill

RangeError on Chrome for Android only

khawarizmus opened this issue · 10 comments

The following snippet of code works well on all major browsers (desktop) and it works on Firefox for android as well as safari for IOS

const HijriT = Temporal.Now.zonedDateTime("islamic-umalqura", timeZone);
console.log(HijriT.day);

However on Chrome for Android it throws the following error:

RangeError: era must be ah, not bc

My chrome version is 142.0.6367.179
Tested no Android 14.

If it helps the error is coming from here

This looks like a bug in Intl.DateTimeFormat on this version of Chrome for Andriod. To confirm, run this code on the android device:

new Intl.DateTimeFormat(`en-US-u-ca-islamic-umalqura`, { era: 'short' })
  .formatToParts(new Date(2024, 04, 27))
  .find(part => part.type === 'era')
  .value

If it returns "AH" (as it does on Chrome for Mac 125.0.6422.77) then it's working properly. If it returns "BC" then there's a problem with the calendar data available on that version of Chrome.

It might be that this particular Android version was not compiled with non-Gregorian calendar data. You can check this by simply running this:

new Intl.DateTimeFormat(`en-US-u-ca-islamic-umalqura`, { era: 'short' })
  .formatToParts(new Date(2024, 04, 27))

Do the results look like Gergorian dates or Islamic calendar dates? This will be useful into to put in your bug report.

@sffc if this is indeed an Android-specific Chrome bug with Intl.DateTimeFormat, where should a bug report be filed?

Thank you for the swift reply. It seems that indeed the era is not being resolved properly. as:

console.log(
  "Era",
  new Intl.DateTimeFormat("en-US-u-ca-islamic-umalqura", { era: "short" })
    .formatToParts(new Date(2024, 4, 27))
    .find((part) => part.type === "era")?.value
);

Outputs "Era BC"

However the rest of the data seems to be working fine only the era seems problematic as:

console.log(
  "date",
  new Intl.DateTimeFormat(`en-US-u-ca-islamic-umalqura`, {
    era: "short",
  }).formatToParts(new Date(2024, 4, 27))
);

Prints

[
    {
        "type": "month",
        "value": "11"
    },
    {
        "type": "literal",
        "value": "/"
    },
    {
        "type": "day",
        "value": "19"
    },
    {
        "type": "literal",
        "value": "/"
    },
    {
        "type": "year",
        "value": "1445"
    },
    {
        "type": "literal",
        "value": " "
    },
    {
        "type": "era",
        "value": "BC"
    }
]

I would be happy to file a bug wherever it should be if I am directed.

Also worth noting that on the same Android phone Firefox for Android works fine. so the non-Gregorian data is being compiled properly and it seems that it's a bug specifically on Chrome for android.

Looks like this bug was already reported here: https://issues.chromium.org/issues/40856332

You'll want to watch that issue for status.

If you want to try making a PR to work around this issue in Temporal polyfills, we'd be happy to review it. Please file the PR in the proposal-temporal repo and the commit will eventually percolate down here to this repo.

The fix you'll probably want to try is to override the reviseIntlEra method in helperIslamic. Take a look at the implementation of this method in helperGregory for inspiration.

Thank you for the guidance @justingrant I appreciate it. I will raise a PR today or tomorrow.

@justingrant FYI. I have raised a PR for this here as advised.

@justingrant will the patch be published to npm? if yes, then I would appreciate it if I could know when

it will eventually, the production polyfill in the other repo needs to get caught up with upstream and that may take a while.

There's another polyfill from @arshaw that's probably closer to upstream at this point. FYI Adam, you may want to pick up this fix too.

@khawarizmus, I just released v0.2.5 of temporal-polyfill (aka the "fullcalendar" polyfill) and it contains an attempt at a bugfix for your issue. Would you mind testing?

Hey @arshaw. Thank you for the fix and apologies for taking some time to reply. I have already managed to get thinsg working by using pnpm-patch-i. I have a lot of code (including published libraries) that rely on the @js-temporal/polyfill hence switching to your polyfill might not be straight forward for me.

However I went ahead and tested your polyfill (using v0.2.5).

The following code

const HDate = FullTemporal.Now.zonedDateTime("islamic-umalqura", timeZone);
console.log(HDate.day);

console.log(
  new FullIntl.DateTimeFormat(locale.value, {
    era: "short",
    calendar: Calendars.UMM_AL_QURA,
  }).format(HDate.toInstant())
);

console.log(
  new FullIntl.DateTimeFormat(locale.value, {
    dateStyle: "full",
    calendar: Calendars.UMM_AL_QURA,
  }).format(HDate.toInstant())
);

outputs:

26
11/26/1445 BC, 10:18:22 AM
Monday, November 26, 1445 BC

The numbers are correct. the line console.log(HDate.day) doesn't throw an error. However the era is still wrong BC instead of AH. Note that the Months names i.e (November instead of Dull-Qidah) are wrong for both your polyfill and the patched version of @js-temporal/polyfill and it's something that should be fixed at Chrome level i suppose, unless you guys know of a way to fix it. currently i am just hard coding the months in an array and reaching to the right index when i want to display them.

Thanks for checking @khawarizmus. Glad my fix works for fixing the numbers, but sad the fix doesn't apply to Intl.DateTimeFormat. More extensive monkeypatching/polyfilling would need to happen on Intl.DateTimeFormat to get this to work as you guessed.