1 7 package com.ibm.icu.util; 8 import com.ibm.icu.util.TimeZone; 9 import com.ibm.icu.impl.CalendarAstronomer; 10 import com.ibm.icu.impl.CalendarCache; 11 import java.util.Date ; 12 import java.util.Locale ; 13 14 77 public class IslamicCalendar extends Calendar { 78 private static final long serialVersionUID = -6253365474073869325L; 80 81 private static String copyright = "Copyright \u00a9 1997-1998 IBM Corp. All Rights Reserved."; 82 83 87 91 public static final int MUHARRAM = 0; 92 93 97 public static final int SAFAR = 1; 98 99 103 public static final int RABI_1 = 2; 104 105 109 public static final int RABI_2 = 3; 110 111 115 public static final int JUMADA_1 = 4; 116 117 121 public static final int JUMADA_2 = 5; 122 123 127 public static final int RAJAB = 6; 128 129 133 public static final int SHABAN = 7; 134 135 139 public static final int RAMADAN = 8; 140 141 145 public static final int SHAWWAL = 9; 146 147 151 public static final int DHU_AL_QIDAH = 10; 152 153 157 public static final int DHU_AL_HIJJAH = 11; 158 159 160 private static final long HIJRA_MILLIS = -42521587200000L; 162 166 171 public IslamicCalendar() 172 { 173 this(TimeZone.getDefault(), ULocale.getDefault()); 174 } 175 176 182 public IslamicCalendar(TimeZone zone) 183 { 184 this(zone, ULocale.getDefault()); 185 } 186 187 194 public IslamicCalendar(Locale aLocale) 195 { 196 this(TimeZone.getDefault(), aLocale); 197 } 198 199 207 public IslamicCalendar(ULocale locale) 208 { 209 this(TimeZone.getDefault(), locale); 210 } 211 212 220 public IslamicCalendar(TimeZone zone, Locale aLocale) 221 { 222 super(zone, aLocale); 223 setTimeInMillis(System.currentTimeMillis()); 224 } 225 226 235 public IslamicCalendar(TimeZone zone, ULocale locale) 236 { 237 super(zone, locale); 238 setTimeInMillis(System.currentTimeMillis()); 239 } 240 241 248 public IslamicCalendar(Date date) { 249 super(TimeZone.getDefault(), ULocale.getDefault()); 250 this.setTime(date); 251 } 252 253 263 public IslamicCalendar(int year, int month, int date) 264 { 265 super(TimeZone.getDefault(), ULocale.getDefault()); 266 this.set(Calendar.YEAR, year); 267 this.set(Calendar.MONTH, month); 268 this.set(Calendar.DATE, date); 269 } 270 271 287 public IslamicCalendar(int year, int month, int date, int hour, 288 int minute, int second) 289 { 290 super(TimeZone.getDefault(), ULocale.getDefault()); 291 this.set(Calendar.YEAR, year); 292 this.set(Calendar.MONTH, month); 293 this.set(Calendar.DATE, date); 294 this.set(Calendar.HOUR_OF_DAY, hour); 295 this.set(Calendar.MINUTE, minute); 296 this.set(Calendar.SECOND, second); 297 } 298 299 307 public void setCivil(boolean beCivil) 308 { 309 if (civil != beCivil) { 310 long m = getTimeInMillis(); 313 civil = beCivil; 314 clear(); 315 setTimeInMillis(m); 316 } 317 } 318 319 325 public boolean isCivil() { 326 return civil; 327 } 328 329 333 private static final int LIMITS[][] = { 334 { 0, 0, 0, 0 }, { 1, 1, 5000000, 5000000 }, { 0, 0, 11, 11 }, { 1, 1, 51, 52 }, { 0, 0, 5, 6 }, { 1, 1, 29, 30 }, { 1, 1, 354, 355 }, {}, { -1, -1, 4, 5 }, {}, {}, {}, {}, {}, {}, {}, {}, { -5000001, -5000001, 5000001, 5000001 }, {}, { -5000000, -5000000, 5000000, 5000000 }, {}, {}, }; 359 360 363 protected int handleGetLimit(int field, int limitType) { 364 return LIMITS[field][limitType]; 365 } 366 367 371 391 394 private final static boolean civilLeapYear(int year) 395 { 396 return (14 + 11 * year) % 30 < 11; 397 398 } 399 400 404 private long yearStart(int year) { 405 if (civil) { 406 return (year-1)*354 + (long)Math.floor((3+11*year)/30.0); 407 } else { 408 return trueMonthStart(12*(year-1)); 409 } 410 } 411 412 419 private long monthStart(int year, int month) { 420 if (civil) { 421 return (long)Math.ceil(29.5*month) 422 + (year-1)*354 + (long)Math.floor((3+11*year)/30.0); 423 } else { 424 return trueMonthStart(12*(year-1) + month); 425 } 426 } 427 428 436 private static final long trueMonthStart(long month) 437 { 438 long start = cache.get(month); 439 440 if (start == CalendarCache.EMPTY) 441 { 442 long origin = HIJRA_MILLIS 444 + (long)Math.floor(month * CalendarAstronomer.SYNODIC_MONTH - 1) * ONE_DAY; 445 446 double age = moonAge(origin); 447 448 if (moonAge(origin) >= 0) { 449 do { 451 origin -= ONE_DAY; 452 age = moonAge(origin); 453 } while (age >= 0); 454 } 455 else { 456 do { 458 origin += ONE_DAY; 459 age = moonAge(origin); 460 } while (age < 0); 461 } 462 463 start = (origin - HIJRA_MILLIS) / ONE_DAY + 1; 464 465 cache.put(month, start); 466 } 467 return start; 468 } 469 470 479 static final double moonAge(long time) 480 { 481 double age = 0; 482 483 synchronized(astro) { 484 astro.setTime(time); 485 age = astro.getMoonAge(); 486 } 487 age = age * 180 / Math.PI; 489 if (age > 180) { 490 age = age - 360; 491 } 492 493 return age; 494 } 495 496 500 private static CalendarAstronomer astro = new CalendarAstronomer(); 502 503 private static CalendarCache cache = new CalendarCache(); 504 505 512 private boolean civil = true; 513 514 518 525 protected int handleGetMonthLength(int extendedYear, int month) { 526 527 int length = 0; 528 529 if (civil) { 530 length = 29 + (month+1) % 2; 531 if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) { 532 length++; 533 } 534 } else { 535 month = 12*(extendedYear-1) + month; 536 length = (int)( trueMonthStart(month+1) - trueMonthStart(month) ); 537 } 538 return length; 539 } 540 541 545 protected int handleGetYearLength(int extendedYear) { 546 if (civil) { 547 return 354 + (civilLeapYear(extendedYear) ? 1 : 0); 548 } else { 549 int month = 12*(extendedYear-1); 550 return (int)(trueMonthStart(month + 12) - trueMonthStart(month)); 551 } 552 } 553 554 558 562 protected int handleComputeMonthStart(int eyear, int month, boolean useMonth) { 563 return (int) monthStart(eyear, month) + 1948439; 564 } 565 566 570 573 protected int handleGetExtendedYear() { 574 int year; 575 if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR) { 576 year = internalGet(EXTENDED_YEAR, 1); } else { 578 year = internalGet(YEAR, 1); } 580 return year; 581 } 582 583 599 protected void handleComputeFields(int julianDay) { 600 int year, month, dayOfMonth, dayOfYear; 601 long monthStart; 602 long days = julianDay - 1948440; 603 604 if (civil) { 605 year = (int)Math.floor( (30 * days + 10646) / 10631.0 ); 607 month = (int)Math.ceil((days - 29 - yearStart(year)) / 29.5 ); 608 month = Math.min(month, 11); 609 monthStart = monthStart(year, month); 610 } else { 611 int months = (int)Math.floor(days / CalendarAstronomer.SYNODIC_MONTH); 613 614 monthStart = (long)Math.floor(months * CalendarAstronomer.SYNODIC_MONTH - 1); 615 616 if ( days - monthStart >= 28 && moonAge(internalGetTimeInMillis()) > 0) { 617 months++; 619 } 620 621 while ((monthStart = trueMonthStart(months)) > days) { 624 months--; 626 } 627 628 year = months / 12 + 1; 629 month = months % 12; 630 } 631 632 dayOfMonth = (int)(days - monthStart(year, month)) + 1; 633 634 dayOfYear = (int)(days - monthStart(year, 0) + 1); 636 637 internalSet(ERA, 0); 638 internalSet(YEAR, year); 639 internalSet(EXTENDED_YEAR, year); 640 internalSet(MONTH, month); 641 internalSet(DAY_OF_MONTH, dayOfMonth); 642 internalSet(DAY_OF_YEAR, dayOfYear); 643 } 644 645 651 public String getType() { 652 return "islamic"; 653 } 654 655 672 } 673 | Popular Tags |