1 /* NumberFormat.java -- Formats and parses numbers
2 Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java.io.IOException;
42 import java.io.InvalidObjectException;
43 import java.io.ObjectInputStream;
44 import java.io.ObjectOutputStream;
45 import java.util.Currency;
46 import java.util.Locale;
47 import java.util.MissingResourceException;
48 import java.util.ResourceBundle;
51 * This is the abstract superclass of all classes which format and
52 * parse numeric values such as decimal numbers, integers, currency values,
53 * and percentages. These classes perform their parsing and formatting
54 * in a locale specific manner, accounting for such items as differing
55 * currency symbols and thousands separators.
57 * To create an instance of a concrete subclass of <code>NumberFormat</code>,
58 * do not call a class constructor directly. Instead, use one of the
59 * static factory methods in this class such as
60 * <code>getCurrencyInstance</code>.
62 * @author Tom Tromey (tromey@cygnus.com)
63 * @author Aaron M. Renn (arenn@urbanophile.com)
66 /* Written using "Java Class Libraries", 2nd edition, plus online
67 * API docs for JDK 1.2 from http://www.javasoft.com.
68 * Status: Believed complete and correct to 1.2, except getAvailableLocales.
70 public abstract class NumberFormat extends Format implements Cloneable
73 * This is a constant used to create a <code>FieldPosition</code> object
74 * that will return the integer portion of a formatted number.
76 public static final int INTEGER_FIELD = 0;
79 * This is a constant used to create a <code>FieldPosition</code> object
80 * that will return the fractional portion of a formatted number.
82 public static final int FRACTION_FIELD = 1;
84 public static class Field extends Format.Field
86 static final long serialVersionUID = 7494728892700160890L;
89 * Attribute set to all characters containing digits of the integer
92 public static final NumberFormat.Field INTEGER
93 = new Field("integer");
96 * Attribute set to all characters containing digits of the fractional
99 public static final NumberFormat.Field FRACTION
100 = new Field("fraction");
103 * Attribute set to all characters containing digits of the exponential
106 public static final NumberFormat.Field EXPONENT
107 = new Field("exponent");
110 * Attribute set to all characters containing a decimal separator.
112 public static final NumberFormat.Field DECIMAL_SEPARATOR
113 = new Field("decimal separator");
116 * Attribute set to all characters containing a sign (plus or minus).
118 public static final NumberFormat.Field SIGN
122 * Attribute set to all characters containing a grouping separator (e.g.
123 * a comma, a white space,...).
125 public static final NumberFormat.Field GROUPING_SEPARATOR
126 = new Field("grouping separator");
129 * Attribute set to all characters containing an exponential symbol (e.g.
132 public static final NumberFormat.Field EXPONENT_SYMBOL
133 = new Field("exponent symbol");
136 * Attribute set to all characters containing a percent symbol (e.g. '%')
138 public static final NumberFormat.Field PERCENT
139 = new Field("percent");
142 * Attribute set to all characters containing a permille symbol.
144 public static final NumberFormat.Field PERMILLE
145 = new Field("permille");
148 * Attribute set to all characters containing the currency unit.
150 public static final NumberFormat.Field CURRENCY
151 = new Field("currency");
154 * Attribute set to all characters containing the exponent sign.
156 public static final NumberFormat.Field EXPONENT_SIGN
157 = new Field("exponent sign");
160 * Private fields to register all fields contained in this descriptor.
162 private static final NumberFormat.Field[] allFields =
164 INTEGER, FRACTION, EXPONENT, DECIMAL_SEPARATOR, SIGN,
165 GROUPING_SEPARATOR, EXPONENT_SYMBOL, PERCENT,
166 PERMILLE, CURRENCY, EXPONENT_SIGN
170 * This constructor is only used by the deserializer. Without it,
171 * it would fail to construct a valid object.
179 * Create a Field instance with the specified field name.
181 * @param field_name Field name for the new Field instance.
183 protected Field(String field_name)
189 * This function is used by the deserializer to know which object
190 * to use when it encounters an encoded NumberFormat.Field in a
191 * serialization stream. If the stream is valid it should return
192 * one of the above field. In the other case we throw an exception.
194 * @return a valid official NumberFormat.Field instance.
196 * @throws InvalidObjectException if the field name is invalid.
198 protected Object readResolve() throws InvalidObjectException
200 String s = getName();
201 for (int i = 0; i < allFields.length; i++)
202 if (s.equals(allFields[i].getName()))
205 throw new InvalidObjectException("no such NumberFormat field called "
211 * This method is a specialization of the format method that performs
212 * a simple formatting of the specified <code>long</code> number.
214 * @param number The <code>long</code> to format.
216 * @return The formatted number
218 public final String format (long number)
220 StringBuffer sbuf = new StringBuffer(50);
221 format (number, sbuf, null);
222 return sbuf.toString();
225 public final StringBuffer format (Object obj, StringBuffer sbuf,
228 if (obj instanceof Number)
229 return format(((Number) obj).doubleValue(), sbuf, pos);
231 throw new IllegalArgumentException
232 ("Cannot format given Object as a Number");
236 * This method formats the specified <code>double</code> and appends it to
237 * a <code>StringBuffer</code>.
239 * @param number The <code>double</code> to format.
240 * @param sbuf The <code>StringBuffer</code> to append the formatted number
242 * @param pos The desired <code>FieldPosition</code>.
244 * @return The <code>StringBuffer</code> with the appended number.
246 public abstract StringBuffer format (double number,
247 StringBuffer sbuf, FieldPosition pos);
250 * This method formats the specified <code>long</code> and appends it to
251 * a <code>StringBuffer</code>.
253 * @param number The <code>long</code> to format.
254 * @param sbuf The <code>StringBuffer</code> to append the formatted number
256 * @param pos The desired <code>FieldPosition</code>.
258 * @return The <code>StringBuffer</code> with the appended number.
260 public abstract StringBuffer format (long number,
261 StringBuffer sbuf, FieldPosition pos);
264 * This method tests the specified object for equality against this object.
265 * This will be <code>true</code> if the following conditions are met:
268 * <li>The specified object is not <code>null</code>.
269 * <li>The specified object is an instance of <code>NumberFormat</code>.
272 * Since this method does not test much, it is highly advised that
273 * concrete subclasses override this method.
275 * @param obj The <code>Object</code> to test against equality with
278 * @return <code>true</code> if the specified object is equal to
279 * this object, <code>false</code> otherwise.
281 public boolean equals (Object obj)
283 if (! (obj instanceof NumberFormat))
285 NumberFormat nf = (NumberFormat) obj;
286 return (groupingUsed == nf.groupingUsed
287 && maximumFractionDigits == nf.maximumFractionDigits
288 && maximumIntegerDigits == nf.maximumIntegerDigits
289 && minimumFractionDigits == nf.minimumFractionDigits
290 && minimumIntegerDigits == nf.minimumIntegerDigits
291 && parseIntegerOnly == nf.parseIntegerOnly);
295 * This method returns a list of locales for which concrete instances
296 * of <code>NumberFormat</code> subclasses may be created.
298 * @return The list of available locales.
300 public static Locale[] getAvailableLocales ()
302 Locale[] list = new Locale[1];
307 private static NumberFormat computeInstance(Locale loc, String resource,
313 res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
314 loc, ClassLoader.getSystemClassLoader());
316 catch (MissingResourceException x)
323 fmt = res == null ? def : res.getString(resource);
325 catch (MissingResourceException x)
329 DecimalFormatSymbols dfs = new DecimalFormatSymbols (loc);
330 return new DecimalFormat (fmt, dfs);
334 * This method returns an instance of <code>NumberFormat</code> suitable
335 * for formatting and parsing currency values in the default locale.
337 * @return An instance of <code>NumberFormat</code> for handling currencies.
339 public static final NumberFormat getCurrencyInstance ()
341 return getCurrencyInstance (Locale.getDefault());
345 * This method returns an instance of <code>NumberFormat</code> suitable
346 * for formatting and parsing currency values in the specified locale.
348 * @return An instance of <code>NumberFormat</code> for handling currencies.
350 public static NumberFormat getCurrencyInstance (Locale loc)
354 format = computeInstance (loc, "currencyFormat", "$#,##0.00;($#,##0.00)");
355 format.setMaximumFractionDigits(format.getCurrency().getDefaultFractionDigits());
360 * This method returns a default instance for the default locale. This
361 * will be a concrete subclass of <code>NumberFormat</code>, but the
362 * actual class returned is dependent on the locale.
364 * @return An instance of the default <code>NumberFormat</code> class.
366 public static final NumberFormat getInstance ()
368 return getInstance (Locale.getDefault());
372 * This method returns a default instance for the specified locale. This
373 * will be a concrete subclass of <code>NumberFormat</code>, but the
374 * actual class returned is dependent on the locale.
376 * @param loc The desired locale.
378 * @return An instance of the default <code>NumberFormat</code> class.
380 public static NumberFormat getInstance (Locale loc)
382 // For now always return a number instance.
383 return getNumberInstance (loc);
387 * This method returns the maximum number of digits allowed in the fraction
388 * portion of a number.
390 * @return The maximum number of digits allowed in the fraction
391 * portion of a number.
393 public int getMaximumFractionDigits ()
395 return maximumFractionDigits;
399 * This method returns the maximum number of digits allowed in the integer
400 * portion of a number.
402 * @return The maximum number of digits allowed in the integer
403 * portion of a number.
405 public int getMaximumIntegerDigits ()
407 return maximumIntegerDigits;
411 * This method returns the minimum number of digits allowed in the fraction
412 * portion of a number.
414 * @return The minimum number of digits allowed in the fraction
415 * portion of a number.
417 public int getMinimumFractionDigits ()
419 return minimumFractionDigits;
423 * This method returns the minimum number of digits allowed in the integer
424 * portion of a number.
426 * @return The minimum number of digits allowed in the integer
427 * portion of a number.
429 public int getMinimumIntegerDigits ()
431 return minimumIntegerDigits;
435 * This method returns a default instance for the specified locale. This
436 * will be a concrete subclass of <code>NumberFormat</code>, but the
437 * actual class returned is dependent on the locale.
439 * @return An instance of the default <code>NumberFormat</code> class.
441 public static final NumberFormat getNumberInstance ()
443 return getNumberInstance (Locale.getDefault());
447 * This method returns a general purpose number formatting and parsing
448 * class for the default locale. This will be a concrete subclass of
449 * <code>NumberFormat</code>, but the actual class returned is dependent
452 * @return An instance of a generic number formatter for the default locale.
454 public static NumberFormat getNumberInstance (Locale loc)
456 return computeInstance (loc, "numberFormat", "#,##0.###");
460 * This method returns an integer formatting and parsing class for the
461 * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
462 * but the actual class returned is dependent on the locale.
464 * @return An instance of an integer number formatter for the default locale.
467 public static final NumberFormat getIntegerInstance()
469 return getIntegerInstance (Locale.getDefault());
473 * This method returns an integer formatting and parsing class for the
474 * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
475 * but the actual class returned is dependent on the locale.
477 * @param locale the desired locale.
479 * @return An instance of an integer number formatter for the desired locale.
482 public static NumberFormat getIntegerInstance(Locale locale)
484 NumberFormat format = computeInstance (locale, "numberFormat", "#,##0");
485 format.setMaximumFractionDigits(0);
486 format.setParseIntegerOnly (true);
491 * This method returns an instance of <code>NumberFormat</code> suitable
492 * for formatting and parsing percentage values in the default locale.
494 * @return An instance of <code>NumberFormat</code> for handling percentages.
496 public static final NumberFormat getPercentInstance ()
498 return getPercentInstance (Locale.getDefault());
502 * This method returns an instance of <code>NumberFormat</code> suitable
503 * for formatting and parsing percentage values in the specified locale.
505 * @param loc The desired locale.
507 * @return An instance of <code>NumberFormat</code> for handling percentages.
509 public static NumberFormat getPercentInstance (Locale loc)
511 return computeInstance (loc, "percentFormat", "#,##0%");
515 * This method returns a hash value for this object.
517 * @return The hash code.
519 public int hashCode ()
521 int hash = super.hashCode();
522 hash ^= (maximumFractionDigits + maximumIntegerDigits
523 + minimumFractionDigits + minimumIntegerDigits);
526 if (parseIntegerOnly)
532 * This method tests whether or not grouping is in use. Grouping is
533 * a method of marking separations in numbers, such as thousand separators
534 * in the US English locale. The grouping positions and symbols are all
535 * locale specific. As an example, with grouping disabled, the number one
536 * million would appear as "1000000". With grouping enabled, this number
537 * might appear as "1,000,000". (Both of these assume the US English
540 * @return <code>true</code> if grouping is enabled,
541 * <code>false</code> otherwise.
543 public boolean isGroupingUsed ()
549 * This method tests whether or not only integer values should be parsed.
550 * If this class is parsing only integers, parsing stops at the decimal
553 * @return <code>true</code> if only integers are parsed,
554 * <code>false</code> otherwise.
556 public boolean isParseIntegerOnly ()
558 return parseIntegerOnly;
562 * This is a default constructor for use by subclasses.
564 public NumberFormat ()
569 * This method parses the specified string into a <code>Number</code>. This
570 * will be a <code>Long</code> if possible, otherwise it will be a
571 * <code>Double</code>. If no number can be parsed, no exception is
572 * thrown. Instead, the parse position remains at its initial index.
574 * @param sourceStr The string to parse.
575 * @param pos The desired <code>ParsePosition</code>.
577 * @return The parsed <code>Number</code>
579 public abstract Number parse (String sourceStr, ParsePosition pos);
582 * This method parses the specified string into a <code>Number</code>. This
583 * will be a <code>Long</code> if possible, otherwise it will be a
584 * <code>Double</code>. If no number can be parsed, an exception will be
587 * @param sourceStr The string to parse.
589 * @return The parsed <code>Number</code>
591 * @exception ParseException If no number can be parsed.
593 public Number parse (String sourceStr) throws ParseException
595 ParsePosition pp = new ParsePosition (0);
596 Number r = parse (sourceStr, pp);
599 int index = pp.getErrorIndex();
601 index = pp.getIndex();
602 throw new ParseException ("couldn't parse number", index);
608 * This method parses the specified string into an <code>Object</code>. This
609 * will be a <code>Long</code> if possible, otherwise it will be a
610 * <code>Double</code>. If no number can be parsed, no exception is
611 * thrown. Instead, the parse position remains at its initial index.
613 * @param sourceStr The string to parse.
614 * @param pos The desired <code>ParsePosition</code>.
616 * @return The parsed <code>Object</code>
618 public final Object parseObject (String sourceStr, ParsePosition pos)
620 return parse (sourceStr, pos);
624 * This method sets the grouping behavior of this formatter. Grouping is
625 * a method of marking separations in numbers, such as thousand separators
626 * in the US English locale. The grouping positions and symbols are all
627 * locale specific. As an example, with grouping disabled, the number one
628 * million would appear as "1000000". With grouping enabled, this number
629 * might appear as "1,000,000". (Both of these assume the US English
632 * @param newValue <code>true</code> to enable grouping,
633 * <code>false</code> to disable it.
635 public void setGroupingUsed (boolean newValue)
637 groupingUsed = newValue;
641 * This method sets the maximum number of digits allowed in the fraction
642 * portion of a number to the specified value. If this is less than the
643 * current minimum allowed digits, the minimum allowed digits value will
644 * be lowered to be equal to the new maximum allowed digits value.
646 * @param digits The new maximum fraction digits value.
648 public void setMaximumFractionDigits (int digits)
650 maximumFractionDigits = digits;
651 if (getMinimumFractionDigits () > maximumFractionDigits)
652 setMinimumFractionDigits (maximumFractionDigits);
656 * This method sets the maximum number of digits allowed in the integer
657 * portion of a number to the specified value. If this is less than the
658 * current minimum allowed digits, the minimum allowed digits value will
659 * be lowered to be equal to the new maximum allowed digits value.
661 * @param digits The new maximum integer digits value.
663 public void setMaximumIntegerDigits (int digits)
665 maximumIntegerDigits = digits;
666 if (getMinimumIntegerDigits () > maximumIntegerDigits)
667 setMinimumIntegerDigits (maximumIntegerDigits);
671 * This method sets the minimum number of digits allowed in the fraction
672 * portion of a number to the specified value. If this is greater than the
673 * current maximum allowed digits, the maximum allowed digits value will
674 * be raised to be equal to the new minimum allowed digits value.
676 * @param digits The new minimum fraction digits value.
678 public void setMinimumFractionDigits (int digits)
680 minimumFractionDigits = digits;
681 if (getMaximumFractionDigits () < minimumFractionDigits)
682 setMaximumFractionDigits (minimumFractionDigits);
686 * This method sets the minimum number of digits allowed in the integer
687 * portion of a number to the specified value. If this is greater than the
688 * current maximum allowed digits, the maximum allowed digits value will
689 * be raised to be equal to the new minimum allowed digits value.
691 * @param digits The new minimum integer digits value.
693 public void setMinimumIntegerDigits (int digits)
695 minimumIntegerDigits = digits;
696 if (getMaximumIntegerDigits () < minimumIntegerDigits)
697 setMaximumIntegerDigits (minimumIntegerDigits);
701 * This method sets the parsing behavior of this object to parse only
704 * @param value <code>true</code> to parse only integers,
705 * <code>false</code> otherwise.
707 public void setParseIntegerOnly (boolean value)
709 parseIntegerOnly = value;
713 * This method is a specialization of the format method that performs
714 * a simple formatting of the specified <code>double</code> number.
716 * @param number The <code>double</code> to format.
718 * @return The formatted number
720 public final String format (double number)
722 StringBuffer sbuf = new StringBuffer(50);
723 format (number, sbuf, null);
724 return sbuf.toString();
727 // These field names are fixed by the serialization spec.
728 boolean groupingUsed;
729 int maximumFractionDigits;
730 private byte maxFractionDigits;
731 int maximumIntegerDigits;
732 private byte maxIntegerDigits;
733 int minimumFractionDigits;
734 private byte minFractionDigits;
735 int minimumIntegerDigits;
736 private byte minIntegerDigits;
737 boolean parseIntegerOnly;
738 private int serialVersionOnStream;
739 private static final long serialVersionUID = -2308460125733713944L;
741 private void readObject(ObjectInputStream stream)
742 throws IOException, ClassNotFoundException
744 stream.defaultReadObject();
745 if (serialVersionOnStream < 1)
747 maximumFractionDigits = maxFractionDigits;
748 maximumIntegerDigits = maxIntegerDigits;
749 minimumFractionDigits = minFractionDigits;
750 minimumIntegerDigits = minIntegerDigits;
751 serialVersionOnStream = 1;
755 private void writeObject(ObjectOutputStream stream) throws IOException
757 maxFractionDigits = maximumFractionDigits < Byte.MAX_VALUE ?
758 (byte) maximumFractionDigits : Byte.MAX_VALUE;
759 maxIntegerDigits = maximumIntegerDigits < Byte.MAX_VALUE ?
760 (byte) maximumIntegerDigits : Byte.MAX_VALUE;
761 minFractionDigits = minimumFractionDigits < Byte.MAX_VALUE ?
762 (byte) minimumFractionDigits : Byte.MAX_VALUE;
763 minIntegerDigits = minimumIntegerDigits < Byte.MAX_VALUE ?
764 (byte) minimumIntegerDigits : Byte.MAX_VALUE;
765 serialVersionOnStream = 1;
766 stream.defaultWriteObject();
770 * Returns the currency used by this number format when formatting currency
773 * The default implementation throws UnsupportedOperationException.
775 * @return The used currency object, or null.
777 * @throws UnsupportedOperationException If the number format class doesn't
778 * implement currency formatting.
782 public Currency getCurrency()
784 throw new UnsupportedOperationException();
788 * Sets the currency used by this number format when formatting currency
791 * The default implementation throws UnsupportedOperationException.
793 * @param currency The new currency to be used by this number format.
795 * @throws NullPointerException If currenc is null.
796 * @throws UnsupportedOperationException If the number format class doesn't
797 * implement currency formatting.
801 public void setCurrency(Currency currency)
803 if (currency == null)
804 throw new NullPointerException("currency may not be null");
806 throw new UnsupportedOperationException();