Skip to content

Use NumberFormatter instead of legacy NumberFormat #17006

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

Open
rickmacgillis opened this issue Nov 30, 2024 · 4 comments
Open

Use NumberFormatter instead of legacy NumberFormat #17006

rickmacgillis opened this issue Nov 30, 2024 · 4 comments

Comments

@rickmacgillis
Copy link

Description

The following code:

<?PHP
function nth(int $number) : ?string {
		$formatter = new \NumberFormatter('en_US', \NumberFormatter::ORDINAL);
		$formatted = $formatter->format($number);
		return $formatted === false ? null : $formatted;
}

echo nth(651959195189);
?>

Resulted in this output:

651,959,195,189rd

But I expected this output instead:

651,959,195,189th

PHP Version

PHP 8.3.6

Operating System

Linux Mint 22

@damianwadley
Copy link
Member

Pretty confident this is a bug in ICU, but I'll let someone else make that call.

What seems to be happening behind the scenes is that ICU is taking the 64-bit integer given to it by PHP and converting it into a 32-bit integer (I assume accidentally) getting -875833803 as a result, looking up the ordinal formatting rules (which are essentially switch (number % 10) { ... }), and formatting the original 64-bit number using the rule for ...3 (which is of course {number}rd).

Good news is that there's a workaround: if you force the number to a float, that means it will get passed to ICU's unum_formatDouble which appears to work correctly.
https://3v4l.org/C0WgV

@rickmacgillis
Copy link
Author

Confirmed. Type hinting float instead of int fixed the issue.

@cmb69
Copy link
Member

cmb69 commented Dec 1, 2024

Indeed, looks like an upstream issue:

https://github.com/unicode-org/icu/blob/e025466e3ac94bcf4a8062b98b68f4c6b7e00990/icu4c/source/i18n/nfrule.cpp#L775-L776

But we should also read https://unicode-org.github.io/icu/userguide/format_parse/numbers/legacy-numberformat.html:

⚠️ Since ICU 60, the recommended way to format numbers is NumberFormatter; see index.md.

This page is here for reference for the older NumberFormat hierarchy in ICU4C and ICU4J.

@cmb69
Copy link
Member

cmb69 commented Dec 4, 2024

Okay, no further feedback and apparently an upstream issue, so I'm repurposing this ticket.

@cmb69 cmb69 changed the title 651,959,195,189rd on NumberFormatter::ORDINAL Use NumberFormatter instead of legacy NumberFormat Dec 4, 2024
@cmb69 cmb69 added Feature and removed Bug labels Dec 4, 2024
@devnexen devnexen self-assigned this Dec 6, 2024
devnexen added a commit to devnexen/php-src that referenced this issue Dec 6, 2024
…sting.

Those APIs are not particularly 1:1, here using NumberFormatter for
NumberFormatter::format/numft_format at the moment, trying to assess
what's possible for next.
devnexen added a commit to devnexen/php-src that referenced this issue Dec 6, 2024
…sting.

Those APIs are not particularly 1:1, here using NumberFormatter for
NumberFormatter::format/numft_format at the moment, trying to assess
what's possible for next.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants