# HG changeset patch # User jonas # Date 1181253643 0 # Node ID fa8a27b80eb4a8a3fc391cfd11da6b2bb1a995b0 # Parent daf35e2ad044a9541cbd239fef70e977c56f78d6 Added round-half-even (banker's rounding) support. Moved a couple of unit-tests from docstrings to a separate file. diff --git a/babel/numbers.py b/babel/numbers.py --- a/babel/numbers.py +++ b/babel/numbers.py @@ -74,18 +74,16 @@ def format_decimal(number, format=None, locale=LC_NUMERIC): """Returns the given decimal number formatted for a specific locale. - >>> format_decimal(1, locale='en_US') - u'1' >>> format_decimal(1.2345, locale='en_US') u'1.234' + >>> format_decimal(1.2346, locale='en_US') + u'1.235' + >>> format_decimal(-1.2346, locale='en_US') + u'-1.235' >>> format_decimal(1.2345, locale='sv_SE') u'1,234' - >>> format_decimal(12345, locale='de_DE') + >>> format_decimal(12345, locale='de') u'12.345' - >>> format_decimal(-1.2345, format='#,##0.##;-#', locale='sv_SE') - u'-1,23' - >>> format_decimal(-1.2345, format='#,##0.##;(#)', locale='sv_SE') - u'(1,23)' The appropriate thousands grouping and the decimal separator are used for each locale: @@ -218,7 +216,7 @@ # TODO: # Filling -# Rounding +# Rounding increment in pattern # Scientific notation # Significant Digits def parse_pattern(pattern): @@ -295,6 +293,7 @@ self.grouping = grouping self.int_precision = int_precision self.frac_precision = frac_precision + self.format = '%%.%df' % self.frac_precision[1] if '%' in ''.join(self.prefix + self.suffix): self.scale = 100.0 elif u'‰' in ''.join(self.prefix + self.suffix): @@ -308,7 +307,11 @@ def apply(self, value, locale): value *= self.scale negative = int(value < 0) - a, b = str(value).split('.') + a = self.format % value + if self.frac_precision[1] > 0: + a, b = a.split('.') + else: + b = '' a = a.lstrip('-') return '%s%s%s%s' % (self.prefix[negative], self._format_int(a, locale), @@ -334,8 +337,6 @@ if max == 0 or (min == 0 and int(value) == 0): return '' width = len(value) - if width < min: - value += '0' * (min - width) - if width > max: - value = value[:max] # FIXME: Rounding?!? + while len(value) > min and value[-1] == '0': + value = value[:-1] return get_decimal_symbol(locale) + value diff --git a/babel/tests/numbers.py b/babel/tests/numbers.py --- a/babel/tests/numbers.py +++ b/babel/tests/numbers.py @@ -16,9 +16,31 @@ from babel import numbers + +class FormatDecimalTestCase(unittest.TestCase): + + def test_subpatterns(self): + self.assertEqual(numbers.format_decimal(-12345, '#,##0.##;-#', + locale='en_US'), '-12,345') + self.assertEqual(numbers.format_decimal(-12345, '#,##0.##;(#)', + locale='en_US'), '(12,345)') + + def test_default_rounding(self): + """Testing Round-Half-Even (Banker's rounding) + + A '5' is rounded to the closest 'even' number + """ + self.assertEqual(numbers.format_decimal(5.5, '0', locale='sv'), '6') + self.assertEqual(numbers.format_decimal(6.5, '0', locale='sv'), '6') + self.assertEqual(numbers.format_decimal(1.2325, locale='sv'), '1,232') + self.assertEqual(numbers.format_decimal(1.2325, locale='sv'), '1,232') + self.assertEqual(numbers.format_decimal(1.2335, locale='sv'), '1,234') + + def suite(): suite = unittest.TestSuite() suite.addTest(doctest.DocTestSuite(numbers)) + suite.addTest(unittest.makeSuite(FormatDecimalTestCase)) return suite if __name__ == '__main__':