annotate babel/numbers.py @ 212:02f2c7b9a372

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