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