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:
# TODO:
# Filling
-# Rounding
+# Rounding increment in pattern
# Scientific notation
# Significant Digits
def parse_pattern(pattern):
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):
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),
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
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__':