Fixed #25920 -- Added support for non-uniform NUMBER_GROUPING.
This commit is contained in:
parent
46338296aa
commit
b5a1c3a6f5
|
@ -15,12 +15,15 @@ def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='',
|
|||
|
||||
* decimal_sep: Decimal separator symbol (for example ".")
|
||||
* decimal_pos: Number of decimal positions
|
||||
* grouping: Number of digits in every group limited by thousand separator
|
||||
* grouping: Number of digits in every group limited by thousand separator.
|
||||
For non-uniform digit grouping, it can be a sequence with the number
|
||||
of digit group sizes following the format used by the Python locale
|
||||
module in locale.localeconv() LC_NUMERIC grouping (e.g. (3, 2, 0)).
|
||||
* thousand_sep: Thousand separator symbol (for example ",")
|
||||
"""
|
||||
use_grouping = settings.USE_L10N and settings.USE_THOUSAND_SEPARATOR
|
||||
use_grouping = use_grouping or force_grouping
|
||||
use_grouping = use_grouping and grouping > 0
|
||||
use_grouping = use_grouping and grouping != 0
|
||||
# Make the common case fast
|
||||
if isinstance(number, int) and not use_grouping and not decimal_pos:
|
||||
return mark_safe(six.text_type(number))
|
||||
|
@ -46,10 +49,22 @@ def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='',
|
|||
dec_part = decimal_sep + dec_part
|
||||
# grouping
|
||||
if use_grouping:
|
||||
try:
|
||||
# if grouping is a sequence
|
||||
intervals = list(grouping)
|
||||
except TypeError:
|
||||
# grouping is a single value
|
||||
intervals = [grouping, 0]
|
||||
active_interval = intervals.pop(0)
|
||||
int_part_gd = ''
|
||||
for cnt, digit in enumerate(int_part[::-1]):
|
||||
if cnt and not cnt % grouping:
|
||||
cnt = 0
|
||||
for digit in int_part[::-1]:
|
||||
if cnt and cnt == active_interval:
|
||||
if intervals:
|
||||
active_interval = intervals.pop(0) or active_interval
|
||||
int_part_gd += thousand_sep[::-1]
|
||||
cnt = 0
|
||||
int_part_gd += digit
|
||||
cnt += 1
|
||||
int_part = int_part_gd[::-1]
|
||||
return sign + int_part + dec_part
|
||||
|
|
|
@ -1943,12 +1943,28 @@ no grouping will be applied to the number. If this setting is greater than
|
|||
``0``, then :setting:`THOUSAND_SEPARATOR` will be used as the separator between
|
||||
those groups.
|
||||
|
||||
Some locales use non-uniform digit grouping, e.g. ``10,00,00,000`` in
|
||||
``en_IN``. For this case, you can provide a sequence with the number of digit
|
||||
group sizes to be applied. The first number defines the size of the group
|
||||
preceding the decimal delimiter, and each number that follows defines the size
|
||||
of preceding groups. If the sequence is terminated with ``-1``, no further
|
||||
grouping is performed. If the sequence terminates with a ``0``, the last group
|
||||
size is used for the remainder of the number.
|
||||
|
||||
Example tuple for ``en_IN``::
|
||||
|
||||
NUMBER_GROUPING = (3, 2, 0)
|
||||
|
||||
Note that if :setting:`USE_L10N` is set to ``True``, then the locale-dictated
|
||||
format has higher precedence and will be applied instead.
|
||||
|
||||
See also :setting:`DECIMAL_SEPARATOR`, :setting:`THOUSAND_SEPARATOR` and
|
||||
:setting:`USE_THOUSAND_SEPARATOR`.
|
||||
|
||||
.. versionchanged:: 1.11
|
||||
|
||||
Support for non-uniform digit grouping was added.
|
||||
|
||||
.. setting:: PREPEND_WWW
|
||||
|
||||
``PREPEND_WWW``
|
||||
|
|
|
@ -166,7 +166,8 @@ Generic Views
|
|||
Internationalization
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* ...
|
||||
* Number formatting and the :setting:`NUMBER_GROUPING` setting support
|
||||
non-uniform digit grouping.
|
||||
|
||||
Management Commands
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -576,6 +576,18 @@ class FormattingTests(SimpleTestCase):
|
|||
self.assertEqual('-66666.6', nformat(-66666.666, decimal_sep='.', decimal_pos=1))
|
||||
self.assertEqual('-66666.0', nformat(int('-66666'), decimal_sep='.', decimal_pos=1))
|
||||
self.assertEqual('10000.0', nformat(self.l, decimal_sep='.', decimal_pos=1))
|
||||
self.assertEqual(
|
||||
'10,00,00,000.00',
|
||||
nformat(100000000.00, decimal_sep='.', decimal_pos=2, grouping=(3, 2, 0), thousand_sep=',')
|
||||
)
|
||||
self.assertEqual(
|
||||
'1,0,00,000,0000.00',
|
||||
nformat(10000000000.00, decimal_sep='.', decimal_pos=2, grouping=(4, 3, 2, 1, 0), thousand_sep=',')
|
||||
)
|
||||
self.assertEqual(
|
||||
'10000,00,000.00',
|
||||
nformat(1000000000.00, decimal_sep='.', decimal_pos=2, grouping=(3, 2, -1), thousand_sep=',')
|
||||
)
|
||||
# This unusual grouping/force_grouping combination may be triggered by the intcomma filter (#17414)
|
||||
self.assertEqual('10000', nformat(self.l, decimal_sep='.', decimal_pos=0, grouping=0, force_grouping=True))
|
||||
|
||||
|
|
Loading…
Reference in New Issue