]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_8_1_1/main/classes/core/src/com/ibm/icu/impl/DateNumberFormat.java
Added flags.
[Dictionary.git] / jars / icu4j-4_8_1_1 / main / classes / core / src / com / ibm / icu / impl / DateNumberFormat.java
1 /*
2 *******************************************************************************
3 *   Copyright (C) 2007-2011, International Business Machines
4 *   Corporation and others.  All Rights Reserved.
5 *******************************************************************************
6 */
7 package com.ibm.icu.impl;
8
9 import java.io.IOException;
10 import java.io.ObjectInputStream;
11 import java.math.BigInteger;
12 import java.text.FieldPosition;
13 import java.text.ParsePosition;
14 import java.util.Arrays;
15 import java.util.MissingResourceException;
16
17 import com.ibm.icu.lang.UCharacter;
18 import com.ibm.icu.math.BigDecimal;
19 import com.ibm.icu.text.NumberFormat;
20 import com.ibm.icu.util.ULocale;
21 import com.ibm.icu.util.UResourceBundle;
22
23 /*
24  * NumberFormat implementation dedicated/optimized for DateFormat,
25  * used by SimpleDateFormat implementation.
26  */
27 public final class DateNumberFormat extends NumberFormat {
28
29     private static final long serialVersionUID = -6315692826916346953L;
30
31     private char[] digits;
32     private char zeroDigit; // For backwards compatibility
33     private char minusSign;
34     private boolean positiveOnly = false;
35
36     private transient char[] decimalBuf = new char[20]; // 20 digits is good enough to store Long.MAX_VALUE
37
38     private static SimpleCache<ULocale, char[]> CACHE = new SimpleCache<ULocale, char[]>();
39
40     private int maxIntDigits;
41     private int minIntDigits;
42
43     public DateNumberFormat(ULocale loc, String digitString, String nsName) {
44         initialize(loc,digitString,nsName);
45     }
46
47     public DateNumberFormat(ULocale loc, char zeroDigit, String nsName) {
48         StringBuffer buf = new StringBuffer();
49         for ( int i = 0 ; i < 10 ; i++ ) {
50             buf.append((char)(zeroDigit+i));
51         }
52         initialize(loc,buf.toString(),nsName);
53     }
54
55     private void initialize(ULocale loc,String digitString,String nsName) {
56         char[] elems = CACHE.get(loc);
57         if (elems == null) {
58             // Missed cache
59             String minusString;
60             ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, loc);
61             try {
62                 minusString = rb.getStringWithFallback("NumberElements/"+nsName+"/symbols/minusSign");
63             } catch (MissingResourceException ex) {
64                 if ( !nsName.equals("latn") ) {
65                     try {
66                        minusString = rb.getStringWithFallback("NumberElements/latn/symbols/minusSign");                 
67                     } catch (MissingResourceException ex1) {
68                         minusString = "-";
69                     }
70                 } else {
71                     minusString = "-";
72                 }
73             }
74             elems = new char[11];
75             for ( int i = 0 ; i < 10 ; i++ ) {
76                  elems[i] = digitString.charAt(i);
77             }
78             elems[10] = minusString.charAt(0);
79             CACHE.put(loc, elems);
80         }
81
82         digits = new char[10];
83         System.arraycopy(elems, 0, digits, 0, 10);
84         zeroDigit = digits[0];
85
86         minusSign = elems[10];
87     }
88
89     public void setMaximumIntegerDigits(int newValue) {
90         maxIntDigits = newValue;
91     }
92
93     public int getMaximumIntegerDigits() {
94         return maxIntDigits;
95     }
96
97     public void setMinimumIntegerDigits(int newValue) {
98         minIntDigits = newValue;
99     }
100
101     public int getMinimumIntegerDigits() {
102         return minIntDigits;
103     }
104
105     /* For supporting SimpleDateFormat.parseInt */
106     public void setParsePositiveOnly(boolean isPositiveOnly) {
107         positiveOnly = isPositiveOnly;
108     }
109
110     public char getZeroDigit() {
111         return zeroDigit;
112     }
113
114     public void setZeroDigit(char zero) {
115         zeroDigit = zero;
116         if (digits == null) {
117             digits = new char[10];
118         }
119         digits[0] = zero;
120         for ( int i = 1 ; i < 10 ; i++ ) {
121             digits[i] = (char)(zero+i);
122         }
123     }
124
125     public char[] getDigits() {
126         return digits;
127     }
128
129     public StringBuffer format(double number, StringBuffer toAppendTo,
130             FieldPosition pos) {
131         throw new UnsupportedOperationException("StringBuffer format(double, StringBuffer, FieldPostion) is not implemented");
132     }
133
134     public StringBuffer format(long numberL, StringBuffer toAppendTo,
135             FieldPosition pos) {
136
137         if (numberL < 0) {
138             // negative
139             toAppendTo.append(minusSign);
140             numberL = -numberL;
141         }
142
143         // Note: NumberFormat used by DateFormat only uses int numbers.
144         // Remainder operation on 32bit platform using long is significantly slower
145         // than int.  So, this method casts long number into int.
146         int number = (int)numberL;
147
148         int limit = decimalBuf.length < maxIntDigits ? decimalBuf.length : maxIntDigits;
149         int index = limit - 1;
150         while (true) {
151             decimalBuf[index] = digits[(number % 10)];
152             number /= 10;
153             if (index == 0 || number == 0) {
154                 break;
155             }
156             index--;
157         }
158         int padding = minIntDigits - (limit - index);
159         for (; padding > 0; padding--) {
160             decimalBuf[--index] = digits[0];
161         }
162         int length = limit - index;
163         toAppendTo.append(decimalBuf, index, length);
164         pos.setBeginIndex(0);
165         if (pos.getField() == NumberFormat.INTEGER_FIELD) {
166             pos.setEndIndex(length);
167         } else {
168             pos.setEndIndex(0);
169         }
170         return toAppendTo;
171     }
172     
173     public StringBuffer format(BigInteger number, StringBuffer toAppendTo,
174             FieldPosition pos) {
175         throw new UnsupportedOperationException("StringBuffer format(BigInteger, StringBuffer, FieldPostion) is not implemented");
176     }
177
178     public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo,
179             FieldPosition pos) {
180         throw new UnsupportedOperationException("StringBuffer format(BigDecimal, StringBuffer, FieldPostion) is not implemented");
181     }
182
183     public StringBuffer format(BigDecimal number,
184             StringBuffer toAppendTo, FieldPosition pos) {
185         throw new UnsupportedOperationException("StringBuffer format(BigDecimal, StringBuffer, FieldPostion) is not implemented");
186     }
187
188     /*
189      * Note: This method only parse integer numbers which can be represented by long
190      */
191     private static final long PARSE_THRESHOLD = 922337203685477579L; // (Long.MAX_VALUE / 10) - 1
192
193     public Number parse(String text, ParsePosition parsePosition) {
194         long num = 0;
195         boolean sawNumber = false;
196         boolean negative = false;
197         int base = parsePosition.getIndex();
198         int offset = 0;
199         for (; base + offset < text.length(); offset++) {
200             char ch = text.charAt(base + offset);
201             if (offset == 0 && ch == minusSign) {
202                 if (positiveOnly) {
203                     break;
204                 }
205                 negative = true;
206             } else {
207                 int digit = ch - digits[0];
208                 if (digit < 0 || 9 < digit) {
209                     digit = UCharacter.digit(ch);
210                 }
211                 if (digit < 0 || 9 < digit) {
212                     for ( digit = 0 ; digit < 10 ; digit++ ) {
213                         if ( ch == digits[digit]) {
214                             break;
215                         }
216                     }
217                 }
218                 if (0 <= digit && digit <= 9 && num < PARSE_THRESHOLD) {
219                     sawNumber = true;
220                     num = num * 10 + digit;
221                 } else {
222                     break;
223                 }
224             }
225         }
226         Number result = null;
227         if (sawNumber) {
228             num = negative ? num * (-1) : num;
229             result = new Long(num);
230             parsePosition.setIndex(base + offset);
231         }
232         return result;
233     }
234
235     public boolean equals(Object obj) {
236         if (obj == null || !super.equals(obj) || !(obj instanceof DateNumberFormat)) {
237             return false;
238         }
239         DateNumberFormat other = (DateNumberFormat)obj;
240         return (this.maxIntDigits == other.maxIntDigits
241                 && this.minIntDigits == other.minIntDigits
242                 && this.minusSign == other.minusSign
243                 && this.positiveOnly == other.positiveOnly
244                 && Arrays.equals(this.digits, other.digits));
245     }
246
247     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
248         stream.defaultReadObject();
249         if (digits == null) {
250             setZeroDigit(zeroDigit);
251         }
252         // re-allocate the work buffer
253         decimalBuf = new char[20];
254     }
255 }
256
257 //eof