* fix formatting of fraction in format_decimal() if the input value is a float
with more than 7 significant digits (#183)
* fix format_date() with datetime parameter (#282, patch from Xavier Morel)
+ * fix format_decimal() with small Decimal values (#214, patch from George Lund)
Version 0.9.6
def split_number(value):
"""Convert a number into a (intasstring, fractionasstring) tuple"""
if isinstance(value, Decimal):
- text = str(value)
- else:
- text = ('%.9f' % value).rstrip('0')
+ # NB can't just do text = str(value) as str repr of Decimal may be
+ # in scientific notation, e.g. for small numbers.
+
+ sign, digits, exp = value.as_tuple()
+ # build list of digits in reverse order, then reverse+join
+ # as per http://docs.python.org/library/decimal.html#recipes
+ int_part = []
+ frac_part = []
+
+ digits = map(str, digits)
+
+ # get figures after decimal point
+ for i in range(-exp):
+ # add digit if available, else 0
+ frac_part.append(digits.pop() if digits else '0')
+
+ # add in some zeroes...
+ for i in range(exp):
+ int_part.append('0')
+
+ # and the rest
+ while digits:
+ int_part.append(digits.pop())
+
+ # if < 1, int_part must be set to '0'
+ if len(int_part) == 0:
+ int_part = '0',
+
+ if sign:
+ int_part.append('-')
+
+ return ''.join(reversed(int_part)), ''.join(reversed(frac_part))
+ text = ('%.9f' % value).rstrip('0')
if '.' in text:
a, b = text.split('.', 1)
if b == '0':
# 0 (see ticket #99)
fmt = numbers.format_scientific(0, '#E0', locale='en_US')
self.assertEqual(fmt, '0E0')
+
+ def test_formatting_of_very_small_decimals(self):
+ # previously formatting very small decimals could lead to a type error
+ # because the Decimal->string conversion was too simple (see #214)
+ number = Decimal("7E-7")
+ fmt = numbers.format_decimal(number, format="@@@", locale='en_US')
+ self.assertEqual('0.000000700', fmt)
class BankersRoundTestCase(unittest.TestCase):