2 *******************************************************************************
\r
3 * Copyright (C) 2007-2009, International Business Machines
\r
4 * Corporation and others. All Rights Reserved.
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.impl;
\r
9 import java.io.IOException;
\r
10 import java.io.ObjectInputStream;
\r
11 import java.math.BigInteger;
\r
12 import java.text.FieldPosition;
\r
13 import java.text.ParsePosition;
\r
15 import com.ibm.icu.lang.UCharacter;
\r
16 import com.ibm.icu.math.BigDecimal;
\r
17 import com.ibm.icu.text.NumberFormat;
\r
18 import com.ibm.icu.util.ULocale;
\r
19 import com.ibm.icu.util.UResourceBundle;
\r
22 * NumberFormat implementation dedicated/optimized for DateFormat,
\r
23 * used by SimpleDateFormat implementation.
\r
25 public final class DateNumberFormat extends NumberFormat {
\r
27 private static final long serialVersionUID = -6315692826916346953L;
\r
29 private char zeroDigit;
\r
30 private char minusSign;
\r
31 private boolean positiveOnly = false;
\r
33 private transient char[] decimalBuf = new char[20]; // 20 digits is good enough to store Long.MAX_VALUE
\r
35 private static SimpleCache<ULocale, char[]> CACHE = new SimpleCache<ULocale, char[]>();
\r
37 private int maxIntDigits;
\r
38 private int minIntDigits;
\r
40 public DateNumberFormat(ULocale loc, char zeroDigitIn) {
\r
41 initialize(loc,zeroDigitIn);
\r
44 /* public DateNumberFormat(char zeroDigit, char minusSign) {
\r
45 this.zeroDigit = zeroDigit;
\r
46 this.minusSign = minusSign;
\r
50 private void initialize(ULocale loc,char zeroDigitIn) {
\r
51 char[] elems = CACHE.get(loc);
\r
52 if (elems == null) {
\r
54 ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, loc);
\r
55 String[] numberElements = rb.getStringArray("NumberElements");
\r
56 elems = new char[2];
\r
57 elems[0] = zeroDigitIn;
\r
58 elems[1] = numberElements[6].charAt(0);
\r
59 CACHE.put(loc, elems);
\r
61 zeroDigit = elems[0];
\r
62 minusSign = elems[1];
\r
65 public void setMaximumIntegerDigits(int newValue) {
\r
66 maxIntDigits = newValue;
\r
69 public int getMaximumIntegerDigits() {
\r
70 return maxIntDigits;
\r
73 public void setMinimumIntegerDigits(int newValue) {
\r
74 minIntDigits = newValue;
\r
77 public int getMinimumIntegerDigits() {
\r
78 return minIntDigits;
\r
81 /* For supporting SimpleDateFormat.parseInt */
\r
82 public void setParsePositiveOnly(boolean isPositiveOnly) {
\r
83 positiveOnly = isPositiveOnly;
\r
86 public char getZeroDigit() {
\r
90 public void setZeroDigit(char zero) {
\r
94 public StringBuffer format(double number, StringBuffer toAppendTo,
\r
95 FieldPosition pos) {
\r
96 throw new UnsupportedOperationException("StringBuffer format(double, StringBuffer, FieldPostion) is not implemented");
\r
99 public StringBuffer format(long numberL, StringBuffer toAppendTo,
\r
100 FieldPosition pos) {
\r
104 toAppendTo.append(minusSign);
\r
107 // Note: NumberFormat used by DateFormat only uses int numbers.
\r
108 // Remainder operation on 32bit platform using long is significantly slower
\r
109 // than int. So, this method casts long number into int.
\r
110 int number = (int)numberL;
\r
112 int limit = decimalBuf.length < maxIntDigits ? decimalBuf.length : maxIntDigits;
\r
113 int index = limit - 1;
\r
115 decimalBuf[index] = (char)((number % 10) + zeroDigit);
\r
117 if (index == 0 || number == 0) {
\r
122 int padding = minIntDigits - (limit - index);
\r
123 for (; padding > 0; padding--) {
\r
124 decimalBuf[--index] = zeroDigit;
\r
126 int length = limit - index;
\r
127 toAppendTo.append(decimalBuf, index, length);
\r
128 pos.setBeginIndex(0);
\r
129 if (pos.getField() == NumberFormat.INTEGER_FIELD) {
\r
130 pos.setEndIndex(length);
\r
132 pos.setEndIndex(0);
\r
137 public StringBuffer format(BigInteger number, StringBuffer toAppendTo,
\r
138 FieldPosition pos) {
\r
139 throw new UnsupportedOperationException("StringBuffer format(BigInteger, StringBuffer, FieldPostion) is not implemented");
\r
142 public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo,
\r
143 FieldPosition pos) {
\r
144 throw new UnsupportedOperationException("StringBuffer format(BigDecimal, StringBuffer, FieldPostion) is not implemented");
\r
147 public StringBuffer format(BigDecimal number,
\r
148 StringBuffer toAppendTo, FieldPosition pos) {
\r
149 throw new UnsupportedOperationException("StringBuffer format(BigDecimal, StringBuffer, FieldPostion) is not implemented");
\r
153 * Note: This method only parse integer numbers which can be represented by long
\r
155 public Number parse(String text, ParsePosition parsePosition) {
\r
157 boolean sawNumber = false;
\r
158 boolean negative = false;
\r
159 int base = parsePosition.getIndex();
\r
161 for (; base + offset < text.length(); offset++) {
\r
162 char ch = text.charAt(base + offset);
\r
163 if (offset == 0 && ch == minusSign) {
\r
164 if (positiveOnly) {
\r
169 int digit = ch - zeroDigit;
\r
170 if (digit < 0 || 9 < digit) {
\r
171 digit = UCharacter.digit(ch);
\r
173 if (0 <= digit && digit <= 9) {
\r
175 num = num * 10 + digit;
\r
181 Number result = null;
\r
183 num = negative ? num * (-1) : num;
\r
184 result = new Long(num);
\r
185 parsePosition.setIndex(base + offset);
\r
190 public boolean equals(Object obj) {
\r
191 if (obj == null || !super.equals(obj) || !(obj instanceof DateNumberFormat)) {
\r
194 DateNumberFormat other = (DateNumberFormat)obj;
\r
195 return (this.maxIntDigits == other.maxIntDigits
\r
196 && this.minIntDigits == other.minIntDigits
\r
197 && this.zeroDigit == other.zeroDigit
\r
198 && this.minusSign == other.minusSign
\r
199 && this.positiveOnly == other.positiveOnly);
\r
202 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
\r
203 stream.defaultReadObject();
\r
204 // re-allocate the work buffer
\r
205 decimalBuf = new char[20];
\r