Skip to content

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

@safaiyeh

Description

@safaiyeh

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.
  • 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:

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):

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:

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

Hermes version output:

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:

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

Node/V8 on the same machine returns:

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:

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:

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions