1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html 4 /* 5 ******************************************************************************* 6 * Copyright (C) 1996-2016, International Business Machines Corporation and * 7 * others. All Rights Reserved. * 8 ******************************************************************************* 9 */ 10 package android.icu.util; 11 import java.io.IOException; 12 import java.io.ObjectInputStream; 13 import java.util.Date; 14 import java.util.Locale; 15 16 import android.icu.impl.CalendarAstronomer; 17 import android.icu.impl.CalendarCache; 18 import android.icu.impl.CalendarUtil; 19 import android.icu.util.ULocale.Category; 20 21 /** 22 * <code>IslamicCalendar</code> is a subclass of <code>Calendar</code> 23 * that that implements the Islamic civil and religious calendars. It 24 * is used as the civil calendar in most of the Arab world and the 25 * liturgical calendar of the Islamic faith worldwide. This calendar 26 * is also known as the "Hijri" calendar, since it starts at the time 27 * of Mohammed's emigration (or "hijra") to Medinah on Thursday, 28 * July 15, 622 AD (Julian). 29 * <p> 30 * The Islamic calendar is strictly lunar, and thus an Islamic year of twelve 31 * lunar months does not correspond to the solar year used by most other 32 * calendar systems, including the Gregorian. An Islamic year is, on average, 33 * about 354 days long, so each successive Islamic year starts about 11 days 34 * earlier in the corresponding Gregorian year. 35 * <p> 36 * Each month of the calendar starts when the new moon's crescent is visible 37 * at sunset. However, in order to keep the time fields in this class 38 * synchronized with those of the other calendars and with local clock time, 39 * we treat days and months as beginning at midnight, 40 * roughly 6 hours after the corresponding sunset. 41 * <p> 42 * There are three main variants of the Islamic calendar in existence. The first 43 * is the <em>civil</em> calendar, which uses a fixed cycle of alternating 29- 44 * and 30-day months, with a leap day added to the last month of 11 out of 45 * every 30 years. This calendar is easily calculated and thus predictable in 46 * advance, so it is used as the civil calendar in a number of Arab countries. 47 * This is the default behavior of a newly-created <code>IslamicCalendar</code> 48 * object. 49 * <p> 50 * The Islamic <em>religious</em> calendar and Saudi Arabia's <em>Umm al-Qura</em> 51 * calendar, however, are based on the <em>observation</em> of the crescent moon. 52 * It is thus affected by the position at which the 53 * observations are made, seasonal variations in the time of sunset, the 54 * eccentricities of the moon's orbit, and even the weather at the observation 55 * site. This makes it impossible to calculate in advance, and it causes the 56 * start of a month in the religious calendar to differ from the civil calendar 57 * by up to three days. 58 * <p> 59 * Using astronomical calculations for the position of the sun and moon, the 60 * moon's illumination, and other factors, it is possible to determine the start 61 * of a lunar month with a fairly high degree of certainty. However, these 62 * calculations are extremely complicated and thus slow, so most algorithms, 63 * including the one used here, are only approximations of the true astronomical 64 * calculations. At present, the approximations used in this class are fairly 65 * simplistic; they will be improved in later versions of the code. 66 * <p> 67 * Like the Islamic religious calendar, <em>Umm al-Qura</em> is also based 68 * on the sighting method of the crescent moon but is standardized by Saudi Arabia. 69 * <p> 70 * The fixed-cycle <em>civil</em> calendar is used. 71 * <p> 72 * This class should not be subclassed.</p> 73 * <p> 74 * IslamicCalendar usually should be instantiated using 75 * {@link android.icu.util.Calendar#getInstance(ULocale)} passing in a <code>ULocale</code> 76 * with the tag <code>"@calendar=islamic"</code> or <code>"@calendar=islamic-civil"</code> 77 * or <code>"@calendar=islamic-umalqura"</code>.</p> 78 * 79 * @see android.icu.util.GregorianCalendar 80 * @see android.icu.util.Calendar 81 * 82 * @author Laura Werner 83 * @author Alan Liu 84 */ 85 public class IslamicCalendar extends Calendar { 86 // jdk1.4.2 serialver 87 private static final long serialVersionUID = -6253365474073869325L; 88 89 //------------------------------------------------------------------------- 90 // Constants... 91 //------------------------------------------------------------------------- 92 93 /** 94 * Constant for Muharram, the 1st month of the Islamic year. 95 */ 96 public static final int MUHARRAM = 0; 97 98 /** 99 * Constant for Safar, the 2nd month of the Islamic year. 100 */ 101 public static final int SAFAR = 1; 102 103 /** 104 * Constant for Rabi' al-awwal (or Rabi' I), the 3rd month of the Islamic year. 105 */ 106 public static final int RABI_1 = 2; 107 108 /** 109 * Constant for Rabi' al-thani or (Rabi' II), the 4th month of the Islamic year. 110 */ 111 public static final int RABI_2 = 3; 112 113 /** 114 * Constant for Jumada al-awwal or (Jumada I), the 5th month of the Islamic year. 115 */ 116 public static final int JUMADA_1 = 4; 117 118 /** 119 * Constant for Jumada al-thani or (Jumada II), the 6th month of the Islamic year. 120 */ 121 public static final int JUMADA_2 = 5; 122 123 /** 124 * Constant for Rajab, the 7th month of the Islamic year. 125 */ 126 public static final int RAJAB = 6; 127 128 /** 129 * Constant for Sha'ban, the 8th month of the Islamic year. 130 */ 131 public static final int SHABAN = 7; 132 133 /** 134 * Constant for Ramadan, the 9th month of the Islamic year. 135 */ 136 public static final int RAMADAN = 8; 137 138 /** 139 * Constant for Shawwal, the 10th month of the Islamic year. 140 */ 141 public static final int SHAWWAL = 9; 142 143 /** 144 * Constant for Dhu al-Qi'dah, the 11th month of the Islamic year. 145 */ 146 public static final int DHU_AL_QIDAH = 10; 147 148 /** 149 * Constant for Dhu al-Hijjah, the 12th month of the Islamic year. 150 */ 151 public static final int DHU_AL_HIJJAH = 11; 152 153 154 private static final long HIJRA_MILLIS = -42521587200000L; // 7/16/622 AD 00:00 155 156 /** 157 * Friday EPOC 158 */ 159 private static final long CIVIL_EPOC = 1948440; // CE 622 July 16 Friday (Julian calendar) / CE 622 July 19 (Gregorian calendar) 160 /** 161 * Thursday EPOC 162 */ 163 private static final long ASTRONOMICAL_EPOC = 1948439; // CE 622 July 15 Thursday (Julian calendar) 164 165 //------------------------------------------------------------------------- 166 // Constructors... 167 //------------------------------------------------------------------------- 168 169 /** 170 * Constructs a default <code>IslamicCalendar</code> using the current time 171 * in the default time zone with the default <code>FORMAT</code> locale. 172 * @see Category#FORMAT 173 */ IslamicCalendar()174 public IslamicCalendar() 175 { 176 this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT)); 177 } 178 179 /** 180 * Constructs an <code>IslamicCalendar</code> based on the current time 181 * in the given time zone with the default <code>FORMAT</code> locale. 182 * @param zone the given time zone. 183 * @see Category#FORMAT 184 */ IslamicCalendar(TimeZone zone)185 public IslamicCalendar(TimeZone zone) 186 { 187 this(zone, ULocale.getDefault(Category.FORMAT)); 188 } 189 190 /** 191 * Constructs an <code>IslamicCalendar</code> based on the current time 192 * in the default time zone with the given locale. 193 * 194 * @param aLocale the given locale. 195 */ IslamicCalendar(Locale aLocale)196 public IslamicCalendar(Locale aLocale) 197 { 198 this(TimeZone.forLocaleOrDefault(aLocale), aLocale); 199 } 200 201 /** 202 * Constructs an <code>IslamicCalendar</code> based on the current time 203 * in the default time zone with the given locale. 204 * 205 * @param locale the given ulocale. 206 */ IslamicCalendar(ULocale locale)207 public IslamicCalendar(ULocale locale) 208 { 209 this(TimeZone.forULocaleOrDefault(locale), locale); 210 } 211 212 /** 213 * Constructs an <code>IslamicCalendar</code> based on the current time 214 * in the given time zone with the given locale. 215 * 216 * @param zone the given time zone. 217 * @param aLocale the given locale. 218 */ IslamicCalendar(TimeZone zone, Locale aLocale)219 public IslamicCalendar(TimeZone zone, Locale aLocale) 220 { 221 this(zone, ULocale.forLocale(aLocale)); 222 } 223 224 /** 225 * Constructs an <code>IslamicCalendar</code> based on the current time 226 * in the given time zone with the given locale. 227 * 228 * @param zone the given time zone. 229 * @param locale the given ulocale. 230 */ IslamicCalendar(TimeZone zone, ULocale locale)231 public IslamicCalendar(TimeZone zone, ULocale locale) 232 { 233 super(zone, locale); 234 setCalcTypeForLocale(locale); 235 setTimeInMillis(System.currentTimeMillis()); 236 } 237 238 /** 239 * Constructs an <code>IslamicCalendar</code> with the given date set 240 * in the default time zone with the default <code>FORMAT</code> locale. 241 * 242 * @param date The date to which the new calendar is set. 243 * @see Category#FORMAT 244 */ IslamicCalendar(Date date)245 public IslamicCalendar(Date date) { 246 super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT)); 247 this.setTime(date); 248 } 249 250 /** 251 * Constructs an <code>IslamicCalendar</code> with the given date set 252 * in the default time zone with the default <code>FORMAT</code> locale. 253 * 254 * @param year the value used to set the {@link #YEAR YEAR} time field in the calendar. 255 * @param month the value used to set the {@link #MONTH MONTH} time field in the calendar. 256 * Note that the month value is 0-based. e.g., 0 for Muharram. 257 * @param date the value used to set the {@link #DATE DATE} time field in the calendar. 258 * @see Category#FORMAT 259 */ IslamicCalendar(int year, int month, int date)260 public IslamicCalendar(int year, int month, int date) 261 { 262 super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT)); 263 this.set(Calendar.YEAR, year); 264 this.set(Calendar.MONTH, month); 265 this.set(Calendar.DATE, date); 266 } 267 268 /** 269 * Constructs an <code>IslamicCalendar</code> with the given date 270 * and time set for the default time zone with the default <code>FORMAT</code> locale. 271 * 272 * @param year the value used to set the {@link #YEAR YEAR} time field in the calendar. 273 * @param month the value used to set the {@link #MONTH MONTH} time field in the calendar. 274 * Note that the month value is 0-based. e.g., 0 for Muharram. 275 * @param date the value used to set the {@link #DATE DATE} time field in the calendar. 276 * @param hour the value used to set the {@link #HOUR_OF_DAY HOUR_OF_DAY} time field 277 * in the calendar. 278 * @param minute the value used to set the {@link #MINUTE MINUTE} time field 279 * in the calendar. 280 * @param second the value used to set the {@link #SECOND SECOND} time field 281 * in the calendar. 282 * @see Category#FORMAT 283 */ IslamicCalendar(int year, int month, int date, int hour, int minute, int second)284 public IslamicCalendar(int year, int month, int date, int hour, 285 int minute, int second) 286 { 287 super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT)); 288 this.set(Calendar.YEAR, year); 289 this.set(Calendar.MONTH, month); 290 this.set(Calendar.DATE, date); 291 this.set(Calendar.HOUR_OF_DAY, hour); 292 this.set(Calendar.MINUTE, minute); 293 this.set(Calendar.SECOND, second); 294 } 295 296 /** 297 * Determines whether this object uses the fixed-cycle Islamic civil calendar 298 * or an approximation of the religious, astronomical calendar. 299 * 300 * @param beCivil <code>true</code> to use the civil calendar, 301 * <code>false</code> to use the astronomical calendar. 302 * @apiNote <strong>Discouraged:</strong> ICU 57 use setCalculationType(CalculationType) instead 303 * @hide unsupported on Android 304 */ setCivil(boolean beCivil)305 public void setCivil(boolean beCivil) 306 { 307 civil = beCivil; 308 309 if (beCivil && cType != CalculationType.ISLAMIC_CIVIL) { 310 // The fields of the calendar will become invalid, because the calendar 311 // rules are different 312 long m = getTimeInMillis(); 313 cType = CalculationType.ISLAMIC_CIVIL; 314 clear(); 315 setTimeInMillis(m); 316 } else if(!beCivil && cType != CalculationType.ISLAMIC) { 317 // The fields of the calendar will become invalid, because the calendar 318 // rules are different 319 long m = getTimeInMillis(); 320 cType = CalculationType.ISLAMIC; 321 clear(); 322 setTimeInMillis(m); 323 } 324 } 325 326 /** 327 * Returns <code>true</code> if this object is using the fixed-cycle civil 328 * calendar, or <code>false</code> if using the religious, astronomical 329 * calendar. 330 * @apiNote <strong>Discouraged:</strong> ICU 57 use getCalculationType() instead 331 * @hide unsupported on Android 332 */ isCivil()333 public boolean isCivil() { 334 if(cType == CalculationType.ISLAMIC_CIVIL) { 335 return true; 336 } 337 return false; 338 } 339 340 //------------------------------------------------------------------------- 341 // Minimum / Maximum access functions 342 //------------------------------------------------------------------------- 343 344 // Note: Current IslamicCalendar implementation does not work 345 // well with negative years. 346 347 private static final int LIMITS[][] = { 348 // Minimum Greatest Least Maximum 349 // Minimum Maximum 350 { 0, 0, 0, 0}, // ERA 351 { 1, 1, 5000000, 5000000}, // YEAR 352 { 0, 0, 11, 11}, // MONTH 353 { 1, 1, 50, 51}, // WEEK_OF_YEAR 354 {/* */}, // WEEK_OF_MONTH 355 { 1, 1, 29, 30}, // DAY_OF_MONTH 356 { 1, 1, 354, 355}, // DAY_OF_YEAR 357 {/* */}, // DAY_OF_WEEK 358 { -1, -1, 5, 5}, // DAY_OF_WEEK_IN_MONTH 359 {/* */}, // AM_PM 360 {/* */}, // HOUR 361 {/* */}, // HOUR_OF_DAY 362 {/* */}, // MINUTE 363 {/* */}, // SECOND 364 {/* */}, // MILLISECOND 365 {/* */}, // ZONE_OFFSET 366 {/* */}, // DST_OFFSET 367 { 1, 1, 5000000, 5000000}, // YEAR_WOY 368 {/* */}, // DOW_LOCAL 369 { 1, 1, 5000000, 5000000}, // EXTENDED_YEAR 370 {/* */}, // JULIAN_DAY 371 {/* */}, // MILLISECONDS_IN_DAY 372 }; 373 374 /* 375 * bit map array where a bit turned on represents a month with 30 days. 376 */ 377 private static final int[] UMALQURA_MONTHLENGTH = { 378 //* 1300 -1302 */ "1010 1010 1010", "1101 0101 0100", "1110 1100 1001", 379 0x0AAA, 0x0D54, 0x0EC9, 380 //* 1303 -1307 */ "0110 1101 0100", "0110 1110 1010", "0011 0110 1100", "1010 1010 1101", "0101 0101 0101", 381 0x06D4, 0x06EA, 0x036C, 0x0AAD, 0x0555, 382 //* 1308 -1312 */ "0110 1010 1001", "0111 1001 0010", "1011 1010 1001", "0101 1101 0100", "1010 1101 1010", 383 0x06A9, 0x0792, 0x0BA9, 0x05D4, 0x0ADA, 384 //* 1313 -1317 */ "0101 0101 1100", "1101 0010 1101", "0110 1001 0101", "0111 0100 1010", "1011 0101 0100", 385 0x055C, 0x0D2D, 0x0695, 0x074A, 0x0B54, 386 //* 1318 -1322 */ "1011 0110 1010", "0101 1010 1101", "0100 1010 1110", "1010 0100 1111", "0101 0001 0111", 387 0x0B6A, 0x05AD, 0x04AE, 0x0A4F, 0x0517, 388 //* 1323 -1327 */ "0110 1000 1011", "0110 1010 0101", "1010 1101 0101", "0010 1101 0110", "1001 0101 1011", 389 0x068B, 0x06A5, 0x0AD5, 0x02D6, 0x095B, 390 //* 1328 -1332 */ "0100 1001 1101", "1010 0100 1101", "1101 0010 0110", "1101 1001 0101", "0101 1010 1100", 391 0x049D, 0x0A4D, 0x0D26, 0x0D95, 0x05AC, 392 //* 1333 -1337 */ "1001 1011 0110", "0010 1011 1010", "1010 0101 1011", "0101 0010 1011", "1010 1001 0101", 393 0x09B6, 0x02BA, 0x0A5B, 0x052B, 0x0A95, 394 //* 1338 -1342 */ "0110 1100 1010", "1010 1110 1001", "0010 1111 0100", "1001 0111 0110", "0010 1011 0110", 395 0x06CA, 0x0AE9, 0x02F4, 0x0976, 0x02B6, 396 //* 1343 -1347 */ "1001 0101 0110", "1010 1100 1010", "1011 1010 0100", "1011 1101 0010", "0101 1101 1001", 397 0x0956, 0x0ACA, 0x0BA4, 0x0BD2, 0x05D9, 398 //* 1348 -1352 */ "0010 1101 1100", "1001 0110 1101", "0101 0100 1101", "1010 1010 0101", "1011 0101 0010", 399 0x02DC, 0x096D, 0x054D, 0x0AA5, 0x0B52, 400 //* 1353 -1357 */ "1011 1010 0101", "0101 1011 0100", "1001 1011 0110", "0101 0101 0111", "0010 1001 0111", 401 0x0BA5, 0x05B4, 0x09B6, 0x0557, 0x0297, 402 //* 1358 -1362 */ "0101 0100 1011", "0110 1010 0011", "0111 0101 0010", "1011 0110 0101", "0101 0110 1010", 403 0x054B, 0x06A3, 0x0752, 0x0B65, 0x056A, 404 //* 1363 -1367 */ "1010 1010 1011", "0101 0010 1011", "1100 1001 0101", "1101 0100 1010", "1101 1010 0101", 405 0x0AAB, 0x052B, 0x0C95, 0x0D4A, 0x0DA5, 406 //* 1368 -1372 */ "0101 1100 1010", "1010 1101 0110", "1001 0101 0111", "0100 1010 1011", "1001 0100 1011", 407 0x05CA, 0x0AD6, 0x0957, 0x04AB, 0x094B, 408 //* 1373 -1377 */ "1010 1010 0101", "1011 0101 0010", "1011 0110 1010", "0101 0111 0101", "0010 0111 0110", 409 0x0AA5, 0x0B52, 0x0B6A, 0x0575, 0x0276, 410 //* 1378 -1382 */ "1000 1011 0111", "0100 0101 1011", "0101 0101 0101", "0101 1010 1001", "0101 1011 0100", 411 0x08B7, 0x045B, 0x0555, 0x05A9, 0x05B4, 412 //* 1383 -1387 */ "1001 1101 1010", "0100 1101 1101", "0010 0110 1110", "1001 0011 0110", "1010 1010 1010", 413 0x09DA, 0x04DD, 0x026E, 0x0936, 0x0AAA, 414 //* 1388 -1392 */ "1101 0101 0100", "1101 1011 0010", "0101 1101 0101", "0010 1101 1010", "1001 0101 1011", 415 0x0D54, 0x0DB2, 0x05D5, 0x02DA, 0x095B, 416 //* 1393 -1397 */ "0100 1010 1011", "1010 0101 0101", "1011 0100 1001", "1011 0110 0100", "1011 0111 0001", 417 0x04AB, 0x0A55, 0x0B49, 0x0B64, 0x0B71, 418 //* 1398 -1402 */ "0101 1011 0100", "1010 1011 0101", "1010 0101 0101", "1101 0010 0101", "1110 1001 0010", 419 0x05B4, 0x0AB5, 0x0A55, 0x0D25, 0x0E92, 420 //* 1403 -1407 */ "1110 1100 1001", "0110 1101 0100", "1010 1110 1001", "1001 0110 1011", "0100 1010 1011", 421 0x0EC9, 0x06D4, 0x0AE9, 0x096B, 0x04AB, 422 //* 1408 -1412 */ "1010 1001 0011", "1101 0100 1001", "1101 1010 0100", "1101 1011 0010", "1010 1011 1001", 423 0x0A93, 0x0D49, 0x0DA4, 0x0DB2, 0x0AB9, 424 //* 1413 -1417 */ "0100 1011 1010", "1010 0101 1011", "0101 0010 1011", "1010 1001 0101", "1011 0010 1010", 425 0x04BA, 0x0A5B, 0x052B, 0x0A95, 0x0B2A, 426 //* 1418 -1422 */ "1011 0101 0101", "0101 0101 1100", "0100 1011 1101", "0010 0011 1101", "1001 0001 1101", 427 0x0B55, 0x055C, 0x04BD, 0x023D, 0x091D, 428 //* 1423 -1427 */ "1010 1001 0101", "1011 0100 1010", "1011 0101 1010", "0101 0110 1101", "0010 1011 0110", 429 0x0A95, 0x0B4A, 0x0B5A, 0x056D, 0x02B6, 430 //* 1428 -1432 */ "1001 0011 1011", "0100 1001 1011", "0110 0101 0101", "0110 1010 1001", "0111 0101 0100", 431 0x093B, 0x049B, 0x0655, 0x06A9, 0x0754, 432 //* 1433 -1437 */ "1011 0110 1010", "0101 0110 1100", "1010 1010 1101", "0101 0101 0101", "1011 0010 1001", 433 0x0B6A, 0x056C, 0x0AAD, 0x0555, 0x0B29, 434 //* 1438 -1442 */ "1011 1001 0010", "1011 1010 1001", "0101 1101 0100", "1010 1101 1010", "0101 0101 1010", 435 0x0B92, 0x0BA9, 0x05D4, 0x0ADA, 0x055A, 436 //* 1443 -1447 */ "1010 1010 1011", "0101 1001 0101", "0111 0100 1001", "0111 0110 0100", "1011 1010 1010", 437 0x0AAB, 0x0595, 0x0749, 0x0764, 0x0BAA, 438 //* 1448 -1452 */ "0101 1011 0101", "0010 1011 0110", "1010 0101 0110", "1110 0100 1101", "1011 0010 0101", 439 0x05B5, 0x02B6, 0x0A56, 0x0E4D, 0x0B25, 440 //* 1453 -1457 */ "1011 0101 0010", "1011 0110 1010", "0101 1010 1101", "0010 1010 1110", "1001 0010 1111", 441 0x0B52, 0x0B6A, 0x05AD, 0x02AE, 0x092F, 442 //* 1458 -1462 */ "0100 1001 0111", "0110 0100 1011", "0110 1010 0101", "0110 1010 1100", "1010 1101 0110", 443 0x0497, 0x064B, 0x06A5, 0x06AC, 0x0AD6, 444 //* 1463 -1467 */ "0101 0101 1101", "0100 1001 1101", "1010 0100 1101", "1101 0001 0110", "1101 1001 0101", 445 0x055D, 0x049D, 0x0A4D, 0x0D16, 0x0D95, 446 //* 1468 -1472 */ "0101 1010 1010", "0101 1011 0101", "0010 1101 1010", "1001 0101 1011", "0100 1010 1101", 447 0x05AA, 0x05B5, 0x02DA, 0x095B, 0x04AD, 448 //* 1473 -1477 */ "0101 1001 0101", "0110 1100 1010", "0110 1110 0100", "1010 1110 1010", "0100 1111 0101", 449 0x0595, 0x06CA, 0x06E4, 0x0AEA, 0x04F5, 450 //* 1478 -1482 */ "0010 1011 0110", "1001 0101 0110", "1010 1010 1010", "1011 0101 0100", "1011 1101 0010", 451 0x02B6, 0x0956, 0x0AAA, 0x0B54, 0x0BD2, 452 //* 1483 -1487 */ "0101 1101 1001", "0010 1110 1010", "1001 0110 1101", "0100 1010 1101", "1010 1001 0101", 453 0x05D9, 0x02EA, 0x096D, 0x04AD, 0x0A95, 454 //* 1488 -1492 */ "1011 0100 1010", "1011 1010 0101", "0101 1011 0010", "1001 1011 0101", "0100 1101 0110", 455 0x0B4A, 0x0BA5, 0x05B2, 0x09B5, 0x04D6, 456 //* 1493 -1497 */ "1010 1001 0111", "0101 0100 0111", "0110 1001 0011", "0111 0100 1001", "1011 0101 0101", 457 0x0A97, 0x0547, 0x0693, 0x0749, 0x0B55, 458 //* 1498 -1508 */ "0101 0110 1010", "1010 0110 1011", "0101 0010 1011", "1010 1000 1011", "1101 0100 0110", "1101 1010 0011", "0101 1100 1010", "1010 1101 0110", "0100 1101 1011", "0010 0110 1011", "1001 0100 1011", 459 0x056A, 0x0A6B, 0x052B, 0x0A8B, 0x0D46, 0x0DA3, 0x05CA, 0x0AD6, 0x04DB, 0x026B, 0x094B, 460 //* 1509 -1519 */ "1010 1010 0101", "1011 0101 0010", "1011 0110 1001", "0101 0111 0101", "0001 0111 0110", "1000 1011 0111", "0010 0101 1011", "0101 0010 1011", "0101 0110 0101", "0101 1011 0100", "1001 1101 1010", 461 0x0AA5, 0x0B52, 0x0B69, 0x0575, 0x0176, 0x08B7, 0x025B, 0x052B, 0x0565, 0x05B4, 0x09DA, 462 //* 1520 -1530 */ "0100 1110 1101", "0001 0110 1101", "1000 1011 0110", "1010 1010 0110", "1101 0101 0010", "1101 1010 1001", "0101 1101 0100", "1010 1101 1010", "1001 0101 1011", "0100 1010 1011", "0110 0101 0011", 463 0x04ED, 0x016D, 0x08B6, 0x0AA6, 0x0D52, 0x0DA9, 0x05D4, 0x0ADA, 0x095B, 0x04AB, 0x0653, 464 //* 1531 -1541 */ "0111 0010 1001", "0111 0110 0010", "1011 1010 1001", "0101 1011 0010", "1010 1011 0101", "0101 0101 0101", "1011 0010 0101", "1101 1001 0010", "1110 1100 1001", "0110 1101 0010", "1010 1110 1001", 465 0x0729, 0x0762, 0x0BA9, 0x05B2, 0x0AB5, 0x0555, 0x0B25, 0x0D92, 0x0EC9, 0x06D2, 0x0AE9, 466 //* 1542 -1552 */ "0101 0110 1011", "0100 1010 1011", "1010 0101 0101", "1101 0010 1001", "1101 0101 0100", "1101 1010 1010", "1001 1011 0101", "0100 1011 1010", "1010 0011 1011", "0100 1001 1011", "1010 0100 1101", 467 0x056B, 0x04AB, 0x0A55, 0x0D29, 0x0D54, 0x0DAA, 0x09B5, 0x04BA, 0x0A3B, 0x049B, 0x0A4D, 468 //* 1553 -1563 */ "1010 1010 1010", "1010 1101 0101", "0010 1101 1010", "1001 0101 1101", "0100 0101 1110", "1010 0010 1110", "1100 1001 1010", "1101 0101 0101", "0110 1011 0010", "0110 1011 1001", "0100 1011 1010", 469 0x0AAA, 0x0AD5, 0x02DA, 0x095D, 0x045E, 0x0A2E, 0x0C9A, 0x0D55, 0x06B2, 0x06B9, 0x04BA, 470 //* 1564 -1574 */ "1010 0101 1101", "0101 0010 1101", "1010 1001 0101", "1011 0101 0010", "1011 1010 1000", "1011 1011 0100", "0101 1011 1001", "0010 1101 1010", "1001 0101 1010", "1011 0100 1010", "1101 1010 0100", 471 0x0A5D, 0x052D, 0x0A95, 0x0B52, 0x0BA8, 0x0BB4, 0x05B9, 0x02DA, 0x095A, 0x0B4A, 0x0DA4, 472 //* 1575 -1585 */ "1110 1101 0001", "0110 1110 1000", "1011 0110 1010", "0101 0110 1101", "0101 0011 0101", "0110 1001 0101", "1101 0100 1010", "1101 1010 1000", "1101 1101 0100", "0110 1101 1010", "0101 0101 1011", 473 0x0ED1, 0x06E8, 0x0B6A, 0x056D, 0x0535, 0x0695, 0x0D4A, 0x0DA8, 0x0DD4, 0x06DA, 0x055B, 474 //* 1586 -1596 */ "0010 1001 1101", "0110 0010 1011", "1011 0001 0101", "1011 0100 1010", "1011 1001 0101", "0101 1010 1010", "1010 1010 1110", "1001 0010 1110", "1100 1000 1111", "0101 0010 0111", "0110 1001 0101", 475 0x029D, 0x062B, 0x0B15, 0x0B4A, 0x0B95, 0x05AA, 0x0AAE, 0x092E, 0x0C8F, 0x0527, 0x0695, 476 //* 1597 -1600 */ "0110 1010 1010", "1010 1101 0110", "0101 0101 1101", "0010 1001 1101", }; 477 0x06AA, 0x0AD6, 0x055D, 0x029D 478 }; 479 480 private static final int UMALQURA_YEAR_START = 1300; 481 private static final int UMALQURA_YEAR_END = 1600; 482 483 484 /** 485 */ 486 @Override handleGetLimit(int field, int limitType)487 protected int handleGetLimit(int field, int limitType) { 488 return LIMITS[field][limitType]; 489 } 490 491 //------------------------------------------------------------------------- 492 // Assorted calculation utilities 493 // 494 495 // we could compress this down more if we need to 496 private static final byte[] UMALQURA_YEAR_START_ESTIMATE_FIX = { 497 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, // 1300.. 498 -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, // 1310.. 499 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, // 1320.. 500 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // 1330.. 501 0, 0, 1, 0, 0, -1, -1, 0, 0, 0, // 1340.. 502 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, // 1350.. 503 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, // 1360.. 504 0, 1, 1, 0, 0, -1, 0, 1, 0, 1, // 1370.. 505 1, 0, 0, -1, 0, 1, 0, 0, 0, -1, // 1380.. 506 0, 1, 0, 1, 0, 0, 0, -1, 0, 0, // 1390.. 507 0, 0, -1, -1, 0, -1, 0, 1, 0, 0, // 1400.. 508 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, // 1410.. 509 0, 1, 0, 0, -1, -1, 0, 0, 0, 1, // 1420.. 510 0, 0, -1, -1, 0, -1, 0, 0, -1, -1, // 1430.. 511 0, -1, 0, -1, 0, 0, -1, -1, 0, 0, // 1440.. 512 0, 0, 0, 0, -1, 0, 1, 0, 1, 1, // 1450.. 513 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, // 1460.. 514 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, // 1470.. 515 0, -1, -1, 0, 0, 0, 1, 0, 0, 0, // 1480.. 516 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, // 1490.. 517 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, // 1500.. 518 0, -1, 0, 1, 0, 1, 1, 0, 0, 0, // 1510.. 519 0, 1, 0, 0, 0, -1, 0, 0, 0, 1, // 1520.. 520 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, // 1530.. 521 0, -1, 0, 1, 0, 0, 0, -1, 0, 1, // 1540.. 522 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, // 1550.. 523 -1, 0, 0, 0, 0, 1, 0, 0, 0, -1, // 1560.. 524 0, 0, 0, 0, -1, -1, 0, -1, 0, 1, // 1570.. 525 0, 0, -1, -1, 0, 0, 1, 1, 0, 0, // 1580.. 526 -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, // 1590.. 527 1 // 1600 528 }; 529 530 // Unused code - Alan 2003-05 531 // /** 532 // * Find the day of the week for a given day 533 // * 534 // * @param day The # of days since the start of the Islamic calendar. 535 // */ 536 // // private and uncalled, perhaps not used yet? 537 // private static final int absoluteDayToDayOfWeek(long day) 538 // { 539 // // Calculate the day of the week. 540 // // This relies on the fact that the epoch was a Thursday. 541 // int dayOfWeek = (int)(day + THURSDAY) % 7 + SUNDAY; 542 // if (dayOfWeek < 0) { 543 // dayOfWeek += 7; 544 // } 545 // return dayOfWeek; 546 // } 547 548 /** 549 * Determine whether a year is a leap year in the Islamic civil calendar 550 */ civilLeapYear(int year)551 private final static boolean civilLeapYear(int year) 552 { 553 return (14 + 11 * year) % 30 < 11; 554 } 555 556 /** 557 * Return the day # on which the given year starts. Days are counted 558 * from the Hijri epoch, origin 0. 559 */ yearStart(int year)560 private long yearStart(int year) { 561 long ys = 0; 562 if (cType == CalculationType.ISLAMIC_CIVIL 563 || cType == CalculationType.ISLAMIC_TBLA 564 || (cType == CalculationType.ISLAMIC_UMALQURA && (year < UMALQURA_YEAR_START || year > UMALQURA_YEAR_END))) { 565 ys = (year-1)*354 + (long)Math.floor((3+11*year)/30.0); 566 } else if(cType == CalculationType.ISLAMIC) { 567 ys = trueMonthStart(12*(year-1)); 568 } else if(cType == CalculationType.ISLAMIC_UMALQURA){ 569 year -= UMALQURA_YEAR_START; 570 // rounded least-squares fit of the dates previously calculated from UMALQURA_MONTHLENGTH iteration 571 int yrStartLinearEstimate = (int)((354.36720 * year) + 460322.05 + 0.5); 572 // need a slight correction to some 573 ys = yrStartLinearEstimate + UMALQURA_YEAR_START_ESTIMATE_FIX[year]; 574 } 575 return ys; 576 } 577 578 /** 579 * Return the day # on which the given month starts. Days are counted 580 * from the Hijri epoch, origin 0. 581 * 582 * @param year The hijri year 583 * @param month The hijri month, 0-based 584 */ monthStart(int year, int month)585 private long monthStart(int year, int month) { 586 // Normalize year/month in case month is outside the normal bounds, which may occur 587 // in the case of an add operation 588 int realYear = year + month / 12; 589 int realMonth = month % 12; 590 long ms = 0; 591 if (cType == CalculationType.ISLAMIC_CIVIL 592 || cType == CalculationType.ISLAMIC_TBLA 593 || (cType == CalculationType.ISLAMIC_UMALQURA && year < UMALQURA_YEAR_START )) { 594 ms = (long)Math.ceil(29.5*realMonth) 595 + (realYear-1)*354 + (long)Math.floor((3+11*realYear)/30.0); 596 } else if(cType == CalculationType.ISLAMIC) { 597 ms = trueMonthStart(12*(realYear-1) + realMonth); 598 } else if(cType == CalculationType.ISLAMIC_UMALQURA) { 599 ms = yearStart(year); 600 for(int i=0; i< month; i++) { 601 ms+= handleGetMonthLength(year, i); 602 } 603 } 604 605 return ms; 606 } 607 608 /** 609 * Find the day number on which a particular month of the true/lunar 610 * Islamic calendar starts. 611 * 612 * @param month The month in question, origin 0 from the Hijri epoch 613 * 614 * @return The day number on which the given month starts. 615 */ trueMonthStart(long month)616 private static final long trueMonthStart(long month) 617 { 618 long start = cache.get(month); 619 620 if (start == CalendarCache.EMPTY) 621 { 622 // Make a guess at when the month started, using the average length 623 long origin = HIJRA_MILLIS 624 + (long)Math.floor(month * CalendarAstronomer.SYNODIC_MONTH) * ONE_DAY; 625 626 double age = moonAge(origin); 627 628 if (moonAge(origin) >= 0) { 629 // The month has already started 630 do { 631 origin -= ONE_DAY; 632 age = moonAge(origin); 633 } while (age >= 0); 634 } 635 else { 636 // Preceding month has not ended yet. 637 do { 638 origin += ONE_DAY; 639 age = moonAge(origin); 640 } while (age < 0); 641 } 642 643 start = (origin - HIJRA_MILLIS) / ONE_DAY + 1; 644 645 cache.put(month, start); 646 } 647 return start; 648 } 649 650 /** 651 * Return the "age" of the moon at the given time; this is the difference 652 * in ecliptic latitude between the moon and the sun. This method simply 653 * calls CalendarAstronomer.moonAge, converts to degrees, 654 * and adjusts the resultto be in the range [-180, 180]. 655 * 656 * @param time The time at which the moon's age is desired, 657 * in millis since 1/1/1970. 658 */ moonAge(long time)659 static final double moonAge(long time) 660 { 661 double age = 0; 662 663 synchronized(astro) { 664 astro.setTime(time); 665 age = astro.getMoonAge(); 666 } 667 // Convert to degrees and normalize... 668 age = age * 180 / Math.PI; 669 if (age > 180) { 670 age = age - 360; 671 } 672 673 return age; 674 } 675 676 //------------------------------------------------------------------------- 677 // Internal data.... 678 // 679 680 // And an Astronomer object for the moon age calculations 681 private static CalendarAstronomer astro = new CalendarAstronomer(); 682 683 private static CalendarCache cache = new CalendarCache(); 684 685 /** 686 * <code>true</code> if this object uses the fixed-cycle Islamic civil calendar, 687 * and <code>false</code> if it approximates the true religious calendar using 688 * astronomical calculations for the time of the new moon. 689 * 690 * @serial 691 */ 692 private boolean civil = true; 693 694 /** 695 * determines the type of calculation to use for this instance 696 * 697 * @serial 698 */ 699 private CalculationType cType = CalculationType.ISLAMIC_CIVIL; 700 701 //---------------------------------------------------------------------- 702 // Calendar framework 703 //---------------------------------------------------------------------- 704 705 /** 706 * Return the length (in days) of the given month. 707 * 708 * @param extendedYear The hijri year 709 * @param month The hijri month, 0-based 710 */ 711 @Override handleGetMonthLength(int extendedYear, int month)712 protected int handleGetMonthLength(int extendedYear, int month) { 713 714 int length; 715 716 if (cType == CalculationType.ISLAMIC_CIVIL 717 || cType == CalculationType.ISLAMIC_TBLA 718 || (cType == CalculationType.ISLAMIC_UMALQURA && (extendedYear < UMALQURA_YEAR_START || extendedYear > UMALQURA_YEAR_END) )) { 719 length = 29 + (month+1) % 2; 720 if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) { 721 length++; 722 } 723 } 724 else if (cType == CalculationType.ISLAMIC) { 725 month = 12*(extendedYear-1) + month; 726 length = (int)( trueMonthStart(month+1) - trueMonthStart(month) ); 727 } 728 else { // cType == CalculationType.ISLAMIC_UMALQURA should be true at this point and not null. 729 int idx = (extendedYear - UMALQURA_YEAR_START); // calculate year offset into bit map array 730 int mask = (0x01 << (11 - month)); // set mask for bit corresponding to month 731 if((UMALQURA_MONTHLENGTH[idx] & mask) == 0 ) { 732 length = 29; 733 } 734 else { 735 length = 30; 736 } 737 } 738 return length; 739 } 740 741 /** 742 * Return the number of days in the given Islamic year 743 */ 744 @Override handleGetYearLength(int extendedYear)745 protected int handleGetYearLength(int extendedYear) { 746 int length =0; 747 if (cType == CalculationType.ISLAMIC_CIVIL 748 || cType == CalculationType.ISLAMIC_TBLA 749 || (cType == CalculationType.ISLAMIC_UMALQURA && (extendedYear < UMALQURA_YEAR_START || extendedYear > UMALQURA_YEAR_END) )) { 750 length = 354 + (civilLeapYear(extendedYear) ? 1 : 0); 751 } else if (cType == CalculationType.ISLAMIC) { 752 int month = 12*(extendedYear-1); 753 length = (int)(trueMonthStart(month + 12) - trueMonthStart(month)); 754 } else if (cType == CalculationType.ISLAMIC_UMALQURA) { 755 for(int i=0; i<12; i++) 756 length += handleGetMonthLength(extendedYear, i); 757 } 758 759 return length; 760 } 761 762 //------------------------------------------------------------------------- 763 // Functions for converting from field values to milliseconds.... 764 //------------------------------------------------------------------------- 765 766 // Return JD of start of given month/year 767 // Calendar says: 768 // Get the Julian day of the day BEFORE the start of this year. 769 // If useMonth is true, get the day before the start of the month. 770 // Hence the -1 771 /** 772 */ 773 @Override handleComputeMonthStart(int eyear, int month, boolean useMonth)774 protected int handleComputeMonthStart(int eyear, int month, boolean useMonth) { 775 return (int)(monthStart(eyear, month) + ((cType == CalculationType.ISLAMIC_TBLA)? ASTRONOMICAL_EPOC: CIVIL_EPOC) - 1); 776 } 777 778 //------------------------------------------------------------------------- 779 // Functions for converting from milliseconds to field values 780 //------------------------------------------------------------------------- 781 782 /** 783 */ 784 @Override handleGetExtendedYear()785 protected int handleGetExtendedYear() { 786 int year; 787 if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR) { 788 year = internalGet(EXTENDED_YEAR, 1); // Default to year 1 789 } else { 790 year = internalGet(YEAR, 1); // Default to year 1 791 } 792 return year; 793 } 794 795 /** 796 * Override Calendar to compute several fields specific to the Islamic 797 * calendar system. These are: 798 * 799 * <ul><li>ERA 800 * <li>YEAR 801 * <li>MONTH 802 * <li>DAY_OF_MONTH 803 * <li>DAY_OF_YEAR 804 * <li>EXTENDED_YEAR</ul> 805 * 806 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this 807 * method is called. The getGregorianXxx() methods return Gregorian 808 * calendar equivalents for the given Julian day. 809 */ 810 @Override handleComputeFields(int julianDay)811 protected void handleComputeFields(int julianDay) { 812 int year =0, month=0, dayOfMonth=0, dayOfYear=0; 813 long monthStart; 814 long days = julianDay - CIVIL_EPOC; 815 816 if (cType == CalculationType.ISLAMIC_CIVIL || cType == CalculationType.ISLAMIC_TBLA) { 817 if (cType == CalculationType.ISLAMIC_TBLA) { 818 days = julianDay - ASTRONOMICAL_EPOC; 819 } 820 // Use the civil calendar approximation, which is just arithmetic 821 year = (int)Math.floor( (30 * days + 10646) / 10631.0 ); 822 month = (int)Math.ceil((days - 29 - yearStart(year)) / 29.5 ); 823 month = Math.min(month, 11); 824 } else if (cType == CalculationType.ISLAMIC){ 825 // Guess at the number of elapsed full months since the epoch 826 int months = (int)Math.floor(days / CalendarAstronomer.SYNODIC_MONTH); 827 828 monthStart = (long)Math.floor(months * CalendarAstronomer.SYNODIC_MONTH - 1); 829 830 if ( days - monthStart >= 25 && moonAge(internalGetTimeInMillis()) > 0) { 831 // If we're near the end of the month, assume next month and search backwards 832 months++; 833 } 834 835 // Find out the last time that the new moon was actually visible at this longitude 836 // This returns midnight the night that the moon was visible at sunset. 837 while ((monthStart = trueMonthStart(months)) > days) { 838 // If it was after the date in question, back up a month and try again 839 months--; 840 } 841 842 year = months >= 0 ? ((months / 12) + 1) : ((months + 1 ) / 12); 843 month = ((months % 12) + 12 ) % 12; 844 } else if (cType == CalculationType.ISLAMIC_UMALQURA) { 845 long umalquraStartdays = yearStart(UMALQURA_YEAR_START); 846 if( days < umalquraStartdays) { 847 // Use Civil calculation 848 year = (int)Math.floor( (30 * days + 10646) / 10631.0 ); 849 month = (int)Math.ceil((days - 29 - yearStart(year)) / 29.5 ); 850 month = Math.min(month, 11); 851 } else { 852 int y =UMALQURA_YEAR_START-1, m =0; 853 long d = 1; 854 while(d > 0) { 855 y++; 856 d = days - yearStart(y) +1; 857 if(d == handleGetYearLength(y)) { 858 m=11; 859 break; 860 } else if(d < handleGetYearLength(y) ) { 861 int monthLen = handleGetMonthLength(y, m); 862 m=0; 863 while(d > monthLen) { 864 d -= monthLen; 865 m++; 866 monthLen = handleGetMonthLength(y, m); 867 } 868 break; 869 } 870 } 871 year = y; 872 month = m; 873 } 874 } 875 876 877 dayOfMonth = (int)(days - monthStart(year, month)) + 1; 878 879 // Now figure out the day of the year. 880 dayOfYear = (int)(days - monthStart(year, 0) + 1); 881 882 883 internalSet(ERA, 0); 884 internalSet(YEAR, year); 885 internalSet(EXTENDED_YEAR, year); 886 internalSet(MONTH, month); 887 internalSet(DAY_OF_MONTH, dayOfMonth); 888 internalSet(DAY_OF_YEAR, dayOfYear); 889 } 890 891 /** 892 * enumeration of available calendar calculation types 893 */ 894 public enum CalculationType { 895 /** 896 * Religious calendar (atronomical simulation) 897 */ 898 ISLAMIC ("islamic"), 899 /** 900 * Tabular (intercalary years [2,5,7,10,13,16,18,21,24,26,29]) algorithm 901 * with civil (Friday) epoch. 902 */ 903 ISLAMIC_CIVIL ("islamic-civil"), 904 /** 905 * Umm al-Qura calendar 906 */ 907 ISLAMIC_UMALQURA ("islamic-umalqura"), 908 /** 909 * Tabular (intercalary years [2,5,7,10,13,16,18,21,24,26,29]) algorithm 910 * with astronomical (Thursday) epoch. 911 */ 912 ISLAMIC_TBLA ("islamic-tbla"); 913 914 private String bcpType; 915 CalculationType(String bcpType)916 CalculationType(String bcpType) { 917 this.bcpType = bcpType; 918 } 919 bcpType()920 String bcpType() { 921 return bcpType; 922 } 923 }; 924 925 /** 926 * sets the calculation type for this calendar. 927 */ setCalculationType(CalculationType type)928 public void setCalculationType(CalculationType type) { 929 cType = type; 930 931 // ensure civil property is up-to-date 932 if(cType == CalculationType.ISLAMIC_CIVIL) 933 civil = true; 934 else 935 civil = false; 936 } 937 938 /** 939 * gets the calculation type for this calendar. 940 */ getCalculationType()941 public CalculationType getCalculationType() { 942 return cType; 943 } 944 945 /** 946 * set type based on locale 947 */ setCalcTypeForLocale(ULocale locale)948 private void setCalcTypeForLocale(ULocale locale) { 949 String localeCalType = CalendarUtil.getCalendarType(locale); 950 if("islamic-civil".equals(localeCalType)) 951 setCalculationType(CalculationType.ISLAMIC_CIVIL); 952 else if("islamic-umalqura".equals(localeCalType)) 953 setCalculationType(CalculationType.ISLAMIC_UMALQURA); 954 else if("islamic-tbla".equals(localeCalType)) 955 setCalculationType(CalculationType.ISLAMIC_TBLA); 956 else if(localeCalType.startsWith("islamic")) 957 setCalculationType(CalculationType.ISLAMIC); // needs to be last so it's always the default if it's islamic-something-unhandled 958 else 959 setCalculationType(CalculationType.ISLAMIC_CIVIL); // default for any non-islamic calendar locale 960 } 961 962 963 /** 964 * {@inheritDoc} 965 */ 966 @Override getType()967 public String getType() { 968 if (cType == null) { 969 // TODO: getType() is called during Islamic calendar 970 // construction and might be null at that point. We should 971 // check the initialization sequence. See ticket#10425. 972 return "islamic"; 973 } 974 return cType.bcpType(); 975 } 976 readObject(ObjectInputStream in)977 private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException { 978 in.defaultReadObject(); 979 980 if (cType == null) { 981 // The serialized data was created by an ICU version before CalculationType 982 // was introduced. 983 cType = civil ? CalculationType.ISLAMIC_CIVIL : CalculationType.ISLAMIC; 984 } else { 985 // Make sure 'civil' is consistent with CalculationType 986 civil = (cType == CalculationType.ISLAMIC_CIVIL); 987 } 988 } 989 990 /* 991 private static CalendarFactory factory; 992 public static CalendarFactory factory() { 993 if (factory == null) { 994 factory = new CalendarFactory() { 995 public Calendar create(TimeZone tz, ULocale loc) { 996 return new IslamicCalendar(tz, loc); 997 } 998 999 public String factoryName() { 1000 return "Islamic"; 1001 } 1002 }; 1003 } 1004 return factory; 1005 } 1006 */ 1007 } 1008