annotate babel/numbers.py @ 212:2b0b9bb94660 trunk

Switched to using our own round() implementation. This way we can be sure the correct rounding algorithm (banker's rounding) is used on all platforms.
author jonas
date Tue, 10 Jul 2007 21:20:07 +0000
parents 5125934e5f27
children cc699743ec06
rev   line source
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
2 #
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
3 # Copyright (C) 2007 Edgewall Software
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
4 # All rights reserved.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
5 #
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
8 # are also available at http://babel.edgewall.org/wiki/License.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
9 #
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://babel.edgewall.org/log/.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
13
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
14 """Locale dependent formatting and parsing of numeric data.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
15
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
16 The default locale for the functions in this module is determined by the
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
17 following environment variables, in that order:
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
18
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
19 * ``LC_NUMERIC``,
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
20 * ``LC_ALL``, and
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
21 * ``LANG``
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
22 """
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
23 # TODO: percent and scientific formatting
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
24
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
25 import re
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
26
72
e0bb7dce49ea More explicit module-level function names in `babel.core`. Added `Locale.negotiate` class method.
cmlenz
parents: 50
diff changeset
27 from babel.core import default_locale, Locale
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
28
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
29 __all__ = ['format_number', 'format_decimal', 'format_currency',
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
30 'format_percent', 'format_scientific', 'parse_number',
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
31 'parse_decimal', 'NumberFormatError']
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
32 __docformat__ = 'restructuredtext en'
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
33
72
e0bb7dce49ea More explicit module-level function names in `babel.core`. Added `Locale.negotiate` class method.
cmlenz
parents: 50
diff changeset
34 LC_NUMERIC = default_locale('LC_NUMERIC')
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
35
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
36 def get_currency_symbol(currency, locale=LC_NUMERIC):
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
37 """Return the symbol used by the locale for the specified currency.
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
38
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
39 >>> get_currency_symbol('USD', 'en_US')
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
40 u'$'
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
41
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
42 :param currency: the currency code
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
43 :param locale: the `Locale` object or locale identifier
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
44 :return: the currency symbol
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
45 :rtype: `unicode`
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
46 """
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
47 return Locale.parse(locale).currency_symbols.get(currency, currency)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
48
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
49 def get_decimal_symbol(locale=LC_NUMERIC):
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
50 """Return the symbol used by the locale to separate decimal fractions.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
51
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
52 >>> get_decimal_symbol('en_US')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
53 u'.'
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
54
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
55 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
56 :return: the decimal symbol
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
57 :rtype: `unicode`
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
58 """
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
59 return Locale.parse(locale).number_symbols.get('decimal', u'.')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
60
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
61 def get_group_symbol(locale=LC_NUMERIC):
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
62 """Return the symbol used by the locale to separate groups of thousands.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
63
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
64 >>> get_group_symbol('en_US')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
65 u','
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
66
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
67 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
68 :return: the group symbol
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
69 :rtype: `unicode`
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
70 """
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
71 return Locale.parse(locale).number_symbols.get('group', u',')
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
72
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
73 def format_number(number, locale=LC_NUMERIC):
101
0f641136aa6b Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents: 72
diff changeset
74 """Return the given number formatted for a specific locale.
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
75
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
76 >>> format_number(1099, locale='en_US')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
77 u'1,099'
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
78
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
79 :param number: the number to format
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
80 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
81 :return: the formatted number
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
82 :rtype: `unicode`
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
83 """
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
84 # Do we really need this one?
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
85 return format_decimal(number, locale=locale)
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
86
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
87 def format_decimal(number, format=None, locale=LC_NUMERIC):
101
0f641136aa6b Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents: 72
diff changeset
88 """Return the given decimal number formatted for a specific locale.
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
89
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
90 >>> format_decimal(1.2345, locale='en_US')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
91 u'1.234'
50
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
92 >>> format_decimal(1.2346, locale='en_US')
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
93 u'1.235'
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
94 >>> format_decimal(-1.2346, locale='en_US')
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
95 u'-1.235'
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
96 >>> format_decimal(1.2345, locale='sv_SE')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
97 u'1,234'
50
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
98 >>> format_decimal(12345, locale='de')
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
99 u'12.345'
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
100
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
101 The appropriate thousands grouping and the decimal separator are used for
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
102 each locale:
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
103
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
104 >>> format_decimal(12345.5, locale='en_US')
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
105 u'12,345.5'
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
106
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
107 :param number: the number to format
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
108 :param format:
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
109 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
110 :return: the formatted decimal number
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
111 :rtype: `unicode`
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
112 """
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
113 locale = Locale.parse(locale)
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
114 if not format:
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
115 format = locale.decimal_formats.get(format)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
116 pattern = parse_pattern(format)
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
117 return pattern.apply(number, locale)
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
118
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
119 def format_currency(number, currency, format=None, locale=LC_NUMERIC):
133
32b28673cfd5 Minor doc fixes.
cmlenz
parents: 127
diff changeset
120 u"""Return formatted currency value.
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
121
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
122 >>> format_currency(1099.98, 'USD', locale='en_US')
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
123 u'$1,099.98'
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
124 >>> format_currency(1099.98, 'USD', locale='es_CO')
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
125 u'US$1.099,98'
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
126 >>> format_currency(1099.98, 'EUR', locale='de_DE')
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
127 u'1.099,98 \\u20ac'
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
128
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
129 The pattern can also be specified explicitly:
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
130
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
131 >>> format_currency(1099.98, 'EUR', u'\xa4\xa4 #,##0.00', locale='en_US')
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
132 u'EUR 1,099.98'
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
133
26
6041782ea677 * Reduce size of locale data pickles by only storing the data provided by each locale itself, and merging inherited data at runtime.
cmlenz
parents: 22
diff changeset
134 :param number: the number to format
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
135 :param currency: the currency code
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
136 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
137 :return: the formatted currency value
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
138 :rtype: `unicode`
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
139 """
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
140 locale = Locale.parse(locale)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
141 if not format:
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
142 format = locale.currency_formats.get(format)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
143 pattern = parse_pattern(format)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
144 return pattern.apply(number, locale, currency=currency)
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
145
26
6041782ea677 * Reduce size of locale data pickles by only storing the data provided by each locale itself, and merging inherited data at runtime.
cmlenz
parents: 22
diff changeset
146 def format_percent(number, format=None, locale=LC_NUMERIC):
101
0f641136aa6b Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents: 72
diff changeset
147 """Return formatted percent value for a specific locale.
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
148
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
149 >>> format_percent(0.34, locale='en_US')
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
150 u'34%'
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
151 >>> format_percent(25.1234, locale='en_US')
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
152 u'2,512%'
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
153 >>> format_percent(25.1234, locale='sv_SE')
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
154 u'2\\xa0512 %'
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
155
126
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
156 The format pattern can also be specified explicitly:
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
157
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
158 >>> format_percent(25.1234, u'#,##0\u2030', locale='en_US')
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
159 u'25,123\u2030'
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
160
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
161 :param number: the percent number to format
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
162 :param format:
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
163 :param locale: the `Locale` object or locale identifier
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
164 :return: the formatted percent number
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
165 :rtype: `unicode`
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
166 """
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
167 locale = Locale.parse(locale)
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
168 if not format:
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
169 format = locale.percent_formats.get(format)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
170 pattern = parse_pattern(format)
26
6041782ea677 * Reduce size of locale data pickles by only storing the data provided by each locale itself, and merging inherited data at runtime.
cmlenz
parents: 22
diff changeset
171 return pattern.apply(number, locale)
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
172
26
6041782ea677 * Reduce size of locale data pickles by only storing the data provided by each locale itself, and merging inherited data at runtime.
cmlenz
parents: 22
diff changeset
173 def format_scientific(number, locale=LC_NUMERIC):
126
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
174 # TODO: implement
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
175 raise NotImplementedError
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
176
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
177
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
178 class NumberFormatError(ValueError):
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
179 """Exception raised when a string cannot be parsed into a number."""
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
180
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
181
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
182 def parse_number(string, locale=LC_NUMERIC):
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
183 """Parse localized number string into a long integer.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
184
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
185 >>> parse_number('1,099', locale='en_US')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
186 1099L
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
187 >>> parse_number('1.099', locale='de_DE')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
188 1099L
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
189
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
190 When the given string cannot be parsed, an exception is raised:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
191
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
192 >>> parse_number('1.099,98', locale='de')
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
193 Traceback (most recent call last):
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
194 ...
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
195 NumberFormatError: '1.099,98' is not a valid number
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
196
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
197 :param string: the string to parse
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
198 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
199 :return: the parsed number
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
200 :rtype: `long`
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
201 :raise `NumberFormatError`: if the string can not be converted to a number
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
202 """
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
203 try:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
204 return long(string.replace(get_group_symbol(locale), ''))
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
205 except ValueError:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
206 raise NumberFormatError('%r is not a valid number' % string)
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
207
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
208 def parse_decimal(string, locale=LC_NUMERIC):
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
209 """Parse localized decimal string into a float.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
210
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
211 >>> parse_decimal('1,099.98', locale='en_US')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
212 1099.98
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
213 >>> parse_decimal('1.099,98', locale='de')
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
214 1099.98
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
215
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
216 When the given string cannot be parsed, an exception is raised:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
217
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
218 >>> parse_decimal('2,109,998', locale='de')
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
219 Traceback (most recent call last):
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
220 ...
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
221 NumberFormatError: '2,109,998' is not a valid decimal number
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
222
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
223 :param string: the string to parse
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
224 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
225 :return: the parsed decimal number
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
226 :rtype: `float`
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
227 :raise `NumberFormatError`: if the string can not be converted to a
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
228 decimal number
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
229 """
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
230 locale = Locale.parse(locale)
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
231 try:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
232 return float(string.replace(get_group_symbol(locale), '')
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
233 .replace(get_decimal_symbol(locale), '.'))
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
234 except ValueError:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
235 raise NumberFormatError('%r is not a valid decimal number' % string)
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
236
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
237
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
238 PREFIX_END = r'[^0-9@#.,]'
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
239 NUMBER_TOKEN = r'[0-9@#.\-,E]'
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
240
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
241 PREFIX_PATTERN = r"(?P<prefix>(?:'[^']*'|%s)*)" % PREFIX_END
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
242 NUMBER_PATTERN = r"(?P<number>%s+)" % NUMBER_TOKEN
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
243 SUFFIX_PATTERN = r"(?P<suffix>.*)"
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
244
127
1bf549a5dc1c Add a couple of CLI tests.
cmlenz
parents: 126
diff changeset
245 number_re = re.compile(r"%s%s%s" % (PREFIX_PATTERN, NUMBER_PATTERN,
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
246 SUFFIX_PATTERN))
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
247
212
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
248 def bankersround(value, ndigits=0):
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
249 """Round a number to a given precision.
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
250
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
251 Works like round() except that the round-half-even (banker's rounding)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
252 algorithm is used instead of round-half-up.
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
253
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
254 >>> bankersround(5.5, 0)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
255 6.0
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
256 >>> bankersround(6.5, 0)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
257 6.0
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
258 >>> bankersround(-6.5, 0)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
259 -6.0
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
260 >>> bankersround(1234, -2)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
261 1200.0
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
262 """
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
263 sign = int(value < 0) and -1 or 1
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
264 value = abs(value)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
265 a, b = str(float(value)).split('.', 1)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
266 digits = str(float(value)).replace('.', '')
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
267 add = 0
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
268 i = len(a) + ndigits
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
269 if i < 0 or i >= len(digits):
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
270 pass
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
271 elif digits[i] > '5':
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
272 add = 1
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
273 elif digits[i] == '5' and digits[i-1] in '13579':
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
274 add = 1
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
275 scale = 10.**ndigits
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
276 return int(value * scale + add) / scale * sign
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
277
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
278 # TODO:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
279 # Filling
50
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
280 # Rounding increment in pattern
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
281 # Scientific notation
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
282 def parse_pattern(pattern):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
283 """Parse number format patterns"""
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
284 if isinstance(pattern, NumberPattern):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
285 return pattern
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
286
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
287 # Do we have a negative subpattern?
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
288 if ';' in pattern:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
289 pattern, neg_pattern = pattern.split(';', 1)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
290 pos_prefix, number, pos_suffix = number_re.search(pattern).groups()
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
291 neg_prefix, _, neg_suffix = number_re.search(neg_pattern).groups()
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
292 else:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
293 pos_prefix, number, pos_suffix = number_re.search(pattern).groups()
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
294 neg_prefix = '-' + pos_prefix
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
295 neg_suffix = pos_suffix
211
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
296 if '@' in number:
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
297 if '.' in number and '0' in number:
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
298 raise ValueError('Significant digit patterns can not contain '
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
299 '"@" or "0"')
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
300 if '.' in number:
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
301 integer, fraction = number.rsplit('.', 1)
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
302 else:
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
303 integer = number
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
304 fraction = ''
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
305 min_frac = max_frac = 0
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
306
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
307 def parse_precision(p):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
308 """Calculate the min and max allowed digits"""
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
309 min = max = 0
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
310 for c in p:
211
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
311 if c in '@0':
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
312 min += 1
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
313 max += 1
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
314 elif c == '#':
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
315 max += 1
211
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
316 elif c == ',':
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
317 continue
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
318 else:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
319 break
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
320 return min, max
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
321
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
322 def parse_grouping(p):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
323 """Parse primary and secondary digit grouping
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
324
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
325 >>> parse_grouping('##')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
326 0, 0
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
327 >>> parse_grouping('#,###')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
328 3, 3
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
329 >>> parse_grouping('#,####,###')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
330 3, 4
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
331 """
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
332 width = len(p)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
333 g1 = p.rfind(',')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
334 if g1 == -1:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
335 return 1000, 1000
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
336 g1 = width - g1 - 1
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
337 g2 = p[:-g1 - 1].rfind(',')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
338 if g2 == -1:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
339 return g1, g1
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
340 g2 = width - g1 - g2 - 2
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
341 return g1, g2
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
342
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
343 int_precision = parse_precision(integer)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
344 frac_precision = parse_precision(fraction)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
345 grouping = parse_grouping(integer)
211
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
346 if not '@' in pattern:
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
347 int_precision = (int_precision[0], 1000) # Unlimited
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
348 return NumberPattern(pattern, (pos_prefix, neg_prefix),
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
349 (pos_suffix, neg_suffix), grouping,
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
350 int_precision, frac_precision)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
351
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
352
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
353 class NumberPattern(object):
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
354
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
355 def __init__(self, pattern, prefix, suffix, grouping,
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
356 int_precision, frac_precision):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
357 self.pattern = pattern
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
358 self.prefix = prefix
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
359 self.suffix = suffix
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
360 self.grouping = grouping
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
361 self.int_precision = int_precision
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
362 self.frac_precision = frac_precision
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
363 if '%' in ''.join(self.prefix + self.suffix):
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
364 self.scale = 100.0
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
365 elif u'‰' in ''.join(self.prefix + self.suffix):
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
366 self.scale = 1000.0
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
367 else:
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
368 self.scale = 1.0
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
369
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
370 def __repr__(self):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
371 return '<%s %r>' % (type(self).__name__, self.pattern)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
372
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
373 def apply(self, value, locale, currency=None):
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
374 value *= self.scale
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
375 negative = int(value < 0)
211
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
376 if '@' in self.pattern: # Is it a siginificant digits pattern?
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
377 text = self._format_sigdig(abs(value),
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
378 self.int_precision[0],
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
379 self.int_precision[1])
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
380 if '.' in text:
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
381 a, b = text.split('.')
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
382 a = self._format_int(a, 0, 1000, locale)
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
383 if b:
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
384 b = get_decimal_symbol(locale) + b
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
385 else:
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
386 a, b = self._format_int(text, 0, 1000, locale), ''
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
387 else: # A normal number pattern
212
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
388 a, b = str(bankersround(abs(value),
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
389 self.frac_precision[1])).split('.', 1)
211
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
390 a = self._format_int(a, self.int_precision[0],
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
391 self.int_precision[1], locale)
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
392 b = self._format_frac(b, locale)
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
393 retval = u'%s%s%s%s' % (self.prefix[negative], a, b,
126
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
394 self.suffix[negative])
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
395 if u'¤' in retval:
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
396 retval = retval.replace(u'¤¤', currency.upper())
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
397 retval = retval.replace(u'¤', get_currency_symbol(currency, locale))
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
398 return retval
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
399
211
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
400 def _format_sigdig(self, value, min, max):
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
401 """Convert value to a string.
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
402
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
403 The resulting string will contain between (min, max) number of
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
404 significant digits.
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
405 """
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
406 a, b = str(float(value)).split('.', 1)
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
407 ndecimals = len(a)
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
408 if a == '0':
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
409 ndecimals = 0
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
410 while b.startswith('0'):
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
411 b = b[1:]
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
412 ndecimals -= 1
212
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
413 text = str(bankersround(value, max - ndecimals))
211
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
414 if text == '0.0':
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
415 text = a = '0'
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
416 b = ''
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
417 digits = 1
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
418 else:
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
419 a, b = text.split('.', 1)
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
420 digits = len(text.replace('.', '').lstrip('0'))
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
421 # Figure out if we need to add any trailing '0':s
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
422 if len(a) >= max and a != '0':
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
423 return a
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
424 if digits < min:
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
425 b += ('0' * (min - digits))
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
426 if b:
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
427 return '%s.%s' % (a, b)
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
428 return a
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
429
5125934e5f27 Added support for siginificant digits in number patterns.
jonas
parents: 137
diff changeset
430 def _format_int(self, value, min, max, locale):
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
431 width = len(value)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
432 if width < min:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
433 value += '0' * (min - width)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
434 gsize = self.grouping[0]
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
435 ret = ''
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
436 symbol = get_group_symbol(locale)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
437 while len(value) > gsize:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
438 ret = symbol + value[-gsize:] + ret
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
439 value = value[:-gsize]
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
440 gsize = self.grouping[1]
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
441 return value + ret
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
442
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
443 def _format_frac(self, value, locale):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
444 min, max = self.frac_precision
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
445 if max == 0 or (min == 0 and int(value) == 0):
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
446 return ''
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
447 width = len(value)
50
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
448 while len(value) > min and value[-1] == '0':
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
449 value = value[:-1]
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
450 return get_decimal_symbol(locale) + value
Copyright (C) 2012-2017 Edgewall Software