Ticket #14317: ticket14317.2.diff
File ticket14317.2.diff, 5.4 KB (added by , 3 years ago) 


django/utils/numberformat.py
diff git a/django/utils/numberformat.py b/django/utils/numberformat.py index 6a31237..7939d8d 100644
a b from django.utils.safestring import mark_safe 3 3 from django.utils import six 4 4 5 5 6 def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='', 7 force_grouping=False): 6 def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='', force_grouping=False): 8 7 """ 9 8 Gets a number (as a number or string), and returns it as a string, 10 9 using formats defined as arguments: … … def format(number, decimal_sep, decimal_pos=None, grouping=0, thousand_sep='', 17 16 use_grouping = settings.USE_L10N and settings.USE_THOUSAND_SEPARATOR 18 17 use_grouping = use_grouping or force_grouping 19 18 use_grouping = use_grouping and grouping > 0 19 use_grouping = use_grouping and thousand_sep 20 20 21 # Make the common case fast 21 22 if isinstance(number, int) and not use_grouping and not decimal_pos: 22 23 return mark_safe(six.text_type(number)) 23 # sign 24 sign = ''24 25 float_number = float(number) 25 26 str_number = six.text_type(number) 26 if str_number[0] == '': 27 28 if decimal_pos is not None: 29 # Use the %f format string. This gives us rounding and the 30 # right number of decimal positions automatically. This also 31 # removes any 'e' if the number is really small or really large 32 str_number = six.text_type(('%.' + str(decimal_pos) + 'f') % float_number) 33 34 if not use_grouping: 35 return str_number.replace('.', decimal_sep) 36 37 # For grouping, we need to separate the sign, int_part and decimal part 38 if float_number < 0: 27 39 sign = '' 28 40 str_number = str_number[1:] 29 # decimal part 30 if '.' in str_number: 41 else: 42 sign = '' 43 44 if decimal_pos is not None or '.' in str_number: 31 45 int_part, dec_part = str_number.split('.') 32 if decimal_pos is not None: 33 dec_part = dec_part[:decimal_pos] 46 dec_part = decimal_sep + dec_part 34 47 else: 35 48 int_part, dec_part = str_number, '' 36 if decimal_pos is not None: 37 dec_part = dec_part + ('0' * (decimal_pos  len(dec_part))) 38 if dec_part: 39 dec_part = decimal_sep + dec_part 40 # grouping 41 if use_grouping: 42 int_part_gd = '' 43 for cnt, digit in enumerate(int_part[::1]): 44 if cnt and not cnt % grouping: 45 int_part_gd += thousand_sep 46 int_part_gd += digit 47 int_part = int_part_gd[::1] 48 return sign + int_part + dec_part 49 50 first_part_len = len(int_part) % grouping 51 full_parts = int_part[first_part_len:] 52 groups = [full_parts[i:i + grouping] for i in range(0, len(full_parts), grouping)] 53 54 if first_part_len > 0: 55 groups.insert(0, int_part[0:first_part_len]) 56 57 return sign + thousand_sep.join(groups) + dec_part 
tests/i18n/tests.py
diff git a/tests/i18n/tests.py b/tests/i18n/tests.py index 1022c8d..1368dbe 100644
a b class FormattingTests(TestCase): 357 357 Localization of numbers 358 358 """ 359 359 with self.settings(USE_THOUSAND_SEPARATOR=False): 360 self.assertEqual('66666.66', nformat(self.n, decimal_sep='.', decimal_pos=2, grouping=3, thousand_sep=',')) 361 self.assertEqual('66666A6', nformat(self.n, decimal_sep='A', decimal_pos=1, grouping=1, thousand_sep='B')) 362 self.assertEqual('66666', nformat(self.n, decimal_sep='X', decimal_pos=0, grouping=1, thousand_sep='Y')) 360 self.assertEqual('66666.67', nformat(self.n, decimal_sep='.', decimal_pos=2, grouping=3, thousand_sep=',')) 361 self.assertEqual('66666A7', nformat(self.n, decimal_sep='A', decimal_pos=1, grouping=1, thousand_sep='B')) 362 self.assertEqual('66667', nformat(self.n, decimal_sep='X', decimal_pos=0, grouping=1, thousand_sep='Y')) 363 364 # ticket #14317 365 self.assertEqual(u'0,00', nformat(0.000000001, decimal_sep=',', decimal_pos=2)) 366 self.assertEqual(u'0,00', nformat(0.00000000000099, decimal_sep=',', decimal_pos=2)) 367 self.assertEqual(u'0,00', nformat(decimal.Decimal(1e37), decimal_sep=',', decimal_pos=2)) 368 self.assertEqual(u'0,67', nformat(0.666, decimal_sep=',', decimal_pos=2)) 369 self.assertEqual(u'0,67', nformat('0.666', decimal_sep=',', decimal_pos=2)) 363 370 364 371 with self.settings(USE_THOUSAND_SEPARATOR=True): 365 self.assertEqual('66,666.66', nformat(self.n, decimal_sep='.', decimal_pos=2, grouping=3, thousand_sep=',')) 366 self.assertEqual('6B6B6B6B6A6', nformat(self.n, decimal_sep='A', decimal_pos=1, grouping=1, thousand_sep='B')) 367 self.assertEqual('66666.6', nformat(66666.666, decimal_sep='.', decimal_pos=1)) 372 self.assertEqual('66,666.67', nformat(self.n, decimal_sep='.', decimal_pos=2, grouping=3, thousand_sep=',')) 373 self.assertEqual('6B6B6B6B6A7', nformat(self.n, decimal_sep='A', decimal_pos=1, grouping=1, thousand_sep='B')) 374 self.assertEqual('66666.7', nformat(66666.666, decimal_sep='.', decimal_pos=1)) 375 368 376 self.assertEqual('66666.0', nformat(int('66666'), decimal_sep='.', decimal_pos=1)) 369 377 self.assertEqual('10000.0', nformat(self.l, decimal_sep='.', decimal_pos=1)) 370 378 # This unusual grouping/force_grouping combination may be triggered by the intcomma filter (#17414)