001: /*
002: *******************************************************************************
003: * Copyright (C) 2005-2006, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */
007: package com.ibm.icu.util;
008:
009: import java.util.Date;
010: import java.util.Locale;
011:
012: /**
013: * Base class for EthiopicCalendar and CopticCalendar.
014: * @internal
015: */
016: class CECalendar extends Calendar {
017: // jdk1.4.2 serialver
018: private static final long serialVersionUID = -999547623066414271L;
019:
020: private static final int LIMITS[][] = {
021: // Minimum Greatest Least Maximum
022: // Minimum Maximum
023: { 0, 0, 1, 1 }, // ERA
024: { 1, 1, 5828963, 5838270 }, // YEAR
025: { 0, 0, 13, 13 }, // MONTH
026: { 1, 1, 52, 53 }, // WEEK_OF_YEAR
027: { 0, 0, 1, 6 }, // WEEK_OF_MONTH
028: { 1, 1, 5, 30 }, // DAY_OF_MONTH
029: { 1, 1, 365, 366 }, // DAY_OF_YEAR
030: {/* */}, // DAY_OF_WEEK
031: { -1, -1, 4, 6 }, // DAY_OF_WEEK_IN_MONTH
032: {/* */}, // AM_PM
033: {/* */}, // HOUR
034: {/* */}, // HOUR_OF_DAY
035: {/* */}, // MINUTE
036: {/* */}, // SECOND
037: {/* */}, // MILLISECOND
038: {/* */}, // ZONE_OFFSET
039: {/* */}, // DST_OFFSET
040: { -5838270, -5838270, 5828964, 5838271 }, // YEAR_WOY
041: {/* */}, // DOW_LOCAL
042: { -5838269, -5838269, 5828963, 5838270 }, // EXTENDED_YEAR
043: {/* */}, // JULIAN_DAY
044: {/* */}, // MILLISECONDS_IN_DAY
045: };
046:
047: private static final int[][] ceMONTH_COUNT = {
048: //len len2 st st2
049: { 30, 30, 0, 0 }, // Meskerem
050: { 30, 30, 30, 30 }, // Tekemt
051: { 30, 30, 60, 60 }, // Hedar
052: { 30, 30, 90, 90 }, // Tahsas
053: { 30, 30, 120, 120 }, // Ter
054: { 30, 30, 150, 150 }, // Yekatit
055: { 30, 30, 180, 180 }, // Megabit
056: { 30, 30, 210, 210 }, // Miazia
057: { 30, 30, 240, 244 }, // Genbot
058: { 30, 30, 270, 270 }, // Sene
059: { 30, 30, 300, 300 }, // Hamle
060: { 30, 30, 330, 330 }, // Nehasse
061: { 5, 6, 360, 360 } // Pwagme
062: // len length of month
063: // len2 length of month in a leap year
064: // st days in year before start of month
065: // st2 days in year before month in leap year
066: };
067:
068: // The Coptic and Ethiopic calendars differ only in their epochs.
069: // We handle this by setting the jdOffset to the difference between
070: // the Julian and Coptic or Ethiopic epoch.
071: // This value is set in the class initialization phase of the two
072: // subclasses, CopticCalendar and EthiopicCalendar
073: protected int jdEpochOffset = -1;
074:
075: protected int handleGetLimit(int field, int limitType) {
076: return LIMITS[field][limitType];
077: }
078:
079: //-------------------------------------------------------------------------
080: // Constructors...
081: //-------------------------------------------------------------------------
082:
083: /**
084: * Constructs a default <code>CECalendar</code> using the current time
085: * in the default time zone with the default locale.
086: */
087: protected CECalendar() {
088: this (TimeZone.getDefault(), ULocale.getDefault());
089: }
090:
091: /**
092: * Constructs a <code>CECalendar</code> based on the current time
093: * in the given time zone with the default locale.
094: *
095: * @param zone The time zone for the new calendar.
096: */
097: protected CECalendar(TimeZone zone) {
098: this (zone, ULocale.getDefault());
099: }
100:
101: /**
102: * Constructs a <code>CECalendar</code> based on the current time
103: * in the default time zone with the given locale.
104: *
105: * @param aLocale The locale for the new calendar.
106: */
107: protected CECalendar(Locale aLocale) {
108: this (TimeZone.getDefault(), aLocale);
109: }
110:
111: /**
112: * Constructs a <code>CECalendar</code> based on the current time
113: * in the default time zone with the given locale.
114: *
115: * @param locale The locale for the new calendar.
116: */
117: protected CECalendar(ULocale locale) {
118: this (TimeZone.getDefault(), locale);
119: }
120:
121: /**
122: * Constructs a <code>CECalendar</code> based on the current time
123: * in the given time zone with the given locale.
124: *
125: * @param zone The time zone for the new calendar.
126: *
127: * @param aLocale The locale for the new calendar.
128: */
129: protected CECalendar(TimeZone zone, Locale aLocale) {
130: super (zone, aLocale);
131: setTimeInMillis(System.currentTimeMillis());
132: }
133:
134: /**
135: * Constructs a <code>CECalendar</code> based on the current time
136: * in the given time zone with the given locale.
137: *
138: * @param zone The time zone for the new calendar.
139: *
140: * @param locale The locale for the new calendar.
141: */
142: protected CECalendar(TimeZone zone, ULocale locale) {
143: super (zone, locale);
144: setTimeInMillis(System.currentTimeMillis());
145: }
146:
147: /**
148: * Constructs a <code>CECalendar</code> with the given date set
149: * in the default time zone with the default locale.
150: *
151: * @param year The value used to set the calendar's {@link #YEAR YEAR} time field.
152: *
153: * @param month The value used to set the calendar's {@link #MONTH MONTH} time field.
154: * The value is 0-based. e.g., 0 for Tishri.
155: *
156: * @param date The value used to set the calendar's {@link #DATE DATE} time field.
157: */
158: protected CECalendar(int year, int month, int date) {
159: super (TimeZone.getDefault(), ULocale.getDefault());
160: this .set(year, month, date);
161: }
162:
163: /**
164: * Constructs a <code>CECalendar</code> with the given date set
165: * in the default time zone with the default locale.
166: *
167: * @param date The date to which the new calendar is set.
168: */
169: protected CECalendar(Date date) {
170: super (TimeZone.getDefault(), ULocale.getDefault());
171: this .setTime(date);
172: }
173:
174: /**
175: * Constructs a <code>CECalendar</code> with the given date
176: * and time set for the default time zone with the default locale.
177: *
178: * @param year The value used to set the calendar's {@link #YEAR YEAR} time field.
179: * @param month The value used to set the calendar's {@link #MONTH MONTH} time field.
180: * The value is 0-based. e.g., 0 for Tishri.
181: * @param date The value used to set the calendar's {@link #DATE DATE} time field.
182: * @param hour The value used to set the calendar's {@link #HOUR_OF_DAY HOUR_OF_DAY} time field.
183: * @param minute The value used to set the calendar's {@link #MINUTE MINUTE} time field.
184: * @param second The value used to set the calendar's {@link #SECOND SECOND} time field.
185: */
186: protected CECalendar(int year, int month, int date, int hour,
187: int minute, int second) {
188: super (TimeZone.getDefault(), ULocale.getDefault());
189: this .set(year, month, date, hour, minute, second);
190: }
191:
192: //-------------------------------------------------------------------------
193: // Calendar system Converstion methods...
194: //-------------------------------------------------------------------------
195:
196: /**
197: * @internal
198: */
199: protected int handleComputeMonthStart(int eyear, int emonth,
200: boolean useMonth) {
201: return ceToJD(eyear, emonth, 0, jdEpochOffset);
202: }
203:
204: /**
205: * @internal
206: */
207: protected int handleGetExtendedYear() {
208: int year;
209: if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR) {
210: year = internalGet(EXTENDED_YEAR, 1); // Default to year 1
211: } else {
212: year = internalGet(YEAR, 1); // Default to year 1
213: }
214: return year;
215: }
216:
217: /**
218: * @internal
219: */
220: protected void handleComputeFields(int julianDay) {
221: Integer[] date = getDateFromJD(julianDay, jdEpochOffset);
222: int _year = date[0].intValue();
223: int _month = date[1].intValue();
224: int _day = date[2].intValue();
225: int ceyear = 0;
226:
227: // Do we want to use EthiopicCalendar.AA, .AM here?
228: int era = GregorianCalendar.AD;
229: if (_year < 0) { // dlf: this is what the test says to do
230: era = GregorianCalendar.BC;
231: ceyear = 1 - _year;
232: } else {
233: ceyear = _year;
234: }
235:
236: internalSet(MONTH, _month);
237: internalSet(DAY_OF_MONTH, _day);
238: internalSet(DAY_OF_YEAR, (30 * _month) + _day);
239: internalSet(EXTENDED_YEAR, ceyear);
240: internalSet(ERA, era);
241: internalSet(YEAR, _year);
242: }
243:
244: /**
245: * @internal
246: */
247: public static int ceToJD(long year, int month, int date,
248: int jdEpochOffset) {
249:
250: // Julian<->Ethiopic algorithms from:
251: // "Calendars in Ethiopia", Berhanu Beyene, Manfred Kudlek, International Conference
252: // of Ethiopian Studies XV, Hamburg, 2003
253:
254: return (int) ((jdEpochOffset + 365) // difference from Julian epoch to 1,1,1
255: + 365 * (year - 1) // number of days from years
256: + quotient(year, 4) // extra day of leap year
257: + 30 * (month + 1) // number of days from months
258: + date // number of days for present month
259: - 31 // slack?
260: );
261: }
262:
263: /**
264: * @internal
265: * @provisional This API might change or be removed in a future release.
266: */
267: public static Integer[] getDateFromJD(int julianDay,
268: int jdEpochOffset) {
269: // 1461 is the number of days in 4 years
270: long r4 = mod(julianDay - jdEpochOffset, 1461); // number of days within a 4 year period
271: long n = mod(r4, 365) + 365 * quotient(r4, 1460); // days in present year
272:
273: long aprime = 4 // number of years in the leap year cycle
274: * quotient(julianDay - jdEpochOffset, 1461) // number of 4 year periods between epochs?
275: + quotient(r4, 365) // number of regular years?
276: - quotient(r4, 1460) // number of 4 year periods?
277: - 1;
278:
279: int _year = (int) (aprime + 1);
280: int _month = (int) (quotient(n, 30));
281: int _day = mod(n, 30) + 1;
282:
283: return new Integer[] { new Integer(_year), new Integer(_month),
284: new Integer(_day) };
285: }
286:
287: /**
288: * These utility functions can be replaced by equivalent
289: * functions from ICU if available.
290: */
291: static int mod(long i, int j) {
292: return (int) (i - (long) j * quotient(i, j));
293: }
294:
295: static int quotient(long i, int j) {
296: return (int) Math.floor((double) i / j);
297: }
298: }
|