From 201ed50bc0d8a7baf332eb0596d3c2ac944b7b43 Mon Sep 17 00:00:00 2001 From: Isaac Jurado Date: Mon, 17 Nov 2014 18:24:47 +0100 Subject: [PATCH] numbers: Use currency decimal digits by default 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 | 30 ++++++++++++++++++++++++++++-- tests/test_numbers.py | 11 +++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/babel/numbers.py b/babel/numbers.py index 2117ce93..19a376be 100644 --- a/babel/numbers.py +++ b/babel/numbers.py @@ -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): diff --git a/tests/test_numbers.py b/tests/test_numbers.py index 6fe67c04..741b7537 100644 --- a/tests/test_numbers.py +++ b/tests/test_numbers.py @@ -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%' -- 2.47.3