annotate babel/numbers.py @ 583:ae897a807442 trunk

restore Python 2.4 compatibility (broken in r634)
author fschwarz
date Sat, 04 Aug 2012 14:35:51 +0000
parents ea413a4d754b
children e0454b9c125c
rev   line source
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
2 #
530
ca203b2af83c Update the copyright line.
jruigrok
parents: 520
diff changeset
3 # Copyright (C) 2007-2011 Edgewall Software
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
4 # All rights reserved.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
5 #
245
4a5083bc9c32 Revert accidential change of file header in [260].
cmlenz
parents: 244
diff changeset
6 # This software is licensed as described in the file COPYING, which
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
8 # are also available at http://babel.edgewall.org/wiki/License.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
9 #
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://babel.edgewall.org/log/.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
13
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
14 """Locale dependent formatting and parsing of numeric data.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
15
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
16 The default locale for the functions in this module is determined by the
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
17 following environment variables, in that order:
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
18
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
19 * ``LC_NUMERIC``,
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
20 * ``LC_ALL``, and
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
21 * ``LANG``
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
22 """
246
b8390ebedc30 Updated TODO-items in number.py.
jonas
parents: 245
diff changeset
23 # TODO:
b8390ebedc30 Updated TODO-items in number.py.
jonas
parents: 245
diff changeset
24 # Padding and rounding increments in pattern:
b8390ebedc30 Updated TODO-items in number.py.
jonas
parents: 245
diff changeset
25 # - http://www.unicode.org/reports/tr35/ (Appendix G.6)
556
aa53048ad7ac remove Python 2.3 compat code for Decimal
fschwarz
parents: 530
diff changeset
26 from decimal import Decimal
243
1e5787ab265b Added initial support for scientific notation patterns.
jonas
parents: 233
diff changeset
27 import math
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
28 import re
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
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
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
31
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
32 __all__ = ['format_number', 'format_decimal', 'format_currency',
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
33 'format_percent', 'format_scientific', 'parse_number',
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
34 'parse_decimal', 'NumberFormatError']
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
35 __docformat__ = 'restructuredtext en'
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
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
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
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
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
53 def get_currency_symbol(currency, locale=LC_NUMERIC):
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
54 """Return the symbol used by the locale for the specified currency.
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
55
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
56 >>> get_currency_symbol('USD', 'en_US')
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
57 u'$'
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
58
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
59 :param currency: the currency code
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
60 :param locale: the `Locale` object or locale identifier
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
61 :return: the currency symbol
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
62 :rtype: `unicode`
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
63 """
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
64 return Locale.parse(locale).currency_symbols.get(currency, currency)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
65
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
66 def get_decimal_symbol(locale=LC_NUMERIC):
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
67 """Return the symbol used by the locale to separate decimal fractions.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
68
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
69 >>> get_decimal_symbol('en_US')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
70 u'.'
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
71
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
72 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
73 :return: the decimal symbol
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
74 :rtype: `unicode`
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
75 """
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
76 return Locale.parse(locale).number_symbols.get('decimal', u'.')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
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
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
114 def get_group_symbol(locale=LC_NUMERIC):
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
115 """Return the symbol used by the locale to separate groups of thousands.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
116
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
117 >>> get_group_symbol('en_US')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
118 u','
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
119
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
120 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
121 :return: the group symbol
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
122 :rtype: `unicode`
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
123 """
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
124 return Locale.parse(locale).number_symbols.get('group', u',')
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
125
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
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
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
128
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
129 >>> format_number(1099, locale='en_US')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
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
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
134
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
135 :param number: the number to format
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
136 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
137 :return: the formatted number
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
138 :rtype: `unicode`
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
139 """
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
140 # Do we really need this one?
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
141 return format_decimal(number, locale=locale)
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
142
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
145
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
146 >>> format_decimal(1.2345, locale='en_US')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
147 u'1.234'
50
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
148 >>> format_decimal(1.2346, locale='en_US')
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
149 u'1.235'
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
150 >>> format_decimal(-1.2346, locale='en_US')
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
151 u'-1.235'
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
152 >>> format_decimal(1.2345, locale='sv_SE')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
156
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
157 The appropriate thousands grouping and the decimal separator are used for
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
158 each locale:
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
159
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
160 >>> format_decimal(12345.5, locale='en_US')
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
161 u'12,345.5'
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
162
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
163 :param number: the number to format
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
164 :param format:
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
165 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
166 :return: the formatted decimal number
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
167 :rtype: `unicode`
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
168 """
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
169 locale = Locale.parse(locale)
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
170 if not format:
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
171 format = locale.decimal_formats.get(format)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
172 pattern = parse_pattern(format)
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
173 return pattern.apply(number, locale)
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
174
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
175 def format_currency(number, currency, format=None, locale=LC_NUMERIC):
133
32b28673cfd5 Minor doc fixes.
cmlenz
parents: 127
diff changeset
176 u"""Return formatted currency value.
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
177
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
178 >>> format_currency(1099.98, 'USD', locale='en_US')
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
179 u'$1,099.98'
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
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
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
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
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
184
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
185 The pattern can also be specified explicitly:
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
186
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
187 >>> format_currency(1099.98, 'EUR', u'\xa4\xa4 #,##0.00', locale='en_US')
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
188 u'EUR 1,099.98'
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
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
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
191 :param currency: the currency code
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
192 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
193 :return: the formatted currency value
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
194 :rtype: `unicode`
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
195 """
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
196 locale = Locale.parse(locale)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
197 if not format:
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
198 format = locale.currency_formats.get(format)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
199 pattern = parse_pattern(format)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
200 return pattern.apply(number, locale, currency=currency)
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
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
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
204
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
205 >>> format_percent(0.34, locale='en_US')
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
206 u'34%'
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
207 >>> format_percent(25.1234, locale='en_US')
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
208 u'2,512%'
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
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
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
211
126
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
212 The format pattern can also be specified explicitly:
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
213
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
214 >>> format_percent(25.1234, u'#,##0\u2030', locale='en_US')
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
215 u'25,123\u2030'
823bc6c83b88 Add test for permille number format.
cmlenz
parents: 125
diff changeset
216
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
217 :param number: the percent number to format
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
218 :param format:
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
219 :param locale: the `Locale` object or locale identifier
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
220 :return: the formatted percent number
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
221 :rtype: `unicode`
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
222 """
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
223 locale = Locale.parse(locale)
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
224 if not format:
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
225 format = locale.percent_formats.get(format)
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
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
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
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
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
251
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
252
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
253 class NumberFormatError(ValueError):
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
254 """Exception raised when a string cannot be parsed into a number."""
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
255
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
256
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
257 def parse_number(string, locale=LC_NUMERIC):
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
258 """Parse localized number string into a long integer.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
259
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
260 >>> parse_number('1,099', locale='en_US')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
261 1099L
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
262 >>> parse_number('1.099', locale='de_DE')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
263 1099L
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
264
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
265 When the given string cannot be parsed, an exception is raised:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
266
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
267 >>> parse_number('1.099,98', locale='de')
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
268 Traceback (most recent call last):
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
269 ...
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
270 NumberFormatError: '1.099,98' is not a valid number
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
271
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
272 :param string: the string to parse
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
273 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
274 :return: the parsed number
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
275 :rtype: `long`
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
276 :raise `NumberFormatError`: if the string can not be converted to a number
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
277 """
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
278 try:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
279 return long(string.replace(get_group_symbol(locale), ''))
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
280 except ValueError:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
281 raise NumberFormatError('%r is not a valid number' % string)
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
282
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
283 def parse_decimal(string, locale=LC_NUMERIC):
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
284 """Parse localized decimal string into a float.
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
285
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
286 >>> parse_decimal('1,099.98', locale='en_US')
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
287 1099.98
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
288 >>> parse_decimal('1.099,98', locale='de')
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
289 1099.98
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
290
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
291 When the given string cannot be parsed, an exception is raised:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
292
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
293 >>> parse_decimal('2,109,998', locale='de')
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
294 Traceback (most recent call last):
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
295 ...
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
296 NumberFormatError: '2,109,998' is not a valid decimal number
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
297
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
298 :param string: the string to parse
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
299 :param locale: the `Locale` object or locale identifier
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
300 :return: the parsed decimal number
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
301 :rtype: `float`
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
302 :raise `NumberFormatError`: if the string can not be converted to a
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
303 decimal number
1
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
304 """
7870274479f5 Import of initial code base.
cmlenz
parents:
diff changeset
305 locale = Locale.parse(locale)
32
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
306 try:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
307 return float(string.replace(get_group_symbol(locale), '')
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
308 .replace(get_decimal_symbol(locale), '.'))
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
309 except ValueError:
ac0957a8fd8b Started docs on number formatting/parsing.
cmlenz
parents: 26
diff changeset
310 raise NumberFormatError('%r is not a valid decimal number' % string)
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
311
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
312
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
315
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
316 PREFIX_PATTERN = r"(?P<prefix>(?:'[^']*'|%s)*)" % PREFIX_END
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
317 NUMBER_PATTERN = r"(?P<number>%s+)" % NUMBER_TOKEN
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
318 SUFFIX_PATTERN = r"(?P<suffix>.*)"
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
319
127
1bf549a5dc1c Add a couple of CLI tests.
cmlenz
parents: 126
diff changeset
320 number_re = re.compile(r"%s%s%s" % (PREFIX_PATTERN, NUMBER_PATTERN,
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
321 SUFFIX_PATTERN))
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
322
218
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
323 def split_number(value):
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
324 """Convert a number into a (intasstring, fractionasstring) tuple"""
556
aa53048ad7ac remove Python 2.3 compat code for Decimal
fschwarz
parents: 530
diff changeset
325 if isinstance(value, Decimal):
580
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
326 # NB can't just do text = str(value) as str repr of Decimal may be
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
327 # in scientific notation, e.g. for small numbers.
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
328
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
329 sign, digits, exp = value.as_tuple()
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
330 # build list of digits in reverse order, then reverse+join
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
331 # as per http://docs.python.org/library/decimal.html#recipes
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
332 int_part = []
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
333 frac_part = []
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
334
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
335 digits = map(str, digits)
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
336
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
337 # get figures after decimal point
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
338 for i in range(-exp):
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
339 # add digit if available, else 0
583
ae897a807442 restore Python 2.4 compatibility (broken in r634)
fschwarz
parents: 580
diff changeset
340 if digits:
ae897a807442 restore Python 2.4 compatibility (broken in r634)
fschwarz
parents: 580
diff changeset
341 frac_part.append(digits.pop())
ae897a807442 restore Python 2.4 compatibility (broken in r634)
fschwarz
parents: 580
diff changeset
342 else:
ae897a807442 restore Python 2.4 compatibility (broken in r634)
fschwarz
parents: 580
diff changeset
343 frac_part.append('0')
580
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
344
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
345 # add in some zeroes...
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
346 for i in range(exp):
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
347 int_part.append('0')
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
348
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
349 # and the rest
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
350 while digits:
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
351 int_part.append(digits.pop())
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
352
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
353 # if < 1, int_part must be set to '0'
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
354 if len(int_part) == 0:
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
355 int_part = '0',
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
356
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
357 if sign:
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
358 int_part.append('-')
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
359
ea413a4d754b fix format_decimal() with small Decimal values (#214, patch from George Lund)
fschwarz
parents: 576
diff changeset
360 return ''.join(reversed(int_part)), ''.join(reversed(frac_part))
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
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
362 if '.' in text:
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
363 a, b = text.split('.', 1)
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
364 if b == '0':
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
365 b = ''
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
366 else:
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
367 a, b = text, ''
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
368 return a, b
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
369
212
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
370 def bankersround(value, ndigits=0):
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
371 """Round a number to a given precision.
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
372
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
373 Works like round() except that the round-half-even (banker's rounding)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
374 algorithm is used instead of round-half-up.
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
375
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
376 >>> bankersround(5.5, 0)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
377 6.0
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
378 >>> bankersround(6.5, 0)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
379 6.0
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
380 >>> bankersround(-6.5, 0)
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
381 -6.0
218
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
382 >>> bankersround(1234.0, -2)
212
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
383 1200.0
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
384 """
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
385 sign = int(value < 0) and -1 or 1
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
386 value = abs(value)
218
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
387 a, b = split_number(value)
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
388 digits = a + b
212
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
389 add = 0
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
390 i = len(a) + ndigits
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
391 if i < 0 or i >= len(digits):
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
392 pass
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
393 elif digits[i] > '5':
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
394 add = 1
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
395 elif digits[i] == '5' and digits[i-1] in '13579':
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
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
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
404 scale = 10**ndigits
556
aa53048ad7ac remove Python 2.3 compat code for Decimal
fschwarz
parents: 530
diff changeset
405 if isinstance(value, Decimal):
218
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
406 return Decimal(int(value * scale + add)) / scale * sign
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
407 else:
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
408 return float(int(value * scale + add)) / scale * sign
212
2b0b9bb94660 Switched to using our own round() implementation.
jonas
parents: 211
diff changeset
409
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
410 def parse_pattern(pattern):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
411 """Parse number format patterns"""
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
412 if isinstance(pattern, NumberPattern):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
413 return pattern
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
414
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
415 # Do we have a negative subpattern?
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
416 if ';' in pattern:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
417 pattern, neg_pattern = pattern.split(';', 1)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
418 pos_prefix, number, pos_suffix = number_re.search(pattern).groups()
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
419 neg_prefix, _, neg_suffix = number_re.search(neg_pattern).groups()
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
420 else:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
421 pos_prefix, number, pos_suffix = number_re.search(pattern).groups()
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
422 neg_prefix = '-' + pos_prefix
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
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
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
434 else:
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
435 integer = number
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
436 fraction = ''
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
437
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
438 def parse_precision(p):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
439 """Calculate the min and max allowed digits"""
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
440 min = max = 0
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
443 min += 1
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
444 max += 1
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
445 elif c == '#':
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
449 else:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
450 break
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
451 return min, max
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
452
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
453 def parse_grouping(p):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
454 """Parse primary and secondary digit grouping
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
455
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
456 >>> parse_grouping('##')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
457 0, 0
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
458 >>> parse_grouping('#,###')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
459 3, 3
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
460 >>> parse_grouping('#,####,###')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
461 3, 4
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
462 """
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
463 width = len(p)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
464 g1 = p.rfind(',')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
465 if g1 == -1:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
466 return 1000, 1000
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
467 g1 = width - g1 - 1
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
468 g2 = p[:-g1 - 1].rfind(',')
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
469 if g2 == -1:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
470 return g1, g1
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
471 g2 = width - g1 - g2 - 2
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
472 return g1, g2
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
484 grouping = parse_grouping(integer)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
485 return NumberPattern(pattern, (pos_prefix, neg_prefix),
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
489
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
490
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
491 class NumberPattern(object):
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
492
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
495 self.pattern = pattern
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
496 self.prefix = prefix
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
497 self.suffix = suffix
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
503 if '%' in ''.join(self.prefix + self.suffix):
218
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
504 self.scale = 100
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
505 elif u'‰' in ''.join(self.prefix + self.suffix):
218
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
506 self.scale = 1000
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
507 else:
218
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
508 self.scale = 1
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
509
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
510 def __repr__(self):
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
511 return '<%s %r>' % (type(self).__name__, self.pattern)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
512
125
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
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
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
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
ce1f9919f8c9 Fix scientific notation for 0. closes #99
aronacher
parents: 246
diff changeset
520 if value:
ce1f9919f8c9 Fix scientific notation for 0. closes #99
aronacher
parents: 246
diff changeset
521 exp = int(math.floor(math.log(value, 10)))
ce1f9919f8c9 Fix scientific notation for 0. closes #99
aronacher
parents: 246
diff changeset
522 else:
ce1f9919f8c9 Fix scientific notation for 0. closes #99
aronacher
parents: 246
diff changeset
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
aa53048ad7ac remove Python 2.3 compat code for Decimal
fschwarz
parents: 530
diff changeset
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
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
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
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
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
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
570 if u'¤' in retval:
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
571 retval = retval.replace(u'¤¤', currency.upper())
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
572 retval = retval.replace(u'¤', get_currency_symbol(currency, locale))
061ea0e0ac8c Add currency formatting.
cmlenz
parents: 101
diff changeset
573 return retval
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
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
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
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
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
588 a, b = split_number(bankersround(value, max - ndecimals))
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
589 digits = len((a + b).lstrip('0'))
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
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
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
602 width = len(value)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
605 gsize = self.grouping[0]
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
606 ret = ''
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
607 symbol = get_group_symbol(locale)
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
608 while len(value) > gsize:
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
609 ret = symbol + value[-gsize:] + ret
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
610 value = value[:-gsize]
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
611 gsize = self.grouping[1]
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
612 return value + ret
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
613
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
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
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
616 if len(value) < min:
cc699743ec06 Added Decimal support to the number formatter.
jonas
parents: 212
diff changeset
617 value += ('0' * (min - len(value)))
22
d1e6944f2ff0 Implemented babel.numbers.format_percent
jonas
parents: 9
diff changeset
618 if max == 0 or (min == 0 and int(value) == 0):
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
619 return ''
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
620 width = len(value)
50
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
621 while len(value) > min and value[-1] == '0':
0896af2c49ec Added round-half-even (banker's rounding) support.
jonas
parents: 39
diff changeset
622 value = value[:-1]
9
9ed6cf5975a1 Add basic support for number format patterns.
jonas
parents: 1
diff changeset
623 return get_decimal_symbol(locale) + value
Copyright (C) 2012-2017 Edgewall Software