2 *******************************************************************************
3 * Copyright (C) 2005-2011, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
7 package com.ibm.icu.util;
10 import java.util.Locale;
12 import com.ibm.icu.util.ULocale.Category;
15 * Base class for EthiopicCalendar and CopticCalendar.
17 abstract class CECalendar extends Calendar {
19 private static final long serialVersionUID = -999547623066414271L;
21 private static final int LIMITS[][] = {
22 // Minimum Greatest Least Maximum
24 { 0, 0, 1, 1 }, // ERA
25 { 1, 1, 5000000, 5000000 }, // YEAR
26 { 0, 0, 12, 12 }, // MONTH
27 { 1, 1, 52, 53 }, // WEEK_OF_YEAR
28 {/* */}, // WEEK_OF_MONTH
29 { 1, 1, 5, 30 }, // DAY_OF_MONTH
30 { 1, 1, 365, 366 }, // DAY_OF_YEAR
31 {/* */}, // DAY_OF_WEEK
32 { -1, -1, 1, 5 }, // DAY_OF_WEEK_IN_MONTH
35 {/* */}, // HOUR_OF_DAY
38 {/* */}, // MILLISECOND
39 {/* */}, // ZONE_OFFSET
40 {/* */}, // DST_OFFSET
41 { -5000000, -5000000, 5000000, 5000000 }, // YEAR_WOY
43 { -5000000, -5000000, 5000000, 5000000 }, // EXTENDED_YEAR
44 {/* */}, // JULIAN_DAY
45 {/* */}, // MILLISECONDS_IN_DAY
48 //-------------------------------------------------------------------------
50 //-------------------------------------------------------------------------
53 * Constructs a default <code>CECalendar</code> using the current time
54 * in the default time zone with the default <code>FORMAT</code> locale.
56 protected CECalendar() {
57 this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
61 * Constructs a <code>CECalendar</code> based on the current time
62 * in the given time zone with the default <code>FORMAT</code> locale.
64 * @param zone The time zone for the new calendar.
66 protected CECalendar(TimeZone zone) {
67 this(zone, ULocale.getDefault(Category.FORMAT));
71 * Constructs a <code>CECalendar</code> based on the current time
72 * in the default time zone with the given locale.
74 * @param aLocale The locale for the new calendar.
76 protected CECalendar(Locale aLocale) {
77 this(TimeZone.getDefault(), aLocale);
81 * Constructs a <code>CECalendar</code> based on the current time
82 * in the default time zone with the given locale.
84 * @param locale The locale for the new calendar.
86 protected CECalendar(ULocale locale) {
87 this(TimeZone.getDefault(), locale);
91 * Constructs a <code>CECalendar</code> based on the current time
92 * in the given time zone with the given locale.
94 * @param zone The time zone for the new calendar.
96 * @param aLocale The locale for the new calendar.
98 protected CECalendar(TimeZone zone, Locale aLocale) {
100 setTimeInMillis(System.currentTimeMillis());
104 * Constructs a <code>CECalendar</code> based on the current time
105 * in the given time zone with the given locale.
107 * @param zone The time zone for the new calendar.
109 * @param locale The locale for the new calendar.
111 protected CECalendar(TimeZone zone, ULocale locale) {
113 setTimeInMillis(System.currentTimeMillis());
117 * Constructs a <code>CECalendar</code> with the given date set
118 * in the default time zone with the default <code>FORMAT</code> locale.
120 * @param year The value used to set the calendar's {@link #YEAR YEAR} time field.
122 * @param month The value used to set the calendar's {@link #MONTH MONTH} time field.
123 * The value is 0-based. e.g., 0 for Tishri.
125 * @param date The value used to set the calendar's {@link #DATE DATE} time field.
127 protected CECalendar(int year, int month, int date) {
128 super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
129 this.set(year, month, date);
133 * Constructs a <code>CECalendar</code> with the given date set
134 * in the default time zone with the default <code>FORMAT</code> locale.
136 * @param date The date to which the new calendar is set.
138 protected CECalendar(Date date) {
139 super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
144 * Constructs a <code>CECalendar</code> with the given date
145 * and time set for the default time zone with the default <code>FORMAT</code> locale.
147 * @param year The value used to set the calendar's {@link #YEAR YEAR} time field.
148 * @param month The value used to set the calendar's {@link #MONTH MONTH} time field.
149 * The value is 0-based. e.g., 0 for Tishri.
150 * @param date The value used to set the calendar's {@link #DATE DATE} time field.
151 * @param hour The value used to set the calendar's {@link #HOUR_OF_DAY HOUR_OF_DAY} time field.
152 * @param minute The value used to set the calendar's {@link #MINUTE MINUTE} time field.
153 * @param second The value used to set the calendar's {@link #SECOND SECOND} time field.
155 protected CECalendar(int year, int month, int date, int hour,
156 int minute, int second)
158 super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
159 this.set(year, month, date, hour, minute, second);
162 //-------------------------------------------------------------------------
163 // Calendar framework
164 //-------------------------------------------------------------------------
167 * The Coptic and Ethiopic calendars differ only in their epochs.
168 * This method must be implemented by CECalendar subclasses to
169 * return the date offset from Julian.
171 abstract protected int getJDEpochOffset();
174 * Return JD of start of given month/extended year
176 protected int handleComputeMonthStart(int eyear,
179 return ceToJD(eyear, emonth, 0, getJDEpochOffset());
183 * Calculate the limit for a specified type of limit and field
185 protected int handleGetLimit(int field, int limitType) {
186 return LIMITS[field][limitType];
189 // (The following method is not called because all existing subclasses
193 * Return the number of days in the given month of the given extended
194 * year of this calendar system. Subclasses should override this
195 * method if they can provide a more correct or more efficient
196 * implementation than the default implementation in Calendar.
198 protected int handleGetMonthLength(int extendedYear, int month)
201 // The Ethiopian and Coptic calendars have 13 months, 12 of 30 days each and
202 // an intercalary month at the end of the year of 5 or 6 days, depending whether
203 // the year is a leap year or not. The Leap Year follows the same rules as the
204 // Julian Calendar so that the extra month always has six days in the year before
205 // a Julian Leap Year.
206 if ((month + 1) % 13 != 0)
208 // not intercalary month
213 // intercalary month 5 days + possible leap day
214 return ((extendedYear % 4) / 3) + 5;
220 //-------------------------------------------------------------------------
221 // Calendar framework
222 //-------------------------------------------------------------------------
225 * Convert an Coptic/Ethiopic year, month and day to a Julian day
226 * @param year the extended year
227 * @param month the month
231 public static int ceToJD(long year, int month, int day, int jdEpochOffset) {
233 // Julian<->Ethiopic algorithms from:
234 // "Calendars in Ethiopia", Berhanu Beyene, Manfred Kudlek, International Conference
235 // of Ethiopian Studies XV, Hamburg, 2003
237 // handle month > 12, < 0 (e.g. from add/set)
243 year += month/13 - 1;
244 month = month%13 + 12;
247 jdEpochOffset // difference from Julian epoch to 1,1,1
248 + 365 * year // number of days from years
249 + floorDivide(year, 4) // extra day of leap year
250 + 30 * month // number of days from months (months are 0-based)
251 + day - 1 // number of days for present month (1 based)
256 * Convert a Julian day to an Coptic/Ethiopic year, month and day
258 public static void jdToCE(int julianDay, int jdEpochOffset, int[] fields) {
259 int c4; // number of 4 year cycle (1461 days)
260 int[] r4 = new int[1]; // remainder of 4 year cycle, always positive
262 c4 = floorDivide(julianDay - jdEpochOffset, 1461, r4);
265 fields[0] = 4 * c4 + (r4[0]/365 - r4[0]/1460); // 4 * <number of 4year cycle> + <years within the last cycle>
267 int doy = (r4[0] == 1460) ? 365 : (r4[0] % 365); // days in present year
270 fields[1] = doy / 30; // 30 -> Coptic/Ethiopic month length up to 12th month
272 fields[2] = (doy % 30) + 1; // 1-based days in a month