diff --git a/num2words/currency.py b/num2words/currency.py new file mode 100644 index 0000000..c28c82a --- /dev/null +++ b/num2words/currency.py @@ -0,0 +1,37 @@ +from __future__ import division + +from decimal import Decimal + + +def parse_currency_parts(value): + if isinstance(value, int): + # assume cents if value is integer + negative = value < 0 + value = abs(value) + integer, cents = divmod(value, 100) + + elif isinstance(value, Decimal): + negative = value < 0 + value = abs(value) + integer, fraction = divmod(value, 1) + integer = int(integer) + cents = int(fraction * 100) + + else: + # @TODO consider using something (babel) that does locale aware parsing + value = str(value).replace(',', '.') + negative = value.startswith('-') + + if negative: + value = value.lstrip('-') + + if '.' in value: + integer, fraction = value.rsplit('.', 1) + fraction = fraction.ljust(2, "0") + else: + integer, fraction = value, 0 + + integer = int(integer) + cents = int(fraction) + + return integer, cents, negative diff --git a/num2words/lang_LT.py b/num2words/lang_LT.py index ed8f462..326c6c7 100644 --- a/num2words/lang_LT.py +++ b/num2words/lang_LT.py @@ -95,6 +95,8 @@ vienas tūkstantis du šimtai trisdešimt keturi eurai, penkiasdešimt šeši ce """ from __future__ import unicode_literals +from .currency import parse_currency_parts + ZERO = (u'nulis',) ONES = { @@ -223,34 +225,11 @@ def n2w(n): def to_currency(n, currency='EUR', cents=True): - if type(n) == int: - if n < 0: - minus = True - else: - minus = False - - n = abs(n) - left = n / 100 - right = n % 100 - else: - n = str(n).replace(',', '.') - if '.' in n: - left, right = n.split('.') - else: - left, right = n, 0 - left, right = int(left), int(right) - minus = False + left, right, is_negative = parse_currency_parts(n) cr1, cr2 = CURRENCIES[currency] - if minus: - minus_str = "minus " - else: - minus_str = "" - - if cents: - cents_str = int2word(right) - else: - cents_str = "%02d" % right + minus_str = "minus " if is_negative else "" + cents_str = int2word(right) if cents else "%02d" % right return u'%s%s %s, %s %s' % (minus_str, int2word(left), pluralize(left, cr1), diff --git a/num2words/lang_LV.py b/num2words/lang_LV.py index 18f1878..a1ae8d2 100644 --- a/num2words/lang_LV.py +++ b/num2words/lang_LV.py @@ -99,6 +99,8 @@ mīnus divpadsmit tūkstoši pieci simti deviņpadsmit eiro, 85 centi """ from __future__ import unicode_literals +from .currency import parse_currency_parts + ZERO = (u'nulle',) ONES = { @@ -233,34 +235,11 @@ def n2w(n): def to_currency(n, currency='EUR', cents=True, seperator=','): - if type(n) == int: - if n < 0: - minus = True - else: - minus = False - - n = abs(n) - left = n / 100 - right = n % 100 - else: - n = str(n).replace(',', '.') - if '.' in n: - left, right = n.split('.') - else: - left, right = n, 0 - left, right = int(left), int(right) - minus = False + left, right, is_negative = parse_currency_parts(n) cr1, cr2 = CURRENCIES[currency] - if minus: - minus_str = "mīnus " - else: - minus_str = "" - - if cents: - cents_str = int2word(right) - else: - cents_str = "%02d" % right + minus_str = "mīnus " if is_negative else "" + cents_str = int2word(right) if cents else "%02d" % right return u'%s%s %s%s %s %s' % ( minus_str, diff --git a/num2words/lang_PL.py b/num2words/lang_PL.py index 39cbaa8..46c3b46 100644 --- a/num2words/lang_PL.py +++ b/num2words/lang_PL.py @@ -104,6 +104,8 @@ sto dwadzieścia trzy złote i pięćdziesiąt groszy """ from __future__ import unicode_literals +from .currency import parse_currency_parts + ZERO = (u'zero',) ONES = { @@ -241,36 +243,11 @@ def n2w(n): def to_currency(n, currency='EUR', cents=True, seperator=','): - if type(n) == int: - if n < 0: - minus = True - else: - minus = False - - n = abs(n) - left = n // 100 - right = n % 100 - else: - n = str(n).replace(',', '.') - if '.' in n: - left, right = n.split('.') - if len(right) == 1: - right = right + '0' - else: - left, right = n, 0 - left, right = int(left), int(right) - minus = False + left, right, is_negative = parse_currency_parts(n) cr1, cr2 = CURRENCIES[currency] - if minus: - minus_str = "minus " - else: - minus_str = "" - - if cents: - cents_str = int2word(right) - else: - cents_str = "%02d" % right + minus_str = "minus " if is_negative else "" + cents_str = int2word(right) if cents else "%02d" % right return u'%s%s %s%s %s %s' % ( minus_str, diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index 080eec5..71a7815 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -103,6 +103,8 @@ u""" """ from __future__ import unicode_literals +from .currency import parse_currency_parts + ZERO = (u'ноль',) ONES_FEMININE = { @@ -259,29 +261,10 @@ def n2w(n): def to_currency(n, currency='EUR', cents=True, seperator=','): - if type(n) == int: - if n < 0: - minus = True - else: - minus = False - - n = abs(n) - left = n / 100 - right = n % 100 - else: - n = str(n).replace(',', '.') - if '.' in n: - left, right = n.split('.') - else: - left, right = n, 0 - left, right = int(left), int(right) - minus = False + left, right, is_negative = parse_currency_parts(n) cr1, cr2 = CURRENCIES[currency] - if minus: - minus_str = "минус " - else: - minus_str = "" + minus_str = "минус " if is_negative else "" if cents: cents_feminine = currency == 'RUB' diff --git a/num2words/lang_UK.py b/num2words/lang_UK.py index 2b75bfa..c16aaed 100644 --- a/num2words/lang_UK.py +++ b/num2words/lang_UK.py @@ -103,6 +103,8 @@ u""" """ from __future__ import unicode_literals +from .currency import parse_currency_parts + ZERO = (u'нуль',) ONES_FEMININE = { @@ -264,29 +266,10 @@ def n2w(n): def to_currency(n, currency='EUR', cents=True, seperator=','): - if type(n) == int: - if n < 0: - minus = True - else: - minus = False - - n = abs(n) - left = n / 100 - right = n % 100 - else: - n = str(n).replace(',', '.') - if '.' in n: - left, right = n.split('.') - else: - left, right = n, 0 - left, right = int(left), int(right) - minus = False + left, right, is_negative = parse_currency_parts(n) cr1, cr2 = CURRENCIES[currency] - if minus: - minus_str = "мiнус " - else: - minus_str = "" + minus_str = "мiнус " if is_negative else "" if cents: cents_feminine = currency == 'UAH' diff --git a/tests/test_currency.py b/tests/test_currency.py new file mode 100644 index 0000000..b3bdb58 --- /dev/null +++ b/tests/test_currency.py @@ -0,0 +1,28 @@ +from decimal import Decimal +from unittest import TestCase + +from num2words.currency import parse_currency_parts + + +class CurrencyTestCase(TestCase): + def test_parse_currency_parts(self): + # integer cents + self.assertEqual(parse_currency_parts(101), (1, 1, False)) + self.assertEqual(parse_currency_parts(-123), (1, 23, True)) + + # decimal + self.assertEqual(parse_currency_parts(Decimal("1.01")), (1, 1, False)) + self.assertEqual(parse_currency_parts(Decimal("-1.23")), (1, 23, True)) + self.assertEqual(parse_currency_parts(Decimal("-1.233")), + (1, 23, True)) + + # string + self.assertEqual(parse_currency_parts("1.01"), (1, 1, False)) + self.assertEqual(parse_currency_parts("-1.23"), (1, 23, True)) + self.assertEqual(parse_currency_parts("-1.2"), (1, 20, True)) + self.assertEqual(parse_currency_parts("1"), (1, 0, False)) + + # float + self.assertEqual(parse_currency_parts(1.01), (1, 1, False)) + self.assertEqual(parse_currency_parts(-1.23), (1, 23, True)) + self.assertEqual(parse_currency_parts(-1.2), (1, 20, True)) diff --git a/tests/test_lv.py b/tests/test_lv.py new file mode 100644 index 0000000..1616a31 --- /dev/null +++ b/tests/test_lv.py @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +from __future__ import unicode_literals + +from unittest import TestCase + +from num2words import num2words + + +class Num2WordsLVTest(TestCase): + def test_to_currency(self): + self.assertEqual( + num2words('38.4', lang='lv', to='currency', seperator=' un', + cents=False, currency='EUR'), + "trīsdesmit astoņi eiro un 40 centi" + ) diff --git a/tests/test_ru.py b/tests/test_ru.py index 9b1ae93..0f644ae 100644 --- a/tests/test_ru.py +++ b/tests/test_ru.py @@ -13,6 +13,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA +from __future__ import unicode_literals from unittest import TestCase @@ -22,23 +23,30 @@ from num2words import num2words class Num2WordsRUTest(TestCase): def test_cardinal(self): - self.assertEqual(num2words(5, lang='ru'), u"пять") - self.assertEqual(num2words(15, lang='ru'), u"пятнадцать") - self.assertEqual(num2words(154, lang='ru'), u"сто пятьдесят четыре") + self.assertEqual(num2words(5, lang='ru'), "пять") + self.assertEqual(num2words(15, lang='ru'), "пятнадцать") + self.assertEqual(num2words(154, lang='ru'), "сто пятьдесят четыре") self.assertEqual( - num2words(1135, lang='ru'), u"одна тысяча сто тридцать пять" + num2words(1135, lang='ru'), "одна тысяча сто тридцать пять" ) self.assertEqual( num2words(418531, lang='ru'), - u"четыреста восемнадцать тысяч пятьсот тридцать один" + "четыреста восемнадцать тысяч пятьсот тридцать один" ) self.assertEqual( - num2words(1000139, lang='ru'), u"один миллион сто тридцать девять" + num2words(1000139, lang='ru'), "один миллион сто тридцать девять" ) def test_floating_point(self): - self.assertEqual(num2words(5.2, lang='ru'), u"пять запятая два") + self.assertEqual(num2words(5.2, lang='ru'), "пять запятая два") self.assertEqual( num2words(561.42, lang='ru'), - u"пятьсот шестьдесят один запятая сорок два" + "пятьсот шестьдесят один запятая сорок два" + ) + + def test_to_currency(self): + self.assertEqual( + num2words('38.4', lang='ru', to='currency', seperator=' и', + cents=False, currency='EUR'), + "тридцать восемь евро и 40 центов" ) diff --git a/tests/test_uk.py b/tests/test_uk.py index 8c20cbc..81737a4 100644 --- a/tests/test_uk.py +++ b/tests/test_uk.py @@ -13,6 +13,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA +from __future__ import unicode_literals from unittest import TestCase @@ -21,18 +22,25 @@ from num2words import num2words class Num2WordsUKTest(TestCase): def test_and_join_199(self): - self.assertEqual(num2words(187, lang='uk'), u"сто вiсiмдесят сiм") + self.assertEqual(num2words(187, lang='uk'), "сто вiсiмдесят сiм") def test_cardinal_for_float_number(self): self.assertEqual( - num2words(12.40, lang='uk'), u"дванадцять кома чотири" + num2words(12.40, lang='uk'), "дванадцять кома чотири" ) self.assertEqual( - num2words(17.31, lang='uk'), u"сiмнадцять кома тридцять одна" + num2words(17.31, lang='uk'), "сiмнадцять кома тридцять одна" ) self.assertEqual( - num2words(14.13, lang='uk'), u"чотирнадцять кома тринадцять" + num2words(14.13, lang='uk'), "чотирнадцять кома тринадцять" ) self.assertEqual( - num2words(12.31, lang='uk'), u"дванадцять кома тридцять одна" + num2words(12.31, lang='uk'), "дванадцять кома тридцять одна" + ) + + def test_to_currency(self): + self.assertEqual( + num2words('38.4', lang='uk', to='currency', seperator=' и', + cents=False, currency='EUR'), + "тридцять вiсiм евро и 40 центiв" )