Mercurial > babel > mirror
annotate babel/numbers.py @ 584:e0454b9c125c trunk
fix indentation in split_number
author | fschwarz |
---|---|
date | Sat, 04 Aug 2012 20:22:49 +0000 |
parents | ae897a807442 |
children | 964cd2ec6f94 |
rev | line source |
---|---|
1 | 1 # -*- coding: utf-8 -*- |
2 # | |
530 | 3 # Copyright (C) 2007-2011 Edgewall Software |
1 | 4 # All rights reserved. |
5 # | |
245 | 6 # This software is licensed as described in the file COPYING, which |
1 | 7 # you should have received as part of this distribution. The terms |
8 # are also available at http://babel.edgewall.org/wiki/License. | |
9 # | |
10 # This software consists of voluntary contributions made by many | |
11 # individuals. For the exact contribution history, see the revision | |
12 # history and logs, available at http://babel.edgewall.org/log/. | |
13 | |
14 """Locale dependent formatting and parsing of numeric data. | |
15 | |
16 The default locale for the functions in this module is determined by the | |
17 following environment variables, in that order: | |
18 | |
19 * ``LC_NUMERIC``, | |
20 * ``LC_ALL``, and | |
21 * ``LANG`` | |
22 """ | |
246 | 23 # TODO: |
24 # Padding and rounding increments in pattern: | |
25 # - http://www.unicode.org/reports/tr35/ (Appendix G.6) | |
556 | 26 from decimal import Decimal |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
27 import math |
1 | 28 import re |
29 | |
72
e0bb7dce49ea
More explicit module-level function names in `babel.core`. Added `Locale.negotiate` class method.
cmlenz
parents:
50
diff
changeset
|
30 from babel.core import default_locale, Locale |
1 | 31 |
32 __all__ = ['format_number', 'format_decimal', 'format_currency', | |
33 'format_percent', 'format_scientific', 'parse_number', | |
32 | 34 'parse_decimal', 'NumberFormatError'] |
1 | 35 __docformat__ = 'restructuredtext en' |
36 | |
72
e0bb7dce49ea
More explicit module-level function names in `babel.core`. Added `Locale.negotiate` class method.
cmlenz
parents:
50
diff
changeset
|
37 LC_NUMERIC = default_locale('LC_NUMERIC') |
1 | 38 |
385
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
39 def get_currency_name(currency, locale=LC_NUMERIC): |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
40 """Return the name used by the locale for the specified currency. |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
41 |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
42 >>> get_currency_name('USD', 'en_US') |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
43 u'US Dollar' |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
44 |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
45 :param currency: the currency code |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
46 :param locale: the `Locale` object or locale identifier |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
47 :return: the currency symbol |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
48 :rtype: `unicode` |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
49 :since: version 0.9.4 |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
50 """ |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
51 return Locale.parse(locale).currencies.get(currency, currency) |
38db48990998
Improve CLDR import of currency-related data to ignore unsupported features such as symbol choice patterns and pluralized display names. See #93.
cmlenz
parents:
375
diff
changeset
|
52 |
125 | 53 def get_currency_symbol(currency, locale=LC_NUMERIC): |
54 """Return the symbol used by the locale for the specified currency. | |
55 | |
56 >>> get_currency_symbol('USD', 'en_US') | |
57 u'$' | |
58 | |
59 :param currency: the currency code | |
60 :param locale: the `Locale` object or locale identifier | |
61 :return: the currency symbol | |
62 :rtype: `unicode` | |
63 """ | |
64 return Locale.parse(locale).currency_symbols.get(currency, currency) | |
65 | |
1 | 66 def get_decimal_symbol(locale=LC_NUMERIC): |
67 """Return the symbol used by the locale to separate decimal fractions. | |
68 | |
69 >>> get_decimal_symbol('en_US') | |
70 u'.' | |
71 | |
72 :param locale: the `Locale` object or locale identifier | |
73 :return: the decimal symbol | |
74 :rtype: `unicode` | |
75 """ | |
76 return Locale.parse(locale).number_symbols.get('decimal', u'.') | |
77 | |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
78 def get_plus_sign_symbol(locale=LC_NUMERIC): |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
79 """Return the plus sign symbol used by the current locale. |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
80 |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
81 >>> get_plus_sign_symbol('en_US') |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
82 u'+' |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
83 |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
84 :param locale: the `Locale` object or locale identifier |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
85 :return: the plus sign symbol |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
86 :rtype: `unicode` |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
87 """ |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
88 return Locale.parse(locale).number_symbols.get('plusSign', u'+') |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
89 |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
90 def get_minus_sign_symbol(locale=LC_NUMERIC): |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
91 """Return the plus sign symbol used by the current locale. |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
92 |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
93 >>> get_minus_sign_symbol('en_US') |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
94 u'-' |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
95 |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
96 :param locale: the `Locale` object or locale identifier |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
97 :return: the plus sign symbol |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
98 :rtype: `unicode` |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
99 """ |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
100 return Locale.parse(locale).number_symbols.get('minusSign', u'-') |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
101 |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
102 def get_exponential_symbol(locale=LC_NUMERIC): |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
103 """Return the symbol used by the locale to separate mantissa and exponent. |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
104 |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
105 >>> get_exponential_symbol('en_US') |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
106 u'E' |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
107 |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
108 :param locale: the `Locale` object or locale identifier |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
109 :return: the exponential symbol |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
110 :rtype: `unicode` |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
111 """ |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
112 return Locale.parse(locale).number_symbols.get('exponential', u'E') |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
113 |
1 | 114 def get_group_symbol(locale=LC_NUMERIC): |
115 """Return the symbol used by the locale to separate groups of thousands. | |
116 | |
117 >>> get_group_symbol('en_US') | |
118 u',' | |
119 | |
120 :param locale: the `Locale` object or locale identifier | |
121 :return: the group symbol | |
122 :rtype: `unicode` | |
123 """ | |
9 | 124 return Locale.parse(locale).number_symbols.get('group', u',') |
1 | 125 |
126 def format_number(number, locale=LC_NUMERIC): | |
435
2a51e91bcfae
Add extra doctest for formatting a number in de_DE since it uses a
jruigrok
parents:
434
diff
changeset
|
127 u"""Return the given number formatted for a specific locale. |
1 | 128 |
129 >>> format_number(1099, locale='en_US') | |
130 u'1,099' | |
435
2a51e91bcfae
Add extra doctest for formatting a number in de_DE since it uses a
jruigrok
parents:
434
diff
changeset
|
131 >>> format_number(1099, locale='de_DE') |
437
64155e929c84
Revert part of the commits with relation to the de locale's use of \xa0 as
jruigrok
parents:
435
diff
changeset
|
132 u'1.099' |
435
2a51e91bcfae
Add extra doctest for formatting a number in de_DE since it uses a
jruigrok
parents:
434
diff
changeset
|
133 |
1 | 134 |
135 :param number: the number to format | |
136 :param locale: the `Locale` object or locale identifier | |
137 :return: the formatted number | |
138 :rtype: `unicode` | |
139 """ | |
9 | 140 # Do we really need this one? |
141 return format_decimal(number, locale=locale) | |
1 | 142 |
9 | 143 def format_decimal(number, format=None, locale=LC_NUMERIC): |
434
b3135adf1079
Adjust tests to match the data in CLDR: German doesn't use a . as thousands
jruigrok
parents:
414
diff
changeset
|
144 u"""Return the given decimal number formatted for a specific locale. |
1 | 145 |
9 | 146 >>> format_decimal(1.2345, locale='en_US') |
147 u'1.234' | |
50 | 148 >>> format_decimal(1.2346, locale='en_US') |
149 u'1.235' | |
150 >>> format_decimal(-1.2346, locale='en_US') | |
151 u'-1.235' | |
9 | 152 >>> format_decimal(1.2345, locale='sv_SE') |
153 u'1,234' | |
437
64155e929c84
Revert part of the commits with relation to the de locale's use of \xa0 as
jruigrok
parents:
435
diff
changeset
|
154 >>> format_decimal(1.2345, locale='de') |
64155e929c84
Revert part of the commits with relation to the de locale's use of \xa0 as
jruigrok
parents:
435
diff
changeset
|
155 u'1,234' |
9 | 156 |
1 | 157 The appropriate thousands grouping and the decimal separator are used for |
158 each locale: | |
159 | |
125 | 160 >>> format_decimal(12345.5, locale='en_US') |
161 u'12,345.5' | |
9 | 162 |
1 | 163 :param number: the number to format |
9 | 164 :param format: |
1 | 165 :param locale: the `Locale` object or locale identifier |
166 :return: the formatted decimal number | |
167 :rtype: `unicode` | |
168 """ | |
169 locale = Locale.parse(locale) | |
125 | 170 if not format: |
171 format = locale.decimal_formats.get(format) | |
172 pattern = parse_pattern(format) | |
9 | 173 return pattern.apply(number, locale) |
1 | 174 |
125 | 175 def format_currency(number, currency, format=None, locale=LC_NUMERIC): |
133 | 176 u"""Return formatted currency value. |
1 | 177 |
32 | 178 >>> format_currency(1099.98, 'USD', locale='en_US') |
125 | 179 u'$1,099.98' |
180 >>> format_currency(1099.98, 'USD', locale='es_CO') | |
375
4eca63af0a12
Implement support for aliases in the CLDR data. Closes #68. Also, update to CLDR 1.6, and a much improved `dump_data` script.
cmlenz
parents:
357
diff
changeset
|
181 u'US$\\xa01.099,98' |
125 | 182 >>> format_currency(1099.98, 'EUR', locale='de_DE') |
437
64155e929c84
Revert part of the commits with relation to the de locale's use of \xa0 as
jruigrok
parents:
435
diff
changeset
|
183 u'1.099,98\\xa0\\u20ac' |
125 | 184 |
185 The pattern can also be specified explicitly: | |
186 | |
187 >>> format_currency(1099.98, 'EUR', u'\xa4\xa4 #,##0.00', locale='en_US') | |
188 u'EUR 1,099.98' | |
1 | 189 |
26
6041782ea677
* Reduce size of locale data pickles by only storing the data provided by each locale itself, and merging inherited data at runtime.
cmlenz
parents:
22
diff
changeset
|
190 :param number: the number to format |
32 | 191 :param currency: the currency code |
1 | 192 :param locale: the `Locale` object or locale identifier |
193 :return: the formatted currency value | |
194 :rtype: `unicode` | |
195 """ | |
125 | 196 locale = Locale.parse(locale) |
197 if not format: | |
198 format = locale.currency_formats.get(format) | |
199 pattern = parse_pattern(format) | |
200 return pattern.apply(number, locale, currency=currency) | |
1 | 201 |
26
6041782ea677
* Reduce size of locale data pickles by only storing the data provided by each locale itself, and merging inherited data at runtime.
cmlenz
parents:
22
diff
changeset
|
202 def format_percent(number, format=None, locale=LC_NUMERIC): |
101
0f641136aa6b
Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents:
72
diff
changeset
|
203 """Return formatted percent value for a specific locale. |
22 | 204 |
205 >>> format_percent(0.34, locale='en_US') | |
206 u'34%' | |
207 >>> format_percent(25.1234, locale='en_US') | |
208 u'2,512%' | |
209 >>> format_percent(25.1234, locale='sv_SE') | |
233
da97a3138239
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
218
diff
changeset
|
210 u'2\\xa0512\\xa0%' |
22 | 211 |
126 | 212 The format pattern can also be specified explicitly: |
213 | |
214 >>> format_percent(25.1234, u'#,##0\u2030', locale='en_US') | |
215 u'25,123\u2030' | |
216 | |
22 | 217 :param number: the percent number to format |
218 :param format: | |
219 :param locale: the `Locale` object or locale identifier | |
220 :return: the formatted percent number | |
221 :rtype: `unicode` | |
222 """ | |
223 locale = Locale.parse(locale) | |
125 | 224 if not format: |
225 format = locale.percent_formats.get(format) | |
226 pattern = parse_pattern(format) | |
26
6041782ea677
* Reduce size of locale data pickles by only storing the data provided by each locale itself, and merging inherited data at runtime.
cmlenz
parents:
22
diff
changeset
|
227 return pattern.apply(number, locale) |
1 | 228 |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
229 def format_scientific(number, format=None, locale=LC_NUMERIC): |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
230 """Return value formatted in scientific notation for a specific locale. |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
231 |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
232 >>> format_scientific(10000, locale='en_US') |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
233 u'1E4' |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
234 |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
235 The format pattern can also be specified explicitly: |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
236 |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
237 >>> format_scientific(1234567, u'##0E00', locale='en_US') |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
238 u'1.23E06' |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
239 |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
240 :param number: the number to format |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
241 :param format: |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
242 :param locale: the `Locale` object or locale identifier |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
243 :return: value formatted in scientific notation. |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
244 :rtype: `unicode` |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
245 """ |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
246 locale = Locale.parse(locale) |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
247 if not format: |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
248 format = locale.scientific_formats.get(format) |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
249 pattern = parse_pattern(format) |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
250 return pattern.apply(number, locale) |
1 | 251 |
32 | 252 |
253 class NumberFormatError(ValueError): | |
254 """Exception raised when a string cannot be parsed into a number.""" | |
255 | |
256 | |
1 | 257 def parse_number(string, locale=LC_NUMERIC): |
258 """Parse localized number string into a long integer. | |
259 | |
260 >>> parse_number('1,099', locale='en_US') | |
261 1099L | |
262 >>> parse_number('1.099', locale='de_DE') | |
263 1099L | |
264 | |
32 | 265 When the given string cannot be parsed, an exception is raised: |
266 | |
267 >>> parse_number('1.099,98', locale='de') | |
268 Traceback (most recent call last): | |
269 ... | |
270 NumberFormatError: '1.099,98' is not a valid number | |
271 | |
1 | 272 :param string: the string to parse |
273 :param locale: the `Locale` object or locale identifier | |
274 :return: the parsed number | |
275 :rtype: `long` | |
32 | 276 :raise `NumberFormatError`: if the string can not be converted to a number |
1 | 277 """ |
32 | 278 try: |
279 return long(string.replace(get_group_symbol(locale), '')) | |
280 except ValueError: | |
281 raise NumberFormatError('%r is not a valid number' % string) | |
1 | 282 |
283 def parse_decimal(string, locale=LC_NUMERIC): | |
284 """Parse localized decimal string into a float. | |
285 | |
286 >>> parse_decimal('1,099.98', locale='en_US') | |
287 1099.98 | |
32 | 288 >>> parse_decimal('1.099,98', locale='de') |
1 | 289 1099.98 |
290 | |
32 | 291 When the given string cannot be parsed, an exception is raised: |
292 | |
293 >>> parse_decimal('2,109,998', locale='de') | |
294 Traceback (most recent call last): | |
295 ... | |
296 NumberFormatError: '2,109,998' is not a valid decimal number | |
297 | |
1 | 298 :param string: the string to parse |
299 :param locale: the `Locale` object or locale identifier | |
300 :return: the parsed decimal number | |
301 :rtype: `float` | |
32 | 302 :raise `NumberFormatError`: if the string can not be converted to a |
303 decimal number | |
1 | 304 """ |
305 locale = Locale.parse(locale) | |
32 | 306 try: |
307 return float(string.replace(get_group_symbol(locale), '') | |
308 .replace(get_decimal_symbol(locale), '.')) | |
309 except ValueError: | |
310 raise NumberFormatError('%r is not a valid decimal number' % string) | |
9 | 311 |
312 | |
313 PREFIX_END = r'[^0-9@#.,]' | |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
314 NUMBER_TOKEN = r'[0-9@#.\-,E+]' |
9 | 315 |
316 PREFIX_PATTERN = r"(?P<prefix>(?:'[^']*'|%s)*)" % PREFIX_END | |
317 NUMBER_PATTERN = r"(?P<number>%s+)" % NUMBER_TOKEN | |
318 SUFFIX_PATTERN = r"(?P<suffix>.*)" | |
319 | |
127 | 320 number_re = re.compile(r"%s%s%s" % (PREFIX_PATTERN, NUMBER_PATTERN, |
9 | 321 SUFFIX_PATTERN)) |
322 | |
218 | 323 def split_number(value): |
324 """Convert a number into a (intasstring, fractionasstring) tuple""" | |
556 | 325 if isinstance(value, Decimal): |
584 | 326 # NB can't just do text = str(value) as str repr of Decimal may be |
327 # in scientific notation, e.g. for small numbers. | |
328 | |
329 sign, digits, exp = value.as_tuple() | |
330 # build list of digits in reverse order, then reverse+join | |
331 # as per http://docs.python.org/library/decimal.html#recipes | |
332 int_part = [] | |
333 frac_part = [] | |
334 | |
335 digits = map(str, digits) | |
336 | |
337 # get figures after decimal point | |
338 for i in range(-exp): | |
339 # add digit if available, else 0 | |
340 if digits: | |
341 frac_part.append(digits.pop()) | |
342 else: | |
343 frac_part.append('0') | |
344 | |
345 # add in some zeroes... | |
346 for i in range(exp): | |
347 int_part.append('0') | |
348 | |
349 # and the rest | |
350 while digits: | |
351 int_part.append(digits.pop()) | |
352 | |
353 # if < 1, int_part must be set to '0' | |
354 if len(int_part) == 0: | |
355 int_part = '0', | |
356 | |
357 if sign: | |
358 int_part.append('-') | |
359 | |
360 return ''.join(reversed(int_part)), ''.join(reversed(frac_part)) | |
580
ea413a4d754b
fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents:
576
diff
changeset
|
361 text = ('%.9f' % value).rstrip('0') |
218 | 362 if '.' in text: |
363 a, b = text.split('.', 1) | |
364 if b == '0': | |
365 b = '' | |
366 else: | |
367 a, b = text, '' | |
368 return a, b | |
369 | |
212 | 370 def bankersround(value, ndigits=0): |
371 """Round a number to a given precision. | |
372 | |
373 Works like round() except that the round-half-even (banker's rounding) | |
374 algorithm is used instead of round-half-up. | |
375 | |
376 >>> bankersround(5.5, 0) | |
377 6.0 | |
378 >>> bankersround(6.5, 0) | |
379 6.0 | |
380 >>> bankersround(-6.5, 0) | |
381 -6.0 | |
218 | 382 >>> bankersround(1234.0, -2) |
212 | 383 1200.0 |
384 """ | |
385 sign = int(value < 0) and -1 or 1 | |
386 value = abs(value) | |
218 | 387 a, b = split_number(value) |
388 digits = a + b | |
212 | 389 add = 0 |
390 i = len(a) + ndigits | |
391 if i < 0 or i >= len(digits): | |
392 pass | |
393 elif digits[i] > '5': | |
394 add = 1 | |
395 elif digits[i] == '5' and digits[i-1] in '13579': | |
396 add = 1 | |
557
4e561e6411ba
Only use bankers round algorithm as a tie breaker if there are two nearest numbers, round as usual if there is only one nearest number (#267, patch by Martin)
fschwarz
parents:
556
diff
changeset
|
397 elif digits[i] == '5': # previous digit is even |
4e561e6411ba
Only use bankers round algorithm as a tie breaker if there are two nearest numbers, round as usual if there is only one nearest number (#267, patch by Martin)
fschwarz
parents:
556
diff
changeset
|
398 # We round up unless all following digits are zero. |
4e561e6411ba
Only use bankers round algorithm as a tie breaker if there are two nearest numbers, round as usual if there is only one nearest number (#267, patch by Martin)
fschwarz
parents:
556
diff
changeset
|
399 for j in xrange(i + 1, len(digits)): |
4e561e6411ba
Only use bankers round algorithm as a tie breaker if there are two nearest numbers, round as usual if there is only one nearest number (#267, patch by Martin)
fschwarz
parents:
556
diff
changeset
|
400 if digits[j] != '0': |
4e561e6411ba
Only use bankers round algorithm as a tie breaker if there are two nearest numbers, round as usual if there is only one nearest number (#267, patch by Martin)
fschwarz
parents:
556
diff
changeset
|
401 add = 1 |
4e561e6411ba
Only use bankers round algorithm as a tie breaker if there are two nearest numbers, round as usual if there is only one nearest number (#267, patch by Martin)
fschwarz
parents:
556
diff
changeset
|
402 break |
4e561e6411ba
Only use bankers round algorithm as a tie breaker if there are two nearest numbers, round as usual if there is only one nearest number (#267, patch by Martin)
fschwarz
parents:
556
diff
changeset
|
403 |
218 | 404 scale = 10**ndigits |
556 | 405 if isinstance(value, Decimal): |
218 | 406 return Decimal(int(value * scale + add)) / scale * sign |
407 else: | |
408 return float(int(value * scale + add)) / scale * sign | |
212 | 409 |
9 | 410 def parse_pattern(pattern): |
411 """Parse number format patterns""" | |
412 if isinstance(pattern, NumberPattern): | |
413 return pattern | |
414 | |
415 # Do we have a negative subpattern? | |
416 if ';' in pattern: | |
417 pattern, neg_pattern = pattern.split(';', 1) | |
418 pos_prefix, number, pos_suffix = number_re.search(pattern).groups() | |
419 neg_prefix, _, neg_suffix = number_re.search(neg_pattern).groups() | |
420 else: | |
421 pos_prefix, number, pos_suffix = number_re.search(pattern).groups() | |
422 neg_prefix = '-' + pos_prefix | |
423 neg_suffix = pos_suffix | |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
424 if 'E' in number: |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
425 number, exp = number.split('E', 1) |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
426 else: |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
427 exp = None |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
428 if '@' in number: |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
429 if '.' in number and '0' in number: |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
430 raise ValueError('Significant digit patterns can not contain ' |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
431 '"@" or "0"') |
22 | 432 if '.' in number: |
520
c76f397343d7
Just use the rsplit() since we do not need to support 2.3 in trunk.
jruigrok
parents:
437
diff
changeset
|
433 integer, fraction = number.rsplit('.', 1) |
22 | 434 else: |
435 integer = number | |
436 fraction = '' | |
9 | 437 |
438 def parse_precision(p): | |
439 """Calculate the min and max allowed digits""" | |
440 min = max = 0 | |
441 for c in p: | |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
442 if c in '@0': |
9 | 443 min += 1 |
444 max += 1 | |
445 elif c == '#': | |
446 max += 1 | |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
447 elif c == ',': |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
448 continue |
9 | 449 else: |
450 break | |
451 return min, max | |
452 | |
453 def parse_grouping(p): | |
454 """Parse primary and secondary digit grouping | |
455 | |
456 >>> parse_grouping('##') | |
457 0, 0 | |
458 >>> parse_grouping('#,###') | |
459 3, 3 | |
460 >>> parse_grouping('#,####,###') | |
461 3, 4 | |
462 """ | |
463 width = len(p) | |
464 g1 = p.rfind(',') | |
465 if g1 == -1: | |
466 return 1000, 1000 | |
467 g1 = width - g1 - 1 | |
468 g2 = p[:-g1 - 1].rfind(',') | |
469 if g2 == -1: | |
470 return g1, g1 | |
471 g2 = width - g1 - g2 - 2 | |
472 return g1, g2 | |
473 | |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
474 int_prec = parse_precision(integer) |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
475 frac_prec = parse_precision(fraction) |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
476 if exp: |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
477 frac_prec = parse_precision(integer+fraction) |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
478 exp_plus = exp.startswith('+') |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
479 exp = exp.lstrip('+') |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
480 exp_prec = parse_precision(exp) |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
481 else: |
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
482 exp_plus = None |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
483 exp_prec = None |
9 | 484 grouping = parse_grouping(integer) |
485 return NumberPattern(pattern, (pos_prefix, neg_prefix), | |
486 (pos_suffix, neg_suffix), grouping, | |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
487 int_prec, frac_prec, |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
488 exp_prec, exp_plus) |
9 | 489 |
490 | |
491 class NumberPattern(object): | |
22 | 492 |
9 | 493 def __init__(self, pattern, prefix, suffix, grouping, |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
494 int_prec, frac_prec, exp_prec, exp_plus): |
9 | 495 self.pattern = pattern |
496 self.prefix = prefix | |
497 self.suffix = suffix | |
498 self.grouping = grouping | |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
499 self.int_prec = int_prec |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
500 self.frac_prec = frac_prec |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
501 self.exp_prec = exp_prec |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
502 self.exp_plus = exp_plus |
22 | 503 if '%' in ''.join(self.prefix + self.suffix): |
218 | 504 self.scale = 100 |
22 | 505 elif u'‰' in ''.join(self.prefix + self.suffix): |
218 | 506 self.scale = 1000 |
22 | 507 else: |
218 | 508 self.scale = 1 |
9 | 509 |
510 def __repr__(self): | |
511 return '<%s %r>' % (type(self).__name__, self.pattern) | |
512 | |
125 | 513 def apply(self, value, locale, currency=None): |
576
e77dd06c40ef
fix formatting of fraction in format_decimal() if the input value is a float with more than 7 significant digits (#183)
fschwarz
parents:
568
diff
changeset
|
514 if isinstance(value, float): |
e77dd06c40ef
fix formatting of fraction in format_decimal() if the input value is a float with more than 7 significant digits (#183)
fschwarz
parents:
568
diff
changeset
|
515 value = Decimal(str(value)) |
22 | 516 value *= self.scale |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
517 is_negative = int(value < 0) |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
518 if self.exp_prec: # Scientific notation |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
519 value = abs(value) |
357 | 520 if value: |
521 exp = int(math.floor(math.log(value, 10))) | |
522 else: | |
523 exp = 0 | |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
524 # Minimum number of integer digits |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
525 if self.int_prec[0] == self.int_prec[1]: |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
526 exp -= self.int_prec[0] - 1 |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
527 # Exponent grouping |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
528 elif self.int_prec[1]: |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
529 exp = int(exp) / self.int_prec[1] * self.int_prec[1] |
556 | 530 if not isinstance(value, Decimal): |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
531 value = float(value) |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
532 if exp < 0: |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
533 value = value * 10**(-exp) |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
534 else: |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
535 value = value / 10**exp |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
536 exp_sign = '' |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
537 if exp < 0: |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
538 exp_sign = get_minus_sign_symbol(locale) |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
539 elif self.exp_plus: |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
540 exp_sign = get_plus_sign_symbol(locale) |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
541 exp = abs(exp) |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
542 number = u'%s%s%s%s' % \ |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
543 (self._format_sigdig(value, self.frac_prec[0], |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
544 self.frac_prec[1]), |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
545 get_exponential_symbol(locale), exp_sign, |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
546 self._format_int(str(exp), self.exp_prec[0], |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
547 self.exp_prec[1], locale)) |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
548 elif '@' in self.pattern: # Is it a siginificant digits pattern? |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
549 text = self._format_sigdig(abs(value), |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
550 self.int_prec[0], |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
551 self.int_prec[1]) |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
552 if '.' in text: |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
553 a, b = text.split('.') |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
554 a = self._format_int(a, 0, 1000, locale) |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
555 if b: |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
556 b = get_decimal_symbol(locale) + b |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
557 number = a + b |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
558 else: |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
559 number = self._format_int(text, 0, 1000, locale) |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
560 else: # A normal number pattern |
218 | 561 a, b = split_number(bankersround(abs(value), |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
562 self.frac_prec[1])) |
218 | 563 b = b or '0' |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
564 a = self._format_int(a, self.int_prec[0], |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
565 self.int_prec[1], locale) |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
566 b = self._format_frac(b, locale) |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
567 number = a + b |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
568 retval = u'%s%s%s' % (self.prefix[is_negative], number, |
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
569 self.suffix[is_negative]) |
125 | 570 if u'¤' in retval: |
571 retval = retval.replace(u'¤¤', currency.upper()) | |
572 retval = retval.replace(u'¤', get_currency_symbol(currency, locale)) | |
573 return retval | |
9 | 574 |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
575 def _format_sigdig(self, value, min, max): |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
576 """Convert value to a string. |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
577 |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
578 The resulting string will contain between (min, max) number of |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
579 significant digits. |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
580 """ |
218 | 581 a, b = split_number(value) |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
582 ndecimals = len(a) |
218 | 583 if a == '0' and b != '': |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
584 ndecimals = 0 |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
585 while b.startswith('0'): |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
586 b = b[1:] |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
587 ndecimals -= 1 |
218 | 588 a, b = split_number(bankersround(value, max - ndecimals)) |
589 digits = len((a + b).lstrip('0')) | |
590 if not digits: | |
211
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
591 digits = 1 |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
592 # Figure out if we need to add any trailing '0':s |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
593 if len(a) >= max and a != '0': |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
594 return a |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
595 if digits < min: |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
596 b += ('0' * (min - digits)) |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
597 if b: |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
598 return '%s.%s' % (a, b) |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
599 return a |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
600 |
5125934e5f27
Added support for siginificant digits in number patterns.
jonas
parents:
137
diff
changeset
|
601 def _format_int(self, value, min, max, locale): |
9 | 602 width = len(value) |
603 if width < min: | |
243
1e5787ab265b
Added initial support for scientific notation patterns.
jonas
parents:
233
diff
changeset
|
604 value = '0' * (min - width) + value |
9 | 605 gsize = self.grouping[0] |
606 ret = '' | |
607 symbol = get_group_symbol(locale) | |
608 while len(value) > gsize: | |
609 ret = symbol + value[-gsize:] + ret | |
610 value = value[:-gsize] | |
611 gsize = self.grouping[1] | |
612 return value + ret | |
613 | |
614 def _format_frac(self, value, locale): | |
244
c24846890620
Added `Decimal` support to the scientific notation formatter and some code cleanup. This closes #52.
jonas
parents:
243
diff
changeset
|
615 min, max = self.frac_prec |
218 | 616 if len(value) < min: |
617 value += ('0' * (min - len(value))) | |
22 | 618 if max == 0 or (min == 0 and int(value) == 0): |
9 | 619 return '' |
620 width = len(value) | |
50 | 621 while len(value) > min and value[-1] == '0': |
622 value = value[:-1] | |
9 | 623 return get_decimal_symbol(locale) + value |