2014-11-30 16:29:52 +08:00
|
|
|
from decimal import Decimal
|
|
|
|
from sys import float_info
|
|
|
|
|
2018-07-20 04:44:40 +08:00
|
|
|
from django.test import SimpleTestCase
|
2012-09-09 00:29:29 +08:00
|
|
|
from django.utils.numberformat import format as nformat
|
|
|
|
|
|
|
|
|
2018-07-20 04:44:40 +08:00
|
|
|
class TestNumberFormat(SimpleTestCase):
|
2012-09-09 00:29:29 +08:00
|
|
|
def test_format_number(self):
|
|
|
|
self.assertEqual(nformat(1234, "."), "1234")
|
|
|
|
self.assertEqual(nformat(1234.2, "."), "1234.2")
|
|
|
|
self.assertEqual(nformat(1234, ".", decimal_pos=2), "1234.00")
|
2016-01-29 23:36:58 +08:00
|
|
|
self.assertEqual(nformat(1234, ".", grouping=2, thousand_sep=","), "1234")
|
|
|
|
self.assertEqual(
|
|
|
|
nformat(1234, ".", grouping=2, thousand_sep=",", force_grouping=True),
|
|
|
|
"12,34",
|
|
|
|
)
|
2012-09-09 00:29:29 +08:00
|
|
|
self.assertEqual(nformat(-1234.33, ".", decimal_pos=1), "-1234.3")
|
2018-07-20 04:44:40 +08:00
|
|
|
# The use_l10n parameter can force thousand grouping behavior.
|
2021-09-09 13:42:05 +08:00
|
|
|
with self.settings(USE_THOUSAND_SEPARATOR=True):
|
2018-07-20 04:44:40 +08:00
|
|
|
self.assertEqual(
|
|
|
|
nformat(1234, ".", grouping=3, thousand_sep=",", use_l10n=False), "1234"
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
nformat(1234, ".", grouping=3, thousand_sep=",", use_l10n=True), "1,234"
|
|
|
|
)
|
2012-09-09 00:29:29 +08:00
|
|
|
|
|
|
|
def test_format_string(self):
|
|
|
|
self.assertEqual(nformat("1234", "."), "1234")
|
|
|
|
self.assertEqual(nformat("1234.2", "."), "1234.2")
|
|
|
|
self.assertEqual(nformat("1234", ".", decimal_pos=2), "1234.00")
|
2016-01-29 23:36:58 +08:00
|
|
|
self.assertEqual(nformat("1234", ".", grouping=2, thousand_sep=","), "1234")
|
|
|
|
self.assertEqual(
|
|
|
|
nformat("1234", ".", grouping=2, thousand_sep=",", force_grouping=True),
|
|
|
|
"12,34",
|
|
|
|
)
|
2012-09-09 00:29:29 +08:00
|
|
|
self.assertEqual(nformat("-1234.33", ".", decimal_pos=1), "-1234.3")
|
2016-01-29 23:36:58 +08:00
|
|
|
self.assertEqual(
|
|
|
|
nformat(
|
|
|
|
"10000", ".", grouping=3, thousand_sep="comma", force_grouping=True
|
|
|
|
),
|
|
|
|
"10comma000",
|
|
|
|
)
|
2012-09-09 00:29:29 +08:00
|
|
|
|
|
|
|
def test_large_number(self):
|
2016-01-29 23:36:58 +08:00
|
|
|
most_max = (
|
|
|
|
"{}179769313486231570814527423731704356798070567525844996"
|
|
|
|
"598917476803157260780028538760589558632766878171540458953"
|
|
|
|
"514382464234321326889464182768467546703537516986049910576"
|
|
|
|
"551282076245490090389328944075868508455133942304583236903"
|
|
|
|
"222948165808559332123348274797826204144723168738177180919"
|
|
|
|
"29988125040402618412485836{}"
|
|
|
|
)
|
|
|
|
most_max2 = (
|
|
|
|
"{}35953862697246314162905484746340871359614113505168999"
|
|
|
|
"31978349536063145215600570775211791172655337563430809179"
|
|
|
|
"07028764928468642653778928365536935093407075033972099821"
|
|
|
|
"15310256415249098018077865788815173701691026788460916647"
|
|
|
|
"38064458963316171186642466965495956524082894463374763543"
|
|
|
|
"61838599762500808052368249716736"
|
|
|
|
)
|
2012-09-09 00:29:29 +08:00
|
|
|
int_max = int(float_info.max)
|
|
|
|
self.assertEqual(nformat(int_max, "."), most_max.format("", "8"))
|
|
|
|
self.assertEqual(nformat(int_max + 1, "."), most_max.format("", "9"))
|
|
|
|
self.assertEqual(nformat(int_max * 2, "."), most_max2.format(""))
|
|
|
|
self.assertEqual(nformat(0 - int_max, "."), most_max.format("-", "8"))
|
|
|
|
self.assertEqual(nformat(-1 - int_max, "."), most_max.format("-", "9"))
|
|
|
|
self.assertEqual(nformat(-2 * int_max, "."), most_max2.format("-"))
|
2014-11-30 16:29:52 +08:00
|
|
|
|
2017-06-13 22:48:53 +08:00
|
|
|
def test_float_numbers(self):
|
2020-02-23 21:37:02 +08:00
|
|
|
tests = [
|
|
|
|
(9e-10, 10, "0.0000000009"),
|
|
|
|
(9e-19, 2, "0.00"),
|
|
|
|
(0.00000000000099, 0, "0"),
|
|
|
|
(0.00000000000099, 13, "0.0000000000009"),
|
|
|
|
(1e16, None, "10000000000000000"),
|
|
|
|
(1e16, 2, "10000000000000000.00"),
|
|
|
|
# A float without a fractional part (3.) results in a ".0" when no
|
|
|
|
# decimal_pos is given. Contrast that with the Decimal('3.') case
|
|
|
|
# in test_decimal_numbers which doesn't return a fractional part.
|
|
|
|
(3.0, None, "3.0"),
|
|
|
|
]
|
|
|
|
for value, decimal_pos, expected_value in tests:
|
|
|
|
with self.subTest(value=value, decimal_pos=decimal_pos):
|
|
|
|
self.assertEqual(nformat(value, ".", decimal_pos), expected_value)
|
|
|
|
# Thousand grouping behavior.
|
|
|
|
self.assertEqual(
|
|
|
|
nformat(1e16, ".", thousand_sep=",", grouping=3, force_grouping=True),
|
|
|
|
"10,000,000,000,000,000",
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
nformat(
|
|
|
|
1e16,
|
|
|
|
".",
|
|
|
|
decimal_pos=2,
|
|
|
|
thousand_sep=",",
|
|
|
|
grouping=3,
|
|
|
|
force_grouping=True,
|
|
|
|
),
|
|
|
|
"10,000,000,000,000,000.00",
|
|
|
|
)
|
2017-06-13 22:48:53 +08:00
|
|
|
|
2014-11-30 16:29:52 +08:00
|
|
|
def test_decimal_numbers(self):
|
|
|
|
self.assertEqual(nformat(Decimal("1234"), "."), "1234")
|
|
|
|
self.assertEqual(nformat(Decimal("1234.2"), "."), "1234.2")
|
|
|
|
self.assertEqual(nformat(Decimal("1234"), ".", decimal_pos=2), "1234.00")
|
2017-06-13 22:48:53 +08:00
|
|
|
self.assertEqual(
|
|
|
|
nformat(Decimal("1234"), ".", grouping=2, thousand_sep=","), "1234"
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
nformat(
|
|
|
|
Decimal("1234"), ".", grouping=2, thousand_sep=",", force_grouping=True
|
|
|
|
),
|
|
|
|
"12,34",
|
|
|
|
)
|
2014-11-30 16:29:52 +08:00
|
|
|
self.assertEqual(nformat(Decimal("-1234.33"), ".", decimal_pos=1), "-1234.3")
|
2017-06-13 22:48:53 +08:00
|
|
|
self.assertEqual(
|
2014-11-30 16:29:52 +08:00
|
|
|
nformat(Decimal("0.00000001"), ".", decimal_pos=8), "0.00000001"
|
2022-02-04 03:24:19 +08:00
|
|
|
)
|
2017-06-13 22:48:53 +08:00
|
|
|
self.assertEqual(nformat(Decimal("9e-19"), ".", decimal_pos=2), "0.00")
|
|
|
|
self.assertEqual(nformat(Decimal(".00000000000099"), ".", decimal_pos=0), "0")
|
|
|
|
self.assertEqual(
|
2022-02-04 03:24:19 +08:00
|
|
|
nformat(
|
2014-11-30 16:29:52 +08:00
|
|
|
Decimal("1e16"), ".", thousand_sep=",", grouping=3, force_grouping=True
|
2022-02-04 03:24:19 +08:00
|
|
|
),
|
2017-06-13 22:48:53 +08:00
|
|
|
"10,000,000,000,000,000",
|
2022-02-04 03:24:19 +08:00
|
|
|
)
|
2017-06-13 22:48:53 +08:00
|
|
|
self.assertEqual(
|
2022-02-04 03:24:19 +08:00
|
|
|
nformat(
|
2019-02-11 18:08:45 +08:00
|
|
|
Decimal("1e16"),
|
2022-02-04 03:24:19 +08:00
|
|
|
".",
|
2017-06-13 22:48:53 +08:00
|
|
|
decimal_pos=2,
|
2014-11-30 16:29:52 +08:00
|
|
|
thousand_sep=",",
|
2017-06-13 22:48:53 +08:00
|
|
|
grouping=3,
|
|
|
|
force_grouping=True,
|
2022-02-04 03:24:19 +08:00
|
|
|
),
|
2017-06-13 22:48:53 +08:00
|
|
|
"10,000,000,000,000,000.00",
|
2022-02-04 03:24:19 +08:00
|
|
|
)
|
2017-06-13 22:48:53 +08:00
|
|
|
self.assertEqual(nformat(Decimal("3."), "."), "3")
|
|
|
|
self.assertEqual(nformat(Decimal("3.0"), "."), "3.0")
|
2019-02-11 18:08:45 +08:00
|
|
|
# Very large & small numbers.
|
|
|
|
tests = [
|
|
|
|
("9e9999", None, "9e+9999"),
|
|
|
|
("9e9999", 3, "9.000e+9999"),
|
|
|
|
("9e201", None, "9e+201"),
|
|
|
|
("9e200", None, "9e+200"),
|
|
|
|
("1.2345e999", 2, "1.23e+999"),
|
|
|
|
("9e-999", None, "9e-999"),
|
|
|
|
("1e-7", 8, "0.00000010"),
|
|
|
|
("1e-8", 8, "0.00000001"),
|
|
|
|
("1e-9", 8, "0.00000000"),
|
|
|
|
("1e-10", 8, "0.00000000"),
|
|
|
|
("1e-11", 8, "0.00000000"),
|
|
|
|
("1" + ("0" * 300), 3, "1.000e+300"),
|
2019-04-13 18:11:34 +08:00
|
|
|
("0.{}1234".format("0" * 299), 3, "0.000"),
|
2019-02-11 18:08:45 +08:00
|
|
|
]
|
|
|
|
for value, decimal_pos, expected_value in tests:
|
|
|
|
with self.subTest(value=value):
|
|
|
|
self.assertEqual(
|
|
|
|
nformat(Decimal(value), ".", decimal_pos), expected_value
|
|
|
|
)
|
2015-03-10 00:56:13 +08:00
|
|
|
|
|
|
|
def test_decimal_subclass(self):
|
|
|
|
class EuroDecimal(Decimal):
|
|
|
|
"""
|
|
|
|
Wrapper for Decimal which prefixes each amount with the € symbol.
|
|
|
|
"""
|
2022-02-04 03:24:19 +08:00
|
|
|
|
2015-03-10 00:56:13 +08:00
|
|
|
def __format__(self, specifier, **kwargs):
|
2017-01-21 21:13:44 +08:00
|
|
|
amount = super().__format__(specifier, **kwargs)
|
2015-03-10 00:56:13 +08:00
|
|
|
return "€ {}".format(amount)
|
|
|
|
|
|
|
|
price = EuroDecimal("1.23")
|
|
|
|
self.assertEqual(nformat(price, ","), "€ 1,23")
|