php.net |  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
Votes:12
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
 [2013-08-28 13:55 UTC] matt at claritum dot com
Description:
------------
Hi,

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

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

[1] https://bugs.php.net/bug.php?id=63140&edit=2
[2] http://icu-
project.org/apiref/icu4c/classicu_1_1NumberFormat.html#a9f1c46495913e2edff15e8c94e
018697

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

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

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] stas@php.net
-Assigned To: +Assigned To: stas
 [2014-07-07 07:01 UTC] stas@php.net
-Status: Assigned +Status: Analyzed
 [2014-07-07 07:01 UTC] stas@php.net
Looks like this is an upstream bug, filed: http://bugs.icu-project.org/trac/ticket/10997
 [2014-12-12 03:18 UTC] stas@php.net
-Status: Analyzed +Status: Feedback
 [2014-12-12 03:18 UTC] stas@php.net
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
Hi,

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

From $ php -i:

intl

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 http://bugs.icu-project.org/trac/ticket/10997 produces exactly the same result:

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

[1] <http://bugs.icu-project.org/trac/ticket/10997>
 [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.

https://github.com/unicode-org/icu/pull/1444
 [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] cmb@php.net
-Status: Assigned +Status: Closed
 [2021-01-12 15:38 UTC] cmb@php.net
Indeed, that has been fixed. :)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 08:01:29 2024 UTC