]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_8_1_1/main/classes/localespi/src/com/ibm/icu/impl/jdkadapter/SimpleDateFormatICU.java
Added flags.
[Dictionary.git] / jars / icu4j-4_8_1_1 / main / classes / localespi / src / com / ibm / icu / impl / jdkadapter / SimpleDateFormatICU.java
1 /*
2  *******************************************************************************
3  * Copyright (C) 2008, 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.Set;
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                 Set<AttributedCharacterIterator.Attribute> keys = attributes.keySet();
109                 for (AttributedCharacterIterator.Attribute key : keys) {
110                     AttributedCharacterIterator.Attribute jdkKey = mapAttribute(key);
111                     Object jdkVal = attributes.get(key);
112                     if (jdkVal instanceof AttributedCharacterIterator.Attribute) {
113                         jdkVal = mapAttribute((AttributedCharacterIterator.Attribute)jdkVal);
114                     }
115                     jdkAttributes.put(jdkKey, jdkVal);
116                 }
117                 int resend = residx + (end - index);
118                 resstr.addAttributes(jdkAttributes, residx, resend);
119
120                 index = end;
121                 residx = resend;
122             }
123         }
124         return resstr.getIterator();
125     }
126
127     @Override
128     public Date get2DigitYearStart() {
129         return fIcuSdf.get2DigitYearStart();
130     }
131
132     @Override
133     public DateFormatSymbols getDateFormatSymbols() {
134         return DateFormatSymbolsICU.wrap(fIcuSdf.getDateFormatSymbols());
135     }
136
137     @Override
138     public int hashCode() {
139         return fIcuSdf.hashCode();
140     }
141
142     @Override
143     public Date parse(String text, ParsePosition pos) {
144         return fIcuSdf.parse(text, pos);
145     }
146
147     @Override
148     public void set2DigitYearStart(Date startDate) {
149         fIcuSdf.set2DigitYearStart(startDate);
150     }
151
152     @Override
153     public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols) {
154         com.ibm.icu.text.DateFormatSymbols icuDfs = null;
155         if (newFormatSymbols instanceof DateFormatSymbolsICU) {
156             icuDfs = ((DateFormatSymbolsICU)newFormatSymbols).unwrap();
157         } else if (fIcuSdf.getCalendar() instanceof com.ibm.icu.util.GregorianCalendar) {
158             // Java 6 uses DateFormatSymbols exclusively for Gregorian
159             // calendar.
160
161             String[] newJDK, curICU, newICU;
162             icuDfs = fIcuSdf.getDateFormatSymbols();
163
164             // Eras
165             newJDK = newFormatSymbols.getEras();
166             curICU = icuDfs.getEras();
167             newICU = copySymbols(newJDK, curICU, true);
168
169             // Months
170             newJDK = newFormatSymbols.getMonths();
171             curICU = icuDfs.getMonths();
172             newICU = copySymbols(newJDK, curICU, false);
173             icuDfs.setMonths(newICU);
174
175             // ShortMonths
176             newJDK = newFormatSymbols.getShortMonths();
177             curICU = icuDfs.getShortMonths();
178             newICU = copySymbols(newJDK, curICU, false);
179             icuDfs.setShortMonths(newICU);
180
181             // Weekdays
182             newJDK = newFormatSymbols.getWeekdays();
183             curICU = icuDfs.getWeekdays();
184             newICU = copySymbols(newJDK, curICU, false);
185             icuDfs.setWeekdays(newICU);
186
187             // ShortWeekdays
188             newJDK = newFormatSymbols.getShortWeekdays();
189             curICU = icuDfs.getShortWeekdays();
190             newICU = copySymbols(newJDK, curICU, false);
191             icuDfs.setShortWeekdays(newICU);
192
193             // AmPm
194             newJDK = newFormatSymbols.getAmPmStrings();
195             curICU = icuDfs.getAmPmStrings();
196             newICU = copySymbols(newJDK, curICU, false);
197             icuDfs.setAmPmStrings(newICU);
198         } else {
199             // For other calendars, JDK's standard DateFormatSymbols
200             // cannot be used.
201             throw new UnsupportedOperationException("JDK DateFormatSymbols cannot be used for the calendar type.");
202         }
203         fIcuSdf.setDateFormatSymbols(icuDfs);
204     }
205
206     @Override
207     public String toLocalizedPattern() {
208         return fIcuSdf.toLocalizedPattern();
209     }
210
211     @Override
212     public String toPattern() {
213         return fIcuSdf.toLocalizedPattern();
214     }
215
216     // Methods overriding java.text.DateFormat
217
218     @Override
219     public Calendar getCalendar() {
220         return CalendarICU.wrap(fIcuSdf.getCalendar());
221     }
222
223     @Override
224     public NumberFormat getNumberFormat() {
225         com.ibm.icu.text.NumberFormat nfmt = fIcuSdf.getNumberFormat();
226         if (nfmt instanceof NumberFormatJDK) {
227             return ((NumberFormatJDK)nfmt).unwrap();
228         }
229         if (nfmt instanceof com.ibm.icu.text.DecimalFormat) {
230             return DecimalFormatICU.wrap((com.ibm.icu.text.DecimalFormat)nfmt);
231         }
232         return NumberFormatICU.wrap(nfmt);
233     }
234
235     @Override
236     public TimeZone getTimeZone() {
237         return getCalendar().getTimeZone();
238     }
239
240     @Override
241     public boolean isLenient() {
242         return fIcuSdf.isLenient();
243     }
244
245     private static final long SAMPLE_TIME = 962409600000L; //2000-07-01T00:00:00Z
246     private static final int JAPANESE_YEAR = 12; // Japanese calendar year @ SAMPLE_TIME
247     private static final int THAI_YEAR = 2543; // Thai Buddhist calendar year @ SAMPLE_TIME
248
249     @Override
250     public void setCalendar(Calendar newCalendar) {
251         com.ibm.icu.util.Calendar icuCal = null;
252         if (newCalendar instanceof CalendarICU) {
253             icuCal = ((CalendarICU)newCalendar).unwrap();
254         } else {
255             // Note:    There is no easy way to implement ICU Calendar with
256             //          JDK Calendar implementation.  For now, this code assumes
257             //          the given calendar is either Gregorian, Buddhist or
258             //          JapaneseImperial.  Once the type is detected, this code
259             //          creates an instance of ICU Calendar with the same type.
260             com.ibm.icu.util.TimeZone icuTz = TimeZoneJDK.wrap(newCalendar.getTimeZone());
261             if (newCalendar instanceof GregorianCalendar) {
262                 icuCal = new com.ibm.icu.util.GregorianCalendar(icuTz);
263             } else {
264                 newCalendar.setTimeInMillis(SAMPLE_TIME);
265                 int year = newCalendar.get(Calendar.YEAR);
266                 if (year == JAPANESE_YEAR) {
267                     icuCal = new com.ibm.icu.util.JapaneseCalendar(icuTz);
268                 } else if (year == THAI_YEAR) {
269                     icuCal = new com.ibm.icu.util.BuddhistCalendar(icuTz);
270                 } else {
271                     // We cannot support the case
272                     throw new UnsupportedOperationException("Unsupported calendar type by ICU Calendar adapter.");
273                 }
274             }
275             // Copy the original calendar settings
276             icuCal.setFirstDayOfWeek(newCalendar.getFirstDayOfWeek());
277             icuCal.setLenient(newCalendar.isLenient());
278             icuCal.setMinimalDaysInFirstWeek(newCalendar.getMinimalDaysInFirstWeek());
279         }
280         fIcuSdf.setCalendar(icuCal);
281     }
282
283     @Override
284     public void setLenient(boolean lenient) {
285         fIcuSdf.setLenient(lenient);
286     }
287
288     @Override
289     public void setNumberFormat(NumberFormat newNumberFormat) {
290         if (newNumberFormat instanceof DecimalFormatICU) {
291             fIcuSdf.setNumberFormat(((DecimalFormatICU)newNumberFormat).unwrap());
292         } else if (newNumberFormat instanceof NumberFormatICU) {
293             fIcuSdf.setNumberFormat(((NumberFormatICU)newNumberFormat).unwrap());
294         } else {
295             fIcuSdf.setNumberFormat(NumberFormatJDK.wrap(newNumberFormat));
296         }
297     }
298
299     @Override
300     public void setTimeZone(TimeZone zone) {
301         fIcuSdf.setTimeZone(TimeZoneJDK.wrap(zone));
302     }
303
304     private String[] copySymbols(String[] newData, String[] curData, boolean alignEnd) {
305         if (newData.length >= curData.length) {
306             return newData;
307         }
308         int startOffset = alignEnd ? curData.length - newData.length : 0;
309         System.arraycopy(newData, 0, curData, startOffset, newData.length);
310         return curData;
311     }
312
313     private static AttributedCharacterIterator.Attribute mapAttribute(AttributedCharacterIterator.Attribute icuAttribute) {
314         AttributedCharacterIterator.Attribute jdkAttribute = icuAttribute;
315
316         if (icuAttribute == DateFormat.Field.AM_PM) {
317             jdkAttribute = java.text.DateFormat.Field.AM_PM;
318         } else if (icuAttribute == DateFormat.Field.DAY_OF_MONTH) {
319             jdkAttribute = java.text.DateFormat.Field.DAY_OF_MONTH;
320         } else if (icuAttribute == DateFormat.Field.DAY_OF_WEEK) {
321             jdkAttribute = java.text.DateFormat.Field.DAY_OF_WEEK;
322         } else if (icuAttribute == DateFormat.Field.DAY_OF_WEEK_IN_MONTH) {
323             jdkAttribute = java.text.DateFormat.Field.DAY_OF_WEEK_IN_MONTH;
324         } else if (icuAttribute == DateFormat.Field.DAY_OF_YEAR) {
325             jdkAttribute = java.text.DateFormat.Field.DAY_OF_YEAR;
326         } else if (icuAttribute == DateFormat.Field.ERA) {
327             jdkAttribute = java.text.DateFormat.Field.ERA;
328         } else if (icuAttribute == DateFormat.Field.HOUR_OF_DAY0) {
329             jdkAttribute = java.text.DateFormat.Field.HOUR_OF_DAY0;
330         } else if (icuAttribute == DateFormat.Field.HOUR_OF_DAY1) {
331             jdkAttribute = java.text.DateFormat.Field.HOUR_OF_DAY1;
332         } else if (icuAttribute == DateFormat.Field.HOUR0) {
333             jdkAttribute = java.text.DateFormat.Field.HOUR0;
334         } else if (icuAttribute == DateFormat.Field.HOUR1) {
335             jdkAttribute = java.text.DateFormat.Field.HOUR1;
336         } else if (icuAttribute == DateFormat.Field.MILLISECOND) {
337             jdkAttribute = java.text.DateFormat.Field.MILLISECOND;
338         } else if (icuAttribute == DateFormat.Field.MINUTE) {
339             jdkAttribute = java.text.DateFormat.Field.MINUTE;
340         } else if (icuAttribute == DateFormat.Field.MONTH) {
341             jdkAttribute = java.text.DateFormat.Field.MONTH;
342         } else if (icuAttribute == DateFormat.Field.SECOND) {
343             jdkAttribute = java.text.DateFormat.Field.SECOND;
344         } else if (icuAttribute == DateFormat.Field.TIME_ZONE) {
345             jdkAttribute = java.text.DateFormat.Field.TIME_ZONE;
346         } else if (icuAttribute == DateFormat.Field.WEEK_OF_MONTH) {
347             jdkAttribute = java.text.DateFormat.Field.WEEK_OF_MONTH;
348         } else if (icuAttribute == DateFormat.Field.WEEK_OF_YEAR) {
349             jdkAttribute = java.text.DateFormat.Field.WEEK_OF_YEAR;
350         } else if (icuAttribute == DateFormat.Field.YEAR) {
351             jdkAttribute = java.text.DateFormat.Field.YEAR;
352         }
353         // There are other DateFormat.Field constants defined in
354         // ICU4J DateFormat below.
355         //
356         //   DOW_LOCAL
357         //   EXTENDED_YEAR
358         //   JULIAN_DAY
359         //   MILLISECONDS_IN_DAY
360         //   QUARTER
361         //   YEAR_WOY
362         //
363         // However, the corresponding pattern characters are not used by
364         // the default factory method - getXXXInstance.  So these constants
365         // are only used when user intentionally set a pattern including
366         // these ICU4J specific pattern letters.  Even it happens,
367         // ICU4J's DateFormat.Field extends java.text.Format.Field, so
368         // it does not break the contract of formatToCharacterIterator.
369
370         return jdkAttribute;
371     }
372
373 }