]> git.ipfire.org Git - thirdparty/babel.git/commitdiff
numbers: Use currency decimal digits by default
authorIsaac Jurado <diptongo@gmail.com>
Mon, 17 Nov 2014 17:24:47 +0000 (18:24 +0100)
committerIsaac Jurado <diptongo@gmail.com>
Sun, 27 Sep 2015 12:47:32 +0000 (14:47 +0200)
When formatting a price, the number of decimals to use should be defined
by the currency.  For example, JPY do not use decimal numbers at all.

However, we still allow the user to override the currency decimal digits
setting with the one from the number format.

Fixes https://github.com/mitsuhiko/babel/issues/139

babel/numbers.py
tests/test_numbers.py

index 2117ce93847d732002f9de632c3da66f65dcde10..19a376bea6d12d0935386e0930130767e5a57eb2 100644 (file)
@@ -256,7 +256,7 @@ def format_decimal(number, format=None, locale=LC_NUMERIC):
     return pattern.apply(number, locale)
 
 
-def format_currency(number, currency, format=None, locale=LC_NUMERIC):
+def format_currency(number, currency, format=None, locale=LC_NUMERIC, currency_digits=True):
     u"""Return formatted currency value.
 
     >>> format_currency(1099.98, 'USD', locale='en_US')
@@ -276,15 +276,41 @@ def format_currency(number, currency, format=None, locale=LC_NUMERIC):
     >>> format_currency(1099.98, 'EUR', u'#,##0.00 \xa4\xa4\xa4', locale='en_US')
     u'1,099.98 euros'
 
+    Currencies usually have a specific number of decimal digits. This function
+    favours that information over the given format:
+
+    >>> format_currency(1099.98, 'JPY', locale='en_US')
+    u'\\xa51,100'
+    >>> format_currency(1099.98, 'COP', u'#,##0.00', locale='es_ES')
+    u'1.100'
+
+    However, the number of decimal digits can be overriden from the currency
+    information, by setting the last parameter to ``True``:
+
+    >>> format_currency(1099.98, 'JPY', locale='en_US', currency_digits=False)
+    u'\\xa51,099.98'
+    >>> format_currency(1099.98, 'COP', u'#,##0.00', locale='es_ES', currency_digits=False)
+    u'1.099,98'
+
     :param number: the number to format
     :param currency: the currency code
     :param locale: the `Locale` object or locale identifier
+    :param currency_digits: use the currency's number of decimal digits
     """
     locale = Locale.parse(locale)
     if not format:
         format = locale.currency_formats.get(format)
     pattern = parse_pattern(format)
-    return pattern.apply(number, locale, currency=currency)
+    if currency_digits:
+        fractions = get_global('currency_fractions')
+        try:
+            digits = fractions[currency][0]
+        except KeyError:
+            digits = fractions['DEFAULT'][0]
+        frac = (digits, digits)
+    else:
+        frac = None
+    return pattern.apply(number, locale, currency=currency, force_frac=frac)
 
 
 def format_percent(number, format=None, locale=LC_NUMERIC):
index 6fe67c04ee6c46f93799094f9a34c6c8aa6537df..741b75378f4ec41135b73c733ab5be913bc1910d 100644 (file)
@@ -252,6 +252,17 @@ def test_format_currency():
     assert (numbers.format_currency(1099.98, 'EUR', locale='nl_NL')
             != numbers.format_currency(-1099.98, 'EUR', locale='nl_NL'))
 
+    assert (numbers.format_currency(1099.98, 'JPY', locale='en_US')
+            == u'\xa51,100')
+    assert (numbers.format_currency(1099.98, 'COP', u'#,##0.00', locale='es_ES')
+            == u'1.100')
+    assert (numbers.format_currency(1099.98, 'JPY', locale='en_US',
+                                    currency_digits=False)
+            == u'\xa51,099.98')
+    assert (numbers.format_currency(1099.98, 'COP', u'#,##0.00', locale='es_ES',
+                                    currency_digits=False)
+            == u'1.099,98')
+
 
 def test_format_percent():
     assert numbers.format_percent(0.34, locale='en_US') == u'34%'