blob: 6412c840b18ffd1eed1b821b7208579580d99885 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.util;
27
28import java.util.Calendar;
29import java.util.GregorianCalendar;
30import java.util.HashMap;
31import java.util.Locale;
32import java.util.Map;
33import java.util.ResourceBundle;
34import java.util.TimeZone;
35import sun.util.resources.LocaleData;
36
37public class BuddhistCalendar extends GregorianCalendar {
38
39//////////////////
40// Class Variables
41//////////////////
42
43 private static final long serialVersionUID = -8527488697350388578L;
44
45 private static final int buddhistOffset = 543;
46
47///////////////
48// Constructors
49///////////////
50
51 /**
52 * Constructs a default BuddhistCalendar using the current time
53 * in the default time zone with the default locale.
54 */
55 public BuddhistCalendar() {
56 super();
57 }
58
59 /**
60 * Constructs a BuddhistCalendar based on the current time
61 * in the given time zone with the default locale.
62 * @param zone the given time zone.
63 */
64 public BuddhistCalendar(TimeZone zone) {
65 super(zone);
66 }
67
68 /**
69 * Constructs a BuddhistCalendar based on the current time
70 * in the default time zone with the given locale.
71 * @param aLocale the given locale.
72 */
73 public BuddhistCalendar(Locale aLocale) {
74 super(aLocale);
75 }
76
77 /**
78 * Constructs a BuddhistCalendar based on the current time
79 * in the given time zone with the given locale.
80 * @param zone the given time zone.
81 * @param aLocale the given locale.
82 */
83 public BuddhistCalendar(TimeZone zone, Locale aLocale) {
84 super(zone, aLocale);
85 }
86
87/////////////////
88// Public methods
89/////////////////
90
91 /**
92 * Compares this BuddhistCalendar to an object reference.
93 * @param obj the object reference with which to compare
94 * @return true if this object is equal to <code>obj</code>; false otherwise
95 */
96 public boolean equals(Object obj) {
97 return obj instanceof BuddhistCalendar
98 && super.equals(obj);
99 }
100
101 /**
102 * Override hashCode.
103 * Generates the hash code for the BuddhistCalendar object
104 */
105 public int hashCode() {
106 return super.hashCode() ^ buddhistOffset;
107 }
108
109 /**
110 * Gets the value for a given time field.
111 * @param field the given time field.
112 * @return the value for the given time field.
113 */
114 public int get(int field)
115 {
116 if (field == YEAR) {
117 return super.get(field) + yearOffset;
118 }
119 return super.get(field);
120 }
121
122 /**
123 * Sets the time field with the given value.
124 * @param field the given time field.
125 * @param value the value to be set for the given time field.
126 */
127 public void set(int field, int value)
128 {
129 if (field == YEAR) {
130 super.set(field, value - yearOffset);
131 } else {
132 super.set(field, value);
133 }
134 }
135
136 /**
137 * Adds the specified (signed) amount of time to the given time field.
138 * @param field the time field.
139 * @param amount the amount of date or time to be added to the field.
140 */
141 public void add(int field, int amount)
142 {
143 int savedYearOffset = yearOffset;
144 yearOffset = 0;
145 try {
146 super.add(field, amount);
147 } finally {
148 yearOffset = savedYearOffset;
149 }
150 }
151
152 /**
153 * Add to field a signed amount without changing larger fields.
154 * A negative roll amount means to subtract from field without changing
155 * larger fields.
156 * @param field the time field.
157 * @param amount the signed amount to add to <code>field</code>.
158 */
159 public void roll(int field, int amount)
160 {
161 int savedYearOffset = yearOffset;
162 yearOffset = 0;
163 try {
164 super.roll(field, amount);
165 } finally {
166 yearOffset = savedYearOffset;
167 }
168 }
169
170 public String getDisplayName(int field, int style, Locale locale) {
171 if (field != ERA) {
172 return super.getDisplayName(field, style, locale);
173 }
174
175 // Handle Thai BuddhistCalendar specific era names
176 if (field < 0 || field >= fields.length ||
177 style < SHORT || style > LONG) {
178 throw new IllegalArgumentException();
179 }
180 if (locale == null) {
181 throw new NullPointerException();
182 }
183 ResourceBundle rb = LocaleData.getDateFormatData(locale);
184 String[] eras = rb.getStringArray(getKey(style));
185 return eras[get(field)];
186 }
187
188 public Map<String,Integer> getDisplayNames(int field, int style, Locale locale) {
189 if (field != ERA) {
190 return super.getDisplayNames(field, style, locale);
191 }
192
193 // Handle Thai BuddhistCalendar specific era names
194 if (field < 0 || field >= fields.length ||
195 style < ALL_STYLES || style > LONG) {
196 throw new IllegalArgumentException();
197 }
198 if (locale == null) {
199 throw new NullPointerException();
200 }
201 // ALL_STYLES
202 if (style == ALL_STYLES) {
203 Map<String,Integer> shortNames = getDisplayNamesImpl(field, SHORT, locale);
204 Map<String,Integer> longNames = getDisplayNamesImpl(field, LONG, locale);
205 if (shortNames == null) {
206 return longNames;
207 }
208 if (longNames != null) {
209 shortNames.putAll(longNames);
210 }
211 return shortNames;
212 }
213
214 // SHORT or LONG
215 return getDisplayNamesImpl(field, style, locale);
216 }
217
218 private Map<String,Integer> getDisplayNamesImpl(int field, int style, Locale locale) {
219 ResourceBundle rb = LocaleData.getDateFormatData(locale);
220 String[] eras = rb.getStringArray(getKey(style));
221 Map<String,Integer> map = new HashMap<String,Integer>(4);
222 for (int i = 0; i < eras.length; i++) {
223 map.put(eras[i], i);
224 }
225 return map;
226 }
227
228 private String getKey(int style) {
229 StringBuilder key = new StringBuilder();
230 key.append(BuddhistCalendar.class.getName());
231 if (style == SHORT) {
232 key.append(".short");
233 }
234 key.append(".Eras");
235 return key.toString();
236 }
237
238 /**
239 * Returns the maximum value that this field could have, given the
240 * current date. For example, with the date "Feb 3, 2540" and the
241 * <code>DAY_OF_MONTH</code> field, the actual maximum is 28; for
242 * "Feb 3, 2539" it is 29.
243 *
244 * @param field the field to determine the maximum of
245 * @return the maximum of the given field for the current date of this Calendar
246 */
247 public int getActualMaximum(int field) {
248 int savedYearOffset = yearOffset;
249 yearOffset = 0;
250 try {
251 return super.getActualMaximum(field);
252 } finally {
253 yearOffset = savedYearOffset;
254 }
255 }
256
257 public String toString() {
258 // The super class produces a String with the Gregorian year
259 // value (or '?')
260 String s = super.toString();
261 // If the YEAR field is UNSET, then return the Gregorian string.
262 if (!isSet(YEAR)) {
263 return s;
264 }
265
266 final String yearField = "YEAR=";
267 int p = s.indexOf(yearField);
268 // If the string doesn't include the year value for some
269 // reason, then return the Gregorian string.
270 if (p == -1) {
271 return s;
272 }
273 p += yearField.length();
274 StringBuilder sb = new StringBuilder(s.substring(0, p));
275 // Skip the year number
276 while (Character.isDigit(s.charAt(p++)))
277 ;
278 int year = internalGet(YEAR) + buddhistOffset;
279 sb.append(year).append(s.substring(p - 1));
280 return sb.toString();
281 }
282
283 private transient int yearOffset = buddhistOffset;
284
285}