test_numberformat.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. from decimal import Decimal
  2. from sys import float_info
  3. from django.test import SimpleTestCase
  4. from django.utils.numberformat import format as nformat
  5. class TestNumberFormat(SimpleTestCase):
  6. def test_format_number(self):
  7. self.assertEqual(nformat(1234, '.'), '1234')
  8. self.assertEqual(nformat(1234.2, '.'), '1234.2')
  9. self.assertEqual(nformat(1234, '.', decimal_pos=2), '1234.00')
  10. self.assertEqual(nformat(1234, '.', grouping=2, thousand_sep=','), '1234')
  11. self.assertEqual(nformat(1234, '.', grouping=2, thousand_sep=',', force_grouping=True), '12,34')
  12. self.assertEqual(nformat(-1234.33, '.', decimal_pos=1), '-1234.3')
  13. # The use_l10n parameter can force thousand grouping behavior.
  14. with self.settings(USE_THOUSAND_SEPARATOR=True):
  15. self.assertEqual(nformat(1234, '.', grouping=3, thousand_sep=',', use_l10n=False), '1234')
  16. self.assertEqual(nformat(1234, '.', grouping=3, thousand_sep=',', use_l10n=True), '1,234')
  17. def test_format_string(self):
  18. self.assertEqual(nformat('1234', '.'), '1234')
  19. self.assertEqual(nformat('1234.2', '.'), '1234.2')
  20. self.assertEqual(nformat('1234', '.', decimal_pos=2), '1234.00')
  21. self.assertEqual(nformat('1234', '.', grouping=2, thousand_sep=','), '1234')
  22. self.assertEqual(nformat('1234', '.', grouping=2, thousand_sep=',', force_grouping=True), '12,34')
  23. self.assertEqual(nformat('-1234.33', '.', decimal_pos=1), '-1234.3')
  24. self.assertEqual(nformat('10000', '.', grouping=3, thousand_sep='comma', force_grouping=True), '10comma000')
  25. def test_large_number(self):
  26. most_max = (
  27. '{}179769313486231570814527423731704356798070567525844996'
  28. '598917476803157260780028538760589558632766878171540458953'
  29. '514382464234321326889464182768467546703537516986049910576'
  30. '551282076245490090389328944075868508455133942304583236903'
  31. '222948165808559332123348274797826204144723168738177180919'
  32. '29988125040402618412485836{}'
  33. )
  34. most_max2 = (
  35. '{}35953862697246314162905484746340871359614113505168999'
  36. '31978349536063145215600570775211791172655337563430809179'
  37. '07028764928468642653778928365536935093407075033972099821'
  38. '15310256415249098018077865788815173701691026788460916647'
  39. '38064458963316171186642466965495956524082894463374763543'
  40. '61838599762500808052368249716736'
  41. )
  42. int_max = int(float_info.max)
  43. self.assertEqual(nformat(int_max, '.'), most_max.format('', '8'))
  44. self.assertEqual(nformat(int_max + 1, '.'), most_max.format('', '9'))
  45. self.assertEqual(nformat(int_max * 2, '.'), most_max2.format(''))
  46. self.assertEqual(nformat(0 - int_max, '.'), most_max.format('-', '8'))
  47. self.assertEqual(nformat(-1 - int_max, '.'), most_max.format('-', '9'))
  48. self.assertEqual(nformat(-2 * int_max, '.'), most_max2.format('-'))
  49. def test_float_numbers(self):
  50. tests = [
  51. (9e-10, 10, '0.0000000009'),
  52. (9e-19, 2, '0.00'),
  53. (.00000000000099, 0, '0'),
  54. (.00000000000099, 13, '0.0000000000009'),
  55. (1e16, None, '10000000000000000'),
  56. (1e16, 2, '10000000000000000.00'),
  57. # A float without a fractional part (3.) results in a ".0" when no
  58. # decimal_pos is given. Contrast that with the Decimal('3.') case
  59. # in test_decimal_numbers which doesn't return a fractional part.
  60. (3., None, '3.0'),
  61. ]
  62. for value, decimal_pos, expected_value in tests:
  63. with self.subTest(value=value, decimal_pos=decimal_pos):
  64. self.assertEqual(nformat(value, '.', decimal_pos), expected_value)
  65. # Thousand grouping behavior.
  66. self.assertEqual(
  67. nformat(1e16, '.', thousand_sep=',', grouping=3, force_grouping=True),
  68. '10,000,000,000,000,000',
  69. )
  70. self.assertEqual(
  71. nformat(1e16, '.', decimal_pos=2, thousand_sep=',', grouping=3, force_grouping=True),
  72. '10,000,000,000,000,000.00',
  73. )
  74. def test_decimal_numbers(self):
  75. self.assertEqual(nformat(Decimal('1234'), '.'), '1234')
  76. self.assertEqual(nformat(Decimal('1234.2'), '.'), '1234.2')
  77. self.assertEqual(nformat(Decimal('1234'), '.', decimal_pos=2), '1234.00')
  78. self.assertEqual(nformat(Decimal('1234'), '.', grouping=2, thousand_sep=','), '1234')
  79. self.assertEqual(nformat(Decimal('1234'), '.', grouping=2, thousand_sep=',', force_grouping=True), '12,34')
  80. self.assertEqual(nformat(Decimal('-1234.33'), '.', decimal_pos=1), '-1234.3')
  81. self.assertEqual(nformat(Decimal('0.00000001'), '.', decimal_pos=8), '0.00000001')
  82. self.assertEqual(nformat(Decimal('9e-19'), '.', decimal_pos=2), '0.00')
  83. self.assertEqual(nformat(Decimal('.00000000000099'), '.', decimal_pos=0), '0')
  84. self.assertEqual(
  85. nformat(Decimal('1e16'), '.', thousand_sep=',', grouping=3, force_grouping=True),
  86. '10,000,000,000,000,000'
  87. )
  88. self.assertEqual(
  89. nformat(Decimal('1e16'), '.', decimal_pos=2, thousand_sep=',', grouping=3, force_grouping=True),
  90. '10,000,000,000,000,000.00'
  91. )
  92. self.assertEqual(nformat(Decimal('3.'), '.'), '3')
  93. self.assertEqual(nformat(Decimal('3.0'), '.'), '3.0')
  94. # Very large & small numbers.
  95. tests = [
  96. ('9e9999', None, '9e+9999'),
  97. ('9e9999', 3, '9.000e+9999'),
  98. ('9e201', None, '9e+201'),
  99. ('9e200', None, '9e+200'),
  100. ('1.2345e999', 2, '1.23e+999'),
  101. ('9e-999', None, '9e-999'),
  102. ('1e-7', 8, '0.00000010'),
  103. ('1e-8', 8, '0.00000001'),
  104. ('1e-9', 8, '0.00000000'),
  105. ('1e-10', 8, '0.00000000'),
  106. ('1e-11', 8, '0.00000000'),
  107. ('1' + ('0' * 300), 3, '1.000e+300'),
  108. ('0.{}1234'.format('0' * 299), 3, '0.000'),
  109. ]
  110. for value, decimal_pos, expected_value in tests:
  111. with self.subTest(value=value):
  112. self.assertEqual(nformat(Decimal(value), '.', decimal_pos), expected_value)
  113. def test_decimal_subclass(self):
  114. class EuroDecimal(Decimal):
  115. """
  116. Wrapper for Decimal which prefixes each amount with the € symbol.
  117. """
  118. def __format__(self, specifier, **kwargs):
  119. amount = super().__format__(specifier, **kwargs)
  120. return '€ {}'.format(amount)
  121. price = EuroDecimal('1.23')
  122. self.assertEqual(nformat(price, ','), '€ 1,23')