Использование babel
В документации babel отмечается, что анализ номеров реализован не полностью да но они проделали большую работу, чтобы получить информацию о валюте в библиотеке. Вы можете использовать get_currency_name()
и get_currency_symbol()
для получения сведений о валюте, а также все другие get_...
функции для получения сведений о обычных числах (десятичная точка, знак минус и т. Д.).
Используя эту информацию, вы можете исключить из строки валюты детали валюты (имя, знак) и группы (например, ,
в США). Затем вы меняете десятичные числа на те, которые используются C
локалью (-
для минуса и .
для десятичной точки).
В результате получается следующий код (я добавил объект для хранения некоторых данных, которые могут пригодиться при дальнейшей обработке):
import re, os
from babel import numbers as n
from babel.core import default_locale
class AmountInfo(object):
def __init__(self, name, symbol, value):
self.name = name
self.symbol = symbol
self.value = value
def parse_currency(value, cur):
decp = n.get_decimal_symbol()
plus = n.get_plus_sign_symbol()
minus = n.get_minus_sign_symbol()
group = n.get_group_symbol()
name = n.get_currency_name(cur)
symbol = n.get_currency_symbol(cur)
remove = [plus, name, symbol, group]
for token in remove:
# remove the pieces of information that shall be obvious
value = re.sub(re.escape(token), '', value)
# change the minus sign to a LOCALE=C minus
value = re.sub(re.escape(minus), '-', value)
# and change the decimal mark to a LOCALE=C decimal point
value = re.sub(re.escape(decp), '.', value)
# just in case remove extraneous spaces
value = re.sub('\s+', '', value)
return AmountInfo(name, symbol, value)
#cur_loc = os.environ['LC_ALL']
cur_loc = default_locale()
print('locale:', cur_loc)
test = [ (n.format_currency(123456.789, 'USD', locale=cur_loc), 'USD')
, (n.format_currency(-123456.78, 'PLN', locale=cur_loc), 'PLN')
, (n.format_currency(123456.789, 'PLN', locale=cur_loc), 'PLN')
, (n.format_currency(123456.789, 'IDR', locale=cur_loc), 'IDR')
, (n.format_currency(123456.789, 'JPY', locale=cur_loc), 'JPY')
, (n.format_currency(-123456.78, 'JPY', locale=cur_loc), 'JPY')
, (n.format_currency(123456.789, 'CNY', locale=cur_loc), 'CNY')
, (n.format_currency(-123456.78, 'CNY', locale=cur_loc), 'CNY')
]
for v,c in test:
print('As currency :', c, ':', v.encode('utf-8'))
info = parse_currency(v, c)
print('As value :', c, ':', info.value)
print('Extra info :', info.name.encode('utf-8')
, info.symbol.encode('utf-8'))
Результат выглядит многообещающим (для США):
$ export LC_ALL=en_US
$ ./cur.py
locale: en_US
As currency : USD : b'$123,456.79'
As value : USD : 123456.79
Extra info : b'US Dollar' b'$'
As currency : PLN : b'-z\xc5\x82123,456.78'
As value : PLN : -123456.78
Extra info : b'Polish Zloty' b'z\xc5\x82'
As currency : PLN : b'z\xc5\x82123,456.79'
As value : PLN : 123456.79
Extra info : b'Polish Zloty' b'z\xc5\x82'
As currency : IDR : b'Rp123,457'
As value : IDR : 123457
Extra info : b'Indonesian Rupiah' b'Rp'
As currency : JPY : b'\xc2\xa5123,457'
As value : JPY : 123457
Extra info : b'Japanese Yen' b'\xc2\xa5'
As currency : JPY : b'-\xc2\xa5123,457'
As value : JPY : -123457
Extra info : b'Japanese Yen' b'\xc2\xa5'
As currency : CNY : b'CN\xc2\xa5123,456.79'
As value : CNY : 123456.79
Extra info : b'Chinese Yuan' b'CN\xc2\xa5'
As currency : CNY : b'-CN\xc2\xa5123,456.78'
As value : CNY : -123456.78
Extra info : b'Chinese Yuan' b'CN\xc2\xa5'
И он по-прежнему работает в разных регионах (Бразилия примечательна тем, что в качестве десятичного знака используется запятая):
$ export LC_ALL=pt_BR
$ ./cur.py
locale: pt_BR
As currency : USD : b'US$123.456,79'
As value : USD : 123456.79
Extra info : b'D\xc3\xb3lar americano' b'US$'
As currency : PLN : b'-PLN123.456,78'
As value : PLN : -123456.78
Extra info : b'Zloti polon\xc3\xaas' b'PLN'
As currency : PLN : b'PLN123.456,79'
As value : PLN : 123456.79
Extra info : b'Zloti polon\xc3\xaas' b'PLN'
As currency : IDR : b'IDR123.457'
As value : IDR : 123457
Extra info : b'Rupia indon\xc3\xa9sia' b'IDR'
As currency : JPY : b'JP\xc2\xa5123.457'
As value : JPY : 123457
Extra info : b'Iene japon\xc3\xaas' b'JP\xc2\xa5'
As currency : JPY : b'-JP\xc2\xa5123.457'
As value : JPY : -123457
Extra info : b'Iene japon\xc3\xaas' b'JP\xc2\xa5'
As currency : CNY : b'CN\xc2\xa5123.456,79'
As value : CNY : 123456.79
Extra info : b'Yuan chin\xc3\xaas' b'CN\xc2\xa5'
As currency : CNY : b'-CN\xc2\xa5123.456,78'
As value : CNY : -123456.78
Extra info : b'Yuan chin\xc3\xaas' b'CN\xc2\xa5'
Следует отметить, что babel
имеет некоторые проблемы с кодированием. Это потому, что файлы локали (в locale-data
) сами используют другую кодировку. Если вы работаете с валютами, с которыми вы знакомы, это не должно быть проблемой. Но если вы попробуете использовать незнакомую валюту, у вас могут возникнуть проблемы (я только что узнал, что Польша использует iso-8859-2
, а не iso-8859-1
).
person
grochmal
schedule
02.06.2016
,
или.
. - person SparkAndShine   schedule 02.06.2016.
по-прежнему имеет значение. - person leekaiinthesky   schedule 02.06.2016