|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65572 NumberFormatter->formatCurrency() ignores FRACTION_DIGITS
Submitted: 2013-08-28 13:55 UTC Modified: 2021-01-12 15:38 UTC
Avg. Score:4.1 ± 1.0
Reproduced:9 of 10 (90.0%)
Same Version:5 (55.6%)
Same OS:4 (44.4%)
From: matt at claritum dot com Assigned: stas (profile)
Status: Closed Package: intl (PECL)
PHP Version: Irrelevant OS: RHEL6
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Bug Type:
From: matt at claritum dot com
New email:
PHP Version: OS:


 [2013-08-28 13:55 UTC] matt at claritum dot com

You can only format a currency to a set number of decimal places if the currency 
is used for the given locale - see test script and Bug #63140[1]

Now I know this is probably an issue with upstream - it seems setting the currency 
resets the number of decimal places, and we don't have any way of resetting it 

But this makes displaying unit prices a real pain. Would it be possible to expose 
the setCurrency() method[2]? I don't know for sure, but I have a feeling setting 
the currency then setting FRACTION_DIGITS would work around the problem.

Thanks for your time

[2] http://icu-

Test script:
$f = new NumberFormatter('en_GB', NumberFormatter::CURRENCY);
$f->setAttribute($f::FRACTION_DIGITS, 4);
echo "pounds: " . $f->formatCurrency('123.45', 'GBP')
echo "euros: " . $f->formatCurrency('123.45', 'EUR');
echo "digits: " . $f->getAttribute($f::FRACTION_DIGITS);

Expected result:
pounds: £123.4500
euros: €123.4500
digits: 4

Actual result:
pounds: £123.4500
euros: €123.45
digits: 2


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2014-07-06 23:32 UTC] php at deep-freeze dot ca
This is really unnatural to work with.

In order to get the desired effect one has to:

$f = new NumberFormatter("en-GB", NumberFormatter::CURRENCY);
// Calling setTextAttribute/CURRENCY_CODE resets fraction digits
$f->setTextAttribute($f::CURRENCY_CODE, "GBP");
$f->setAttribute($f::FRACTION_DIGITS, 4);
echo "POUNDS: ", $f->format(123.45), PHP_EOL;
$f->setTextAttribute($f::CURRENCY_CODE, "EUR");
echo "EUROS: ", $f->format(123.45), PHP_EOL;

Expected Output:
POUNDS: £123.4500
EUROS: €123.4500

Actual Output:
POUNDS: £123.4500
EUROS: €123.45
 [2014-07-07 06:34 UTC]
-Assigned To: +Assigned To: stas
 [2014-07-07 07:01 UTC]
-Status: Assigned +Status: Analyzed
 [2014-07-07 07:01 UTC]
Looks like this is an upstream bug, filed:
 [2014-12-12 03:18 UTC]
-Status: Analyzed +Status: Feedback
 [2014-12-12 03:18 UTC]
Looks like ICU fixed it in v53, please see if it still happens.
 [2014-12-12 17:51 UTC] matt at claritum dot com
-Status: Feedback +Status: Assigned
 [2014-12-12 17:51 UTC] matt at claritum dot com

Thanks for that. Unfortunately it still doesn't do what I want.

From $ php -i:


Internationalization support => enabled
version => PECL-3.0.0
ICU version => 53.1
ICU Data version => 53.1

Directive => Local Value => Master Value
intl.default_locale => no value => no value
intl.error_level => 0 => 0
intl.use_exceptions => 0 => 0

php > $f = new NumberFormatter('en_GB', NumberFormatter::CURRENCY);
php > $f->setAttribute($f::FRACTION_DIGITS, 4);
php > echo "pounds: " . $f->formatCurrency('123.45', 'GBP');
pounds: £123.4500
php > echo "euros: " . $f->formatCurrency('123.45', 'EUR');
euros: €123.45
php > echo "digits: " . $f->getAttribute($f::FRACTION_DIGITS);
digits: 4
php > echo "pounds: " . $f->formatCurrency('123.45', 'GBP');
pounds: £123.4500

So it's remembering the digits and formatting GBP correctly the second time, but still not using them for EUR!

I'll try with ICU 54 which is out now and let you know if that's any better.
 [2014-12-12 18:09 UTC] matt at claritum dot com
Yeah, still broken with ICU 54.1 :(
 [2014-12-12 18:33 UTC] matt at claritum dot com
And actually the test script attached to produces exactly the same result:

$ ./ucurr
Digits: 4
GBP: £123.4500
Digits: 4
EUR: €123.45
Digits: 4
 [2015-06-24 17:35 UTC]
Currently, the ICU ticket[1] is tagged as "accepted defect" and
the milestone is 56.0.1, so we have to be patient.

[1] <>
 [2020-11-05 01:06 UTC] corey dot taylor dot fl at gmail dot com
This was fixed in ICU 60.x and was waiting on a completed icu4c (c++ api) unit tests.

I provided one and it appears to pass.
 [2020-11-06 17:00 UTC] corey dot taylor dot fl at gmail dot com
The ICU issue is now closed as resolved with the icu4c tests passing.

According to the maintainer, ICU 61 is the version the fix was officially released in. It's difficult to demonstrate because 3v4l is using ICU 57 at this time.
 [2020-11-07 15:17 UTC] matt at claritum dot com
I can confirm this is fixed when using ICU 65.1 (from remi's php73 repo):

# php -i | grep ICU
ICU version => 65.1
ICU Data version => 65.1
ICU TZData version => 2019c
ICU Unicode version => 12.1

# php -a
Interactive shell

php > $f = new NumberFormatter('en_GB', NumberFormatter::CURRENCY);
php > $f->setAttribute($f::FRACTION_DIGITS, 4);
php > echo "pounds: " . $f->formatCurrency('123.45', 'GBP') . "\n";
pounds: £123.4500
php > echo "euros: " . $f->formatCurrency('123.45', 'EUR') . "\n";
euros: €123.4500
php > echo "digits: " . $f->getAttribute($f::FRACTION_DIGITS) . "\n";
digits: 4

It took a while, but good to see at last :)
 [2021-01-12 15:38 UTC]
-Status: Assigned +Status: Closed
 [2021-01-12 15:38 UTC]
Indeed, that has been fixed. :)
PHP Copyright © 2001-2023 The PHP Group
All rights reserved.
Last updated: Sun Oct 01 12:01:23 2023 UTC