1// © 2016 and later: Unicode, Inc. and others. 2// License & terms of use: http://www.unicode.org/copyright.html#License 3/* 4 ******************************************************************************* 5 * Copyright (C) 2005-2011, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 */ 9package com.ibm.icu.util; 10 11import java.util.Date; 12import java.util.Locale; 13 14import com.ibm.icu.util.ULocale.Category; 15 16/** 17 * Base class for EthiopicCalendar and CopticCalendar. 18 */ 19abstract class CECalendar extends Calendar { 20 // jdk1.4.2 serialver 21 private static final long serialVersionUID = -999547623066414271L; 22 23 private static final int LIMITS[][] = { 24 // Minimum Greatest Least Maximum 25 // Minimum Maximum 26 { 0, 0, 1, 1 }, // ERA 27 { 1, 1, 5000000, 5000000 }, // YEAR 28 { 0, 0, 12, 12 }, // MONTH 29 { 1, 1, 52, 53 }, // WEEK_OF_YEAR 30 {/* */}, // WEEK_OF_MONTH 31 { 1, 1, 5, 30 }, // DAY_OF_MONTH 32 { 1, 1, 365, 366 }, // DAY_OF_YEAR 33 {/* */}, // DAY_OF_WEEK 34 { -1, -1, 1, 5 }, // DAY_OF_WEEK_IN_MONTH 35 {/* */}, // AM_PM 36 {/* */}, // HOUR 37 {/* */}, // HOUR_OF_DAY 38 {/* */}, // MINUTE 39 {/* */}, // SECOND 40 {/* */}, // MILLISECOND 41 {/* */}, // ZONE_OFFSET 42 {/* */}, // DST_OFFSET 43 { -5000000, -5000000, 5000000, 5000000 }, // YEAR_WOY 44 {/* */}, // DOW_LOCAL 45 { -5000000, -5000000, 5000000, 5000000 }, // EXTENDED_YEAR 46 {/* */}, // JULIAN_DAY 47 {/* */}, // MILLISECONDS_IN_DAY 48 }; 49 50 //------------------------------------------------------------------------- 51 // Constructors... 52 //------------------------------------------------------------------------- 53 54 /** 55 * Constructs a default <code>CECalendar</code> using the current time 56 * in the default time zone with the default <code>FORMAT</code> locale. 57 */ 58 protected CECalendar() { 59 this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT)); 60 } 61 62 /** 63 * Constructs a <code>CECalendar</code> based on the current time 64 * in the given time zone with the default <code>FORMAT</code> locale. 65 * 66 * @param zone The time zone for the new calendar. 67 */ 68 protected CECalendar(TimeZone zone) { 69 this(zone, ULocale.getDefault(Category.FORMAT)); 70 } 71 72 /** 73 * Constructs a <code>CECalendar</code> based on the current time 74 * in the default time zone with the given locale. 75 * 76 * @param aLocale The locale for the new calendar. 77 */ 78 protected CECalendar(Locale aLocale) { 79 this(TimeZone.getDefault(), aLocale); 80 } 81 82 /** 83 * Constructs a <code>CECalendar</code> based on the current time 84 * in the default time zone with the given locale. 85 * 86 * @param locale The locale for the new calendar. 87 */ 88 protected CECalendar(ULocale locale) { 89 this(TimeZone.getDefault(), locale); 90 } 91 92 /** 93 * Constructs a <code>CECalendar</code> based on the current time 94 * in the given time zone with the given locale. 95 * 96 * @param zone The time zone for the new calendar. 97 * 98 * @param aLocale The locale for the new calendar. 99 */ 100 protected CECalendar(TimeZone zone, Locale aLocale) { 101 super(zone, aLocale); 102 setTimeInMillis(System.currentTimeMillis()); 103 } 104 105 /** 106 * Constructs a <code>CECalendar</code> based on the current time 107 * in the given time zone with the given locale. 108 * 109 * @param zone The time zone for the new calendar. 110 * 111 * @param locale The locale for the new calendar. 112 */ 113 protected CECalendar(TimeZone zone, ULocale locale) { 114 super(zone, locale); 115 setTimeInMillis(System.currentTimeMillis()); 116 } 117 118 /** 119 * Constructs a <code>CECalendar</code> with the given date set 120 * in the default time zone with the default <code>FORMAT</code> locale. 121 * 122 * @param year The value used to set the calendar's {@link #YEAR YEAR} time field. 123 * 124 * @param month The value used to set the calendar's {@link #MONTH MONTH} time field. 125 * The value is 0-based. e.g., 0 for Tishri. 126 * 127 * @param date The value used to set the calendar's {@link #DATE DATE} time field. 128 */ 129 protected CECalendar(int year, int month, int date) { 130 super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT)); 131 this.set(year, month, date); 132 } 133 134 /** 135 * Constructs a <code>CECalendar</code> with the given date set 136 * in the default time zone with the default <code>FORMAT</code> locale. 137 * 138 * @param date The date to which the new calendar is set. 139 */ 140 protected CECalendar(Date date) { 141 super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT)); 142 this.setTime(date); 143 } 144 145 /** 146 * Constructs a <code>CECalendar</code> with the given date 147 * and time set for the default time zone with the default <code>FORMAT</code> locale. 148 * 149 * @param year The value used to set the calendar's {@link #YEAR YEAR} time field. 150 * @param month The value used to set the calendar's {@link #MONTH MONTH} time field. 151 * The value is 0-based. e.g., 0 for Tishri. 152 * @param date The value used to set the calendar's {@link #DATE DATE} time field. 153 * @param hour The value used to set the calendar's {@link #HOUR_OF_DAY HOUR_OF_DAY} time field. 154 * @param minute The value used to set the calendar's {@link #MINUTE MINUTE} time field. 155 * @param second The value used to set the calendar's {@link #SECOND SECOND} time field. 156 */ 157 protected CECalendar(int year, int month, int date, int hour, 158 int minute, int second) 159 { 160 super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT)); 161 this.set(year, month, date, hour, minute, second); 162 } 163 164 //------------------------------------------------------------------------- 165 // Calendar framework 166 //------------------------------------------------------------------------- 167 168 /** 169 * The Coptic and Ethiopic calendars differ only in their epochs. 170 * This method must be implemented by CECalendar subclasses to 171 * return the date offset from Julian. 172 */ 173 abstract protected int getJDEpochOffset(); 174 175 /** 176 * Return JD of start of given month/extended year 177 */ 178 protected int handleComputeMonthStart(int eyear, 179 int emonth, 180 boolean useMonth) { 181 return ceToJD(eyear, emonth, 0, getJDEpochOffset()); 182 } 183 184 /** 185 * Calculate the limit for a specified type of limit and field 186 */ 187 protected int handleGetLimit(int field, int limitType) { 188 return LIMITS[field][limitType]; 189 } 190 191 // (The following method is not called because all existing subclasses 192 // override it. 193 ///CLOVER:OFF 194 /** 195 * Return the number of days in the given month of the given extended 196 * year of this calendar system. Subclasses should override this 197 * method if they can provide a more correct or more efficient 198 * implementation than the default implementation in Calendar. 199 */ 200 protected int handleGetMonthLength(int extendedYear, int month) 201 { 202 203 // The Ethiopian and Coptic calendars have 13 months, 12 of 30 days each and 204 // an intercalary month at the end of the year of 5 or 6 days, depending whether 205 // the year is a leap year or not. The Leap Year follows the same rules as the 206 // Julian Calendar so that the extra month always has six days in the year before 207 // a Julian Leap Year. 208 if ((month + 1) % 13 != 0) 209 { 210 // not intercalary month 211 return 30; 212 } 213 else 214 { 215 // intercalary month 5 days + possible leap day 216 return ((extendedYear % 4) / 3) + 5; 217 } 218 219 } 220 ///CLOVER:ON 221 222 //------------------------------------------------------------------------- 223 // Calendar framework 224 //------------------------------------------------------------------------- 225 226 /** 227 * Convert an Coptic/Ethiopic year, month and day to a Julian day 228 * @param year the extended year 229 * @param month the month 230 * @param day the day 231 * @return Julian day 232 */ 233 public static int ceToJD(long year, int month, int day, int jdEpochOffset) { 234 235 // Julian<->Ethiopic algorithms from: 236 // "Calendars in Ethiopia", Berhanu Beyene, Manfred Kudlek, International Conference 237 // of Ethiopian Studies XV, Hamburg, 2003 238 239 // handle month > 12, < 0 (e.g. from add/set) 240 if ( month >= 0 ) { 241 year += month/13; 242 month %= 13; 243 } else { 244 ++month; 245 year += month/13 - 1; 246 month = month%13 + 12; 247 } 248 return (int) ( 249 jdEpochOffset // difference from Julian epoch to 1,1,1 250 + 365 * year // number of days from years 251 + floorDivide(year, 4) // extra day of leap year 252 + 30 * month // number of days from months (months are 0-based) 253 + day - 1 // number of days for present month (1 based) 254 ); 255 } 256 257 /** 258 * Convert a Julian day to an Coptic/Ethiopic year, month and day 259 */ 260 public static void jdToCE(int julianDay, int jdEpochOffset, int[] fields) { 261 int c4; // number of 4 year cycle (1461 days) 262 int[] r4 = new int[1]; // remainder of 4 year cycle, always positive 263 264 c4 = floorDivide(julianDay - jdEpochOffset, 1461, r4); 265 266 // exteded year 267 fields[0] = 4 * c4 + (r4[0]/365 - r4[0]/1460); // 4 * <number of 4year cycle> + <years within the last cycle> 268 269 int doy = (r4[0] == 1460) ? 365 : (r4[0] % 365); // days in present year 270 271 // month 272 fields[1] = doy / 30; // 30 -> Coptic/Ethiopic month length up to 12th month 273 // day 274 fields[2] = (doy % 30) + 1; // 1-based days in a month 275 } 276} 277