Skip to content

Commit

Permalink
Support the option to format a number with no rounding. Useful for De…
Browse files Browse the repository at this point in the history
…cimals
  • Loading branch information
cyrusv authored and strichter committed Jan 5, 2017
1 parent 5add871 commit a21ad14
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGES.rst
Expand Up @@ -13,6 +13,10 @@ CHANGES
special treatment, because standard str(x) collapses them to scientific
representation.

- Support for specifying rounding in NumberFormatter. This is required in some
cases, e.g. when you format a Decimal('0.9999') that sould not be rounded.
Currently, formatting Decimal('0.99999') will raise a TypeError if rounding
is not set to False

4.1.0 (2015-11-06)
------------------
Expand Down
16 changes: 10 additions & 6 deletions src/zope/i18n/format.py
Expand Up @@ -327,8 +327,11 @@ def _format_integer(self, integer, pattern):
integer = self.symbols['nativeZeroDigit']*(min_size-size) + integer
return integer

def _format_fraction(self, fraction, pattern):
max_precision = len(pattern)
def _format_fraction(self, fraction, pattern, rounding=True):
if rounding:
max_precision = len(pattern)
else:
max_precision = sys.maxint
min_precision = pattern.count('0')
precision = len(fraction)
roundInt = False
Expand Down Expand Up @@ -356,7 +359,7 @@ def _format_fraction(self, fraction, pattern):
fraction = self.symbols['decimal'] + fraction
return fraction, roundInt

def format(self, obj, pattern=None):
def format(self, obj, pattern=None, rounding=True):
"See zope.i18n.interfaces.IFormat"
# Make or get binary form of datetime pattern
if pattern is not None:
Expand Down Expand Up @@ -410,7 +413,8 @@ def format(self, obj, pattern=None):
number = ''.join(obj_int_frac)

fraction, roundInt = self._format_fraction(number[1:],
bin_pattern[FRACTION])
bin_pattern[FRACTION],
rounding=rounding)
if roundInt:
number = str(int(number[0]) + 1) + fraction
else:
Expand All @@ -426,8 +430,8 @@ def format(self, obj, pattern=None):

else:
if len(obj_int_frac) > 1:
fraction, roundInt = self._format_fraction(obj_int_frac[1],
bin_pattern[FRACTION])
fraction, roundInt = self._format_fraction(
obj_int_frac[1], bin_pattern[FRACTION], rounding=rounding)
else:
fraction = ''
roundInt = False
Expand Down
5 changes: 5 additions & 0 deletions src/zope/i18n/tests/test_formats.py
Expand Up @@ -1181,6 +1181,11 @@ def testFormatSmallNumbers(self):
-1e-7, '(#0.00#####);(-#0.00#####)'), '(-0.0000001)')
self.assertEqual(self.format.format(1e-9, '(#0.00###)'), '(0.00)')

def testNoRounding(self):
# Witout Rounding
self.assertEqual(self.format.format(
decimal.Decimal('0.99999'), '0.###', rounding=False), '0.99999')


def test_suite():
return TestSuite((
Expand Down

0 comments on commit a21ad14

Please sign in to comment.