annotate babel/numbers.py @ 214:5f90da6265a9

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