]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/main/classes/localespi/src/com/ibm/icu/impl/jdkadapter/SimpleDateFormatICU.java
Clean up imports.
[Dictionary.git] / jars / icu4j-52_1 / main / classes / localespi / src / com / ibm / icu / impl / jdkadapter / SimpleDateFormatICU.java
1 /*
2  *******************************************************************************
3  * Copyright (C) 2008-2011, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package com.ibm.icu.impl.jdkadapter;
8
9 import java.text.AttributedCharacterIterator;
10 import java.text.AttributedString;
11 import java.text.CharacterIterator;
12 import java.text.DateFormatSymbols;
13 import java.text.FieldPosition;
14 import java.text.NumberFormat;
15 import java.text.ParsePosition;
16 import java.util.Calendar;
17 import java.util.Date;
18 import java.util.GregorianCalendar;
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.Map.Entry;
22 import java.util.TimeZone;
23
24 import com.ibm.icu.impl.icuadapter.NumberFormatJDK;
25 import com.ibm.icu.impl.icuadapter.TimeZoneJDK;
26 import com.ibm.icu.text.DateFormat;
27 import com.ibm.icu.text.SimpleDateFormat;
28
29 /**
30  * SimpleDateFormatICU is an adapter class which wraps ICU4J SimpleDateFormat and
31  * implements java.text.SimpleDateFormat APIs.
32  */
33 public class SimpleDateFormatICU extends java.text.SimpleDateFormat {
34
35     private static final long serialVersionUID = -2060890659010258983L;
36
37     private SimpleDateFormat fIcuSdf;
38
39     private SimpleDateFormatICU(SimpleDateFormat icuSdf) {
40         fIcuSdf = icuSdf;
41     }
42
43     public static java.text.SimpleDateFormat wrap(SimpleDateFormat icuSdf) {
44         return new SimpleDateFormatICU(icuSdf);
45     }
46
47     // Methods overriding java.text.SimpleDateFormat
48
49     @Override
50     public void applyLocalizedPattern(String pattern) {
51         fIcuSdf.applyLocalizedPattern(pattern);
52     }
53
54     @Override
55     public void applyPattern(String pattern) {
56         fIcuSdf.applyPattern(pattern);
57     }
58
59     @Override
60     public Object clone() {
61         SimpleDateFormatICU other = (SimpleDateFormatICU)super.clone();
62         other.fIcuSdf = (SimpleDateFormat)this.fIcuSdf.clone();
63         return other;
64     }
65
66     @Override
67     public boolean equals(Object obj) {
68         if (obj instanceof SimpleDateFormatICU) {
69             return ((SimpleDateFormatICU)obj).fIcuSdf.equals(this.fIcuSdf);
70         }
71         return false;
72     }
73
74     @Override
75     public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) {
76         return fIcuSdf.format(date, toAppendTo, pos);
77     }
78
79     @Override
80     public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
81         AttributedCharacterIterator aci = fIcuSdf.formatToCharacterIterator(obj);
82
83         // Create a new AttributedString
84         StringBuilder sb = new StringBuilder(aci.getEndIndex() - aci.getBeginIndex());
85         char c = aci.first();
86         while (true) {
87             sb.append(c);
88             c = aci.next();
89             if (c == CharacterIterator.DONE) {
90                 break;
91             }
92         }
93         AttributedString resstr = new AttributedString(sb.toString());
94
95         // Mapping attributes
96         Map<AttributedCharacterIterator.Attribute,Object> attributes = null;
97         int index = aci.getBeginIndex();
98         int residx = 0;
99         while (true) {
100             if (aci.setIndex(index) == CharacterIterator.DONE) {
101                 break;
102             }
103             attributes = aci.getAttributes();
104             if (attributes != null) {
105                 int end = aci.getRunLimit();
106                 Map<AttributedCharacterIterator.Attribute,Object> jdkAttributes = 
107                     new HashMap<AttributedCharacterIterator.Attribute,Object>();
108                 for (Entry<AttributedCharacterIterator.Attribute, Object> entry
109                         : attributes.entrySet()) {
110                     AttributedCharacterIterator.Attribute key = entry.getKey();
111                     AttributedCharacterIterator.Attribute jdkKey = mapAttribute(key);
112                     Object jdkVal = entry.getValue();
113                     if (jdkVal instanceof AttributedCharacterIterator.Attribute) {
114                         jdkVal = mapAttribute((AttributedCharacterIterator.Attribute)jdkVal);
115                     }
116                     jdkAttributes.put(jdkKey, jdkVal);
117                 }
118                 int resend = residx + (end - index);
119                 resstr.addAttributes(jdkAttributes, residx, resend);
120
121                 index = end;
122                 residx = resend;
123             }
124         }
125         return resstr.getIterator();
126     }
127
128     @Override
129     public Date get2DigitYearStart() {
130         return fIcuSdf.get2DigitYearStart();
131     }
132
133     @Override
134     public DateFormatSymbols getDateFormatSymbols() {
135         return DateFormatSymbolsICU.wrap(fIcuSdf.getDateFormatSymbols());
136     }
137
138     @Override
139     public int hashCode() {
140         return fIcuSdf.hashCode();
141     }
142
143     @Override
144     public Date parse(String text, ParsePosition pos) {
145         return fIcuSdf.parse(text, pos);
146     }
147
148     @Override
149     public void set2DigitYearStart(Date startDate) {
150         fIcuSdf.set2DigitYearStart(startDate);
151     }
152
153     @Override
154     public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols) {
155         com.ibm.icu.text.DateFormatSymbols icuDfs = null;
156         if (newFormatSymbols instanceof DateFormatSymbolsICU) {
157             icuDfs = ((DateFormatSymbolsICU)newFormatSymbols).unwrap();
158         } else if (fIcuSdf.getCalendar() instanceof com.ibm.icu.util.GregorianCalendar) {
159             // Java 6 uses DateFormatSymbols exclusively for Gregorian
160             // calendar.
161
162             String[] newJDK, curICU, newICU;
163             icuDfs = fIcuSdf.getDateFormatSymbols();
164
165             // Eras
166             newJDK = newFormatSymbols.getEras();
167             curICU = icuDfs.getEras();
168             newICU = copySymbols(newJDK, curICU, true);
169
170             // Months
171             newJDK = newFormatSymbols.getMonths();
172             curICU = icuDfs.getMonths();
173             newICU = copySymbols(newJDK, curICU, false);
174             icuDfs.setMonths(newICU);
175
176             // ShortMonths
177             newJDK = newFormatSymbols.getShortMonths();
178             curICU = icuDfs.getShortMonths();
179             newICU = copySymbols(newJDK, curICU, false);
180             icuDfs.setShortMonths(newICU);
181
182             // Weekdays
183             newJDK = newFormatSymbols.getWeekdays();
184             curICU = icuDfs.getWeekdays();
185             newICU = copySymbols(newJDK, curICU, false);
186             icuDfs.setWeekdays(newICU);
187
188             // ShortWeekdays
189             newJDK = newFormatSymbols.getShortWeekdays();
190             curICU = icuDfs.getShortWeekdays();
191             newICU = copySymbols(newJDK, curICU, false);
192             icuDfs.setShortWeekdays(newICU);
193
194             // AmPm
195             newJDK = newFormatSymbols.getAmPmStrings();
196             curICU = icuDfs.getAmPmStrings();
197             newICU = copySymbols(newJDK, curICU, false);
198             icuDfs.setAmPmStrings(newICU);
199         } else {
200             // For other calendars, JDK's standard DateFormatSymbols
201             // cannot be used.
202             throw new UnsupportedOperationException("JDK DateFormatSymbols cannot be used for the calendar type.");
203         }
204         fIcuSdf.setDateFormatSymbols(icuDfs);
205     }
206
207     @Override
208     public String toLocalizedPattern() {
209         return fIcuSdf.toLocalizedPattern();
210     }
211
212     @Override
213     public String toPattern() {
214         return fIcuSdf.toLocalizedPattern();
215     }
216
217     // Methods overriding java.text.DateFormat
218
219     @Override
220     public Calendar getCalendar() {
221         return CalendarICU.wrap(fIcuSdf.getCalendar());
222     }
223
224     @Override
225     public NumberFormat getNumberFormat() {
226         com.ibm.icu.text.NumberFormat nfmt = fIcuSdf.getNumberFormat();
227         if (nfmt instanceof NumberFormatJDK) {
228             return ((NumberFormatJDK)nfmt).unwrap();
229         }
230         if (nfmt instanceof com.ibm.icu.text.DecimalFormat) {
231             return DecimalFormatICU.wrap((com.ibm.icu.text.DecimalFormat)nfmt);
232         }
233         return NumberFormatICU.wrap(nfmt);
234     }
235
236     @Override
237     public TimeZone getTimeZone() {
238         return getCalendar().getTimeZone();
239     }
240
241     @Override
242     public boolean isLenient() {
243         return fIcuSdf.isLenient();
244     }
245
246     private static final long SAMPLE_TIME = 962409600000L; //2000-07-01T00:00:00Z
247     private static final int JAPANESE_YEAR = 12; // Japanese calendar year @ SAMPLE_TIME
248     private static final int THAI_YEAR = 2543; // Thai Buddhist calendar year @ SAMPLE_TIME
249
250     @Override
251     public void setCalendar(Calendar newCalendar) {
252         com.ibm.icu.util.Calendar icuCal = null;
253         if (newCalendar instanceof CalendarICU) {
254             icuCal = ((CalendarICU)newCalendar).unwrap();
255         } else {
256             // Note:    There is no easy way to implement ICU Calendar with
257             //          JDK Calendar implementation.  For now, this code assumes
258             //          the given calendar is either Gregorian, Buddhist or
259             //          JapaneseImperial.  Once the type is detected, this code
260             //          creates an instance of ICU Calendar with the same type.
261             com.ibm.icu.util.TimeZone icuTz = TimeZoneJDK.wrap(newCalendar.getTimeZone());
262             if (newCalendar instanceof GregorianCalendar) {
263                 icuCal = new com.ibm.icu.util.GregorianCalendar(icuTz);
264             } else {
265                 newCalendar.setTimeInMillis(SAMPLE_TIME);
266                 int year = newCalendar.get(Calendar.YEAR);
267                 if (year == JAPANESE_YEAR) {
268                     icuCal = new com.ibm.icu.util.JapaneseCalendar(icuTz);
269                 } else if (year == THAI_YEAR) {
270                     icuCal = new com.ibm.icu.util.BuddhistCalendar(icuTz);
271                 } else {
272                     // We cannot support the case
273                     throw new UnsupportedOperationException("Unsupported calendar type by ICU Calendar adapter.");
274                 }
275             }
276             // Copy the original calendar settings
277             icuCal.setFirstDayOfWeek(newCalendar.getFirstDayOfWeek());
278             icuCal.setLenient(newCalendar.isLenient());
279             icuCal.setMinimalDaysInFirstWeek(newCalendar.getMinimalDaysInFirstWeek());
280         }
281         fIcuSdf.setCalendar(icuCal);
282     }
283
284     @Override
285     public void setLenient(boolean lenient) {
286         fIcuSdf.setLenient(lenient);
287     }
288
289     @Override
290     public void setNumberFormat(NumberFormat newNumberFormat) {
291         if (newNumberFormat instanceof DecimalFormatICU) {
292             fIcuSdf.setNumberFormat(((DecimalFormatICU)newNumberFormat).unwrap());
293         } else if (newNumberFormat instanceof NumberFormatICU) {
294             fIcuSdf.setNumberFormat(((NumberFormatICU)newNumberFormat).unwrap());
295         } else {
296             fIcuSdf.setNumberFormat(NumberFormatJDK.wrap(newNumberFormat));
297         }
298     }
299
300     @Override
301     public void setTimeZone(TimeZone zone) {
302         fIcuSdf.setTimeZone(TimeZoneJDK.wrap(zone));
303     }
304
305     private String[] copySymbols(String[] newData, String[] curData, boolean alignEnd) {
306         if (newData.length >= curData.length) {
307             return newData;
308         }
309         int startOffset = alignEnd ? curData.length - newData.length : 0;
310         System.arraycopy(newData, 0, curData, startOffset, newData.length);
311         return curData;
312     }
313
314     private static AttributedCharacterIterator.Attribute mapAttribute(AttributedCharacterIterator.Attribute icuAttribute) {
315         AttributedCharacterIterator.Attribute jdkAttribute = icuAttribute;
316
317         if (icuAttribute == DateFormat.Field.AM_PM) {
318             jdkAttribute = java.text.DateFormat.Field.AM_PM;
319         } else if (icuAttribute == DateFormat.Field.DAY_OF_MONTH) {
320             jdkAttribute = java.text.DateFormat.Field.DAY_OF_MONTH;
321         } else if (icuAttribute == DateFormat.Field.DAY_OF_WEEK) {
322             jdkAttribute = java.text.DateFormat.Field.DAY_OF_WEEK;
323         } else if (icuAttribute == DateFormat.Field.DAY_OF_WEEK_IN_MONTH) {
324             jdkAttribute = java.text.DateFormat.Field.DAY_OF_WEEK_IN_MONTH;
325         } else if (icuAttribute == DateFormat.Field.DAY_OF_YEAR) {
326             jdkAttribute = java.text.DateFormat.Field.DAY_OF_YEAR;
327         } else if (icuAttribute == DateFormat.Field.ERA) {
328             jdkAttribute = java.text.DateFormat.Field.ERA;
329         } else if (icuAttribute == DateFormat.Field.HOUR_OF_DAY0) {
330             jdkAttribute = java.text.DateFormat.Field.HOUR_OF_DAY0;
331         } else if (icuAttribute == DateFormat.Field.HOUR_OF_DAY1) {
332             jdkAttribute = java.text.DateFormat.Field.HOUR_OF_DAY1;
333         } else if (icuAttribute == DateFormat.Field.HOUR0) {
334             jdkAttribute = java.text.DateFormat.Field.HOUR0;
335         } else if (icuAttribute == DateFormat.Field.HOUR1) {
336             jdkAttribute = java.text.DateFormat.Field.HOUR1;
337         } else if (icuAttribute == DateFormat.Field.MILLISECOND) {
338             jdkAttribute = java.text.DateFormat.Field.MILLISECOND;
339         } else if (icuAttribute == DateFormat.Field.MINUTE) {
340             jdkAttribute = java.text.DateFormat.Field.MINUTE;
341         } else if (icuAttribute == DateFormat.Field.MONTH) {
342             jdkAttribute = java.text.DateFormat.Field.MONTH;
343         } else if (icuAttribute == DateFormat.Field.SECOND) {
344             jdkAttribute = java.text.DateFormat.Field.SECOND;
345         } else if (icuAttribute == DateFormat.Field.TIME_ZONE) {
346             jdkAttribute = java.text.DateFormat.Field.TIME_ZONE;
347         } else if (icuAttribute == DateFormat.Field.WEEK_OF_MONTH) {
348             jdkAttribute = java.text.DateFormat.Field.WEEK_OF_MONTH;
349         } else if (icuAttribute == DateFormat.Field.WEEK_OF_YEAR) {
350             jdkAttribute = java.text.DateFormat.Field.WEEK_OF_YEAR;
351         } else if (icuAttribute == DateFormat.Field.YEAR) {
352             jdkAttribute = java.text.DateFormat.Field.YEAR;
353         }
354         // There are other DateFormat.Field constants defined in
355         // ICU4J DateFormat below.
356         //
357         //   DOW_LOCAL
358         //   EXTENDED_YEAR
359         //   JULIAN_DAY
360         //   MILLISECONDS_IN_DAY
361         //   QUARTER
362         //   YEAR_WOY
363         //
364         // However, the corresponding pattern characters are not used by
365         // the default factory method - getXXXInstance.  So these constants
366         // are only used when user intentionally set a pattern including
367         // these ICU4J specific pattern letters.  Even it happens,
368         // ICU4J's DateFormat.Field extends java.text.Format.Field, so
369         // it does not break the contract of formatToCharacterIterator.
370
371         return jdkAttribute;
372     }
373
374 }