facebook / facebook/hermes

Intl.NumberFormat unit style formats day/hour/minute as seconds on Hermes

Open
#2,011 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
11.3k
Forks
859
Avg merge
1h 30m
Merged PRs (30d)
3

Description

## Bug Description

`Intl.NumberFormat` with `style: 'unit'` returns the wrong unit for duration-style units in Hermes. In particular, `hour` and `minute` are formatted as seconds, and `day` is formatted with the singular unit in `en-US` even for plural values.

This caused a React Native app countdown that should render as `23 days 22 hr` to render as `23 day 79,200s` on Hermes.

I searched existing `Intl.NumberFormat` issues and found related NumberFormat correctness issues such as #1035 and #1318, but I did not find an exact duplicate for `style: 'unit'` with `day` / `hour` / `minute`.

- [ ] I have run `gradle clean` and confirmed this bug does not occur with JSC. N/A for this report: the repro below is iOS/macOS Hermes CLI. I did compare against JavaScriptCore on macOS and V8/Node; both return the expected unit strings.
- [x] The issue is reproducible with the latest version of React Native. I reproduced it with the Hermes `0.16.0` iOS prebuilt tarball referenced by `react-native@0.85.3` when Hermes V1 is disabled. The same issue also reproduces in my app on React Native `0.83.4` / Hermes `0.14.1`.

Hermes git revision (if applicable): `hermes-v0.16.0` release tarball; also observed with `hermes-v0.14.1`
React Native version: `0.85.3` for the latest-version check; originally observed in `0.83.4`
OS: macOS 26.4.1 (`arm64`), iOS React Native app runtime
Platform (most likely one of arm64-v8a, armeabi-v7a, x86, x86_64): `arm64` / iOS + macOS Hermes CLI from the iOS prebuilt tarball

## Steps To Reproduce

1. Install or download Hermes `0.16.0` from the React Native `0.85.3` Hermes iOS prebuilt artifact.
2. Run the code below with the Hermes CLI from that artifact.
3. Compare the output with JavaScriptCore or Node/V8.

Commands used for the latest React Native / Hermes check:

```sh
mkdir -p /tmp/hermes-rn-latest-check
cd /tmp/hermes-rn-latest-check
bun init -y
bun add react-native@0.85.3

curl -L \
https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/0.16.0/hermes-ios-0.16.0-hermes-ios-debug.tar.gz \
-o hermes-ios-debug.tar.gz
mkdir hermes-016
tar -xzf hermes-ios-debug.tar.gz -C hermes-016

./hermes-016/destroot/bin/hermes repro.js
```

Code example (`repro.js`):

```js
const log = typeof print === 'function' ? print : console.log;

function show(unit, value) {
const formatted = new Intl.NumberFormat('en-US', {
style: 'unit',
unit,
unitDisplay: 'short',
maximumFractionDigits: 1,
}).format(value);

log(`${unit}: ${formatted}`);
}

show('day', 2);
show('hour', 2);
show('minute', 2);
show('second', 2);
```

Hermes `0.16.0` output:

```text
day: 2 day
hour: 7,200s
minute: 120s
second: 2s
```

Hermes version output:

```text
Hermes JavaScript compiler and Virtual Machine.
Hermes release version: 0.16.0
HBC bytecode version: 96
```

JavaScriptCore on the same machine, using `osascript -l JavaScript`, returns:

```text
day: 2 days
hour: 2 hr
minute: 2 min
second: 2 sec
```

Node/V8 on the same machine returns:

```text
day: 2 days
hour: 2 hr
minute: 2 min
second: 2 sec
```

The same Hermes behavior also reproduces with my app's installed Hermes `0.14.1` from React Native `0.83.4`:

```text
Hermes release version: 0.14.1
HBC bytecode version: 96

day: 2 day
hour: 7,200s
minute: 120s
second: 2s
```

## The Expected Behavior

`Intl.NumberFormat` should preserve the requested unit when `style: 'unit'` is used.

Expected `en-US` short-unit output for the example above:

```text
day: 2 days
hour: 2 hr
minute: 2 min
second: 2 sec
```

At minimum, `unit: 'hour'` should not format the value as seconds (`2 hr` should not become `7,200s`), and `unit: 'minute'` should not become seconds (`2 min` should not become `120s`).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.