2 *******************************************************************************
\r
3 * Copyright (C) 2008, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.impl.jdkadapter;
\r
9 import java.util.HashMap;
\r
10 import java.util.Locale;
\r
11 import java.util.Map;
\r
12 import java.util.TimeZone;
\r
14 import com.ibm.icu.impl.icuadapter.TimeZoneJDK;
\r
15 import com.ibm.icu.text.DateFormatSymbols;
\r
16 import com.ibm.icu.util.Calendar;
\r
19 * CalendarICU is an adapter class which wraps ICU4J Calendar and
\r
20 * implements java.util.Calendar APIs.
\r
22 public class CalendarICU extends java.util.Calendar {
\r
24 private static final long serialVersionUID = -8641226371713600671L;
\r
26 private Calendar fIcuCal;
\r
28 private CalendarICU(Calendar icuCal) {
\r
33 public static java.util.Calendar wrap(Calendar icuCal) {
\r
34 return new CalendarICU(icuCal);
\r
37 public Calendar unwrap() {
\r
43 public void add(int field, int amount) {
\r
45 fIcuCal.add(field, amount);
\r
48 // Note: We do not need to override followings. These methods
\r
49 // call int compareTo(Calendar anotherCalendar) and we
\r
50 // override the method.
\r
51 //public boolean after(Object when)
\r
52 //public boolean before(Object when)
\r
54 // Note: Jeez! These methods are final and we cannot override them.
\r
55 // We do not want to rewrite ICU Calendar implementation classes
\r
56 // as subclasses of java.util.Calendar. This adapter class
\r
57 // wraps an ICU Calendar instance and the calendar calculation
\r
58 // is actually done independently from java.util.Calendar
\r
59 // implementation. Thus, we need to monitor the status of
\r
60 // superclass fields in some methods and call ICU Calendar's
\r
61 // clear if superclass clear update the status of superclass's
\r
62 // calendar fields. See private void sync().
\r
63 //public void clear()
\r
64 //public void clear(int field)
\r
67 public Object clone() {
\r
69 CalendarICU other = (CalendarICU)super.clone();
\r
70 other.fIcuCal = (Calendar)fIcuCal.clone();
\r
74 public int compareTo(Calendar anotherCalendar) {
\r
76 long thisMillis = getTimeInMillis();
\r
77 long otherMillis = anotherCalendar.getTimeInMillis();
\r
78 return thisMillis > otherMillis ? 1 : (thisMillis == otherMillis ? 0 : -1);
\r
81 // Note: These methods are supposed to be implemented by java.util.Calendar
\r
82 // subclasses. But we actually use a instance of ICU Calendar
\r
83 // for all calendar calculation, we do nothing here.
\r
85 protected void complete() {}
\r
87 protected void computeFields() {}
\r
89 protected void computeTime() {}
\r
92 public boolean equals(Object obj) {
\r
93 if (obj instanceof CalendarICU) {
\r
95 return ((CalendarICU)obj).fIcuCal.equals(fIcuCal);
\r
101 public int get(int field) {
\r
103 return fIcuCal.get(field);
\r
107 public int getActualMaximum(int field) {
\r
108 return fIcuCal.getActualMaximum(field);
\r
112 public int getActualMinimum(int field) {
\r
113 return fIcuCal.getActualMinimum(field);
\r
117 public String getDisplayName(int field, int style, Locale locale) {
\r
118 if (field < 0 || field >= FIELD_COUNT || (style != SHORT && style != LONG && style != ALL_STYLES)) {
\r
119 throw new IllegalArgumentException("Bad field or style.");
\r
121 DateFormatSymbols dfs = DateFormatSymbols.getInstance(locale);
\r
122 String[] array = getFieldStrings(field, style, dfs);
\r
123 if (array != null) {
\r
124 int fieldVal = get(field);
\r
125 if (fieldVal < array.length) {
\r
126 return array[fieldVal];
\r
133 public Map<String,Integer> getDisplayNames(int field, int style, Locale locale) {
\r
134 if (field < 0 || field >= FIELD_COUNT || (style != SHORT && style != LONG && style != ALL_STYLES)) {
\r
135 throw new IllegalArgumentException("Bad field or style.");
\r
137 DateFormatSymbols dfs = DateFormatSymbols.getInstance(locale);
\r
138 if (style != ALL_STYLES) {
\r
139 return getFieldStringsMap(field, style, dfs);
\r
142 Map<String,Integer> result = getFieldStringsMap(field, SHORT, dfs);
\r
143 if (result == null) {
\r
146 if (field == MONTH || field == DAY_OF_WEEK) {
\r
147 Map<String,Integer> longMap = getFieldStringsMap(field, LONG, dfs);
\r
148 if (longMap != null) {
\r
149 result.putAll(longMap);
\r
156 public int getGreatestMinimum(int field) {
\r
157 return fIcuCal.getGreatestMinimum(field);
\r
161 public int getLeastMaximum(int field) {
\r
162 return fIcuCal.getLeastMaximum(field);
\r
166 public int getMaximum(int field) {
\r
167 return fIcuCal.getMaximum(field);
\r
171 public int getMinimalDaysInFirstWeek() {
\r
172 return fIcuCal.getMinimalDaysInFirstWeek();
\r
176 public int getMinimum(int field) {
\r
177 return fIcuCal.getMinimum(field);
\r
180 // Note: getTime() calls getTimeInMillis()
\r
181 //public Date getTime()
\r
184 public long getTimeInMillis() {
\r
186 return fIcuCal.getTimeInMillis();
\r
190 public TimeZone getTimeZone() {
\r
191 return TimeZoneICU.wrap(fIcuCal.getTimeZone());
\r
195 public int hashCode() {
\r
197 return fIcuCal.hashCode();
\r
200 //protected int internalGet(int field)
\r
203 public boolean isLenient() {
\r
204 return fIcuCal.isLenient();
\r
207 //public boolean isSet(int field)
\r
210 public void roll(int field, boolean up) {
\r
212 fIcuCal.roll(field, up);
\r
216 public void roll(int field, int amount) {
\r
218 fIcuCal.roll(field, amount);
\r
222 public void set(int field, int value) {
\r
224 fIcuCal.set(field, value);
\r
227 // Note: These set methods call set(int field, int value) for each field.
\r
228 // These are final, so we cannot override them, but we override
\r
229 // set(int field, int value), so the superclass implementations
\r
230 // still work as we want.
\r
231 //public void set(int year, int month, int date)
\r
232 //public void set(int year, int month, int date, int hourOfDay, int minute)
\r
233 //public void set(int year, int month, int date, int hourOfDay, int minute, int second)
\r
236 public void setFirstDayOfWeek(int value) {
\r
237 fIcuCal.setFirstDayOfWeek(value);
\r
241 public void setLenient(boolean lenient) {
\r
242 fIcuCal.setLenient(lenient);
\r
246 public void setMinimalDaysInFirstWeek(int value) {
\r
247 fIcuCal.setMinimalDaysInFirstWeek(value);
\r
250 // Note: This method calls setTimeInMillis(long millis).
\r
251 // This method is final, so we cannot override it, but we
\r
252 // override setTimeInMillis(long millis), so the superclass
\r
253 // implementation still works as we want.
\r
254 //public void setTime(Date date)
\r
257 public void setTimeInMillis(long millis) {
\r
258 fIcuCal.setTimeInMillis(millis);
\r
262 public void setTimeZone(TimeZone value) {
\r
263 fIcuCal.setTimeZone(TimeZoneJDK.wrap(value));
\r
267 public String toString() {
\r
269 return "CalendarICU: " + fIcuCal.toString();
\r
272 private void sync() {
\r
273 // Check if clear is called for each JDK Calendar field.
\r
274 // If it was, then call clear for the field in the wrapped
\r
276 for (int i = 0; i < isSet.length; i++) {
\r
281 } catch (ArrayIndexOutOfBoundsException e) {
\r
282 // More fields in JDK calendar, which is unlikely
\r
288 private void init() {
\r
289 // Mark "set" for all fields, so we can detect the invocation of
\r
291 for (int i = 0; i < isSet.length; i++) {
\r
296 private static String[] getFieldStrings(int field, int style, DateFormatSymbols dfs) {
\r
297 String[] result = null;
\r
300 result = dfs.getAmPmStrings();
\r
303 result = (style == LONG) ? dfs.getWeekdays() : dfs.getShortWeekdays();
\r
306 //result = (style == LONG) ? dfs.getEraNames() : dfs.getEras();
\r
307 result = dfs.getEras();
\r
310 result = (style == LONG) ? dfs.getMonths() : dfs.getShortMonths();
\r
316 private static Map<String,Integer> getFieldStringsMap(int field, int style, DateFormatSymbols dfs) {
\r
317 String[] strings = getFieldStrings(field, style, dfs);
\r
318 if (strings == null) {
\r
321 Map<String,Integer> res = new HashMap<String,Integer>();
\r
322 for (int i = 0; i < strings.length; i++) {
\r
323 if (strings[i].length() != 0) {
\r
324 res.put(strings[i], Integer.valueOf(i));
\r