src/share/classes/java/time/chrono/HijrahChronology.java

Print this page




  38  *    this list of conditions and the following disclaimer in the documentation
  39  *    and/or other materials provided with the distribution.
  40  *
  41  *  * Neither the name of JSR-310 nor the names of its contributors
  42  *    may be used to endorse or promote products derived from this software
  43  *    without specific prior written permission.
  44  *
  45  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  46  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  47  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  48  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  49  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  50  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  51  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  52  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  53  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  54  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  55  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  56  */
  57 
  58 package java.time.calendar;
  59 
  60 import static java.time.temporal.ChronoField.EPOCH_DAY;
  61 
  62 import java.io.IOException;
  63 import java.io.Serializable;
  64 import java.text.ParseException;

  65 import java.time.DateTimeException;
  66 import java.time.temporal.Chrono;


  67 import java.time.temporal.ChronoField;
  68 import java.time.temporal.ChronoLocalDate;
  69 import java.time.temporal.Era;
  70 import java.time.temporal.TemporalAccessor;
  71 import java.time.temporal.ValueRange;
  72 import java.util.Arrays;
  73 import java.util.HashMap;
  74 import java.util.List;
  75 import java.util.Locale;
  76 
  77 /**
  78  * The Hijrah calendar system.
  79  * <p>
  80  * This chronology defines the rules of the Hijrah calendar system.
  81  * <p>
  82  * The implementation follows the Freeman-Grenville algorithm (*1) and has following features.
  83  * <p><ul>
  84  * <li>A year has 12 months.</li>
  85  * <li>Over a cycle of 30 years there are 11 leap years.</li>
  86  * <li>There are 30 days in month number 1, 3, 5, 7, 9, and 11,
  87  * and 29 days in month number 2, 4, 6, 8, 10, and 12.</li>
  88  * <li>In a leap year month 12 has 30 days.</li>
  89  * <li>In a 30 year cycle, year 2, 5, 7, 10, 13, 16, 18, 21, 24,


 158  *     </tr>
 159  *     <tr>
 160  *       <td>12</td>
 161  *       <td>Dhu 'l-Hijja</td>
 162  *       <td>29, but 30 days in years 2, 5, 7, 10,<br>
 163  * 13, 16, 18, 21, 24, 26, and 29</td>
 164  *     </tr>
 165  *   </tbody>
 166  * </table>
 167  * </blockquote>
 168  * <p>
 169  * (*1) The algorithm is taken from the book,
 170  * The Muslim and Christian Calendars by G.S.P. Freeman-Grenville.
 171  * <p>
 172  *
 173  * <h3>Specification for implementors</h3>
 174  * This class is immutable and thread-safe.
 175  *
 176  * @since 1.8
 177  */
 178 public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializable {
 179 
 180     /**
 181      * The Hijrah Calendar id.
 182      */
 183     private final String typeId;
 184 
 185     /**
 186      * The Hijrah calendarType.
 187      */
 188     private final String calendarType;
 189 
 190     /**
 191      * The singleton instance for the era before the current one - Before Hijrah -
 192      * which has the value 0.
 193      */
 194     public static final Era<HijrahChrono> ERA_BEFORE_AH = HijrahEra.BEFORE_AH;
 195     /**
 196      * The singleton instance for the current era - Hijrah - which has the value 1.
 197      */
 198     public static final Era<HijrahChrono> ERA_AH = HijrahEra.AH;
 199     /**
 200      * Serialization version.
 201      */
 202     private static final long serialVersionUID = 3127340209035924785L;
 203     /**
 204      * The minimum valid year-of-era.
 205      */
 206     public static final int MIN_YEAR_OF_ERA = 1;
 207     /**
 208      * The maximum valid year-of-era.
 209      * This is currently set to 9999 but may be changed to increase the valid range
 210      * in a future version of the specification.
 211      */
 212     public static final int MAX_YEAR_OF_ERA = 9999;
 213 
 214     /**
 215      * Number of Gregorian day of July 19, year 622 (Gregorian), which is epoch day
 216      * of Hijrah calendar.
 217      */
 218     private static final int HIJRAH_JAN_1_1_GREGORIAN_DAY = -492148;


 402      * Narrow names for eras.
 403      */
 404     private static final HashMap<String, String[]> ERA_NARROW_NAMES = new HashMap<>();
 405     /**
 406      * Short names for eras.
 407      */
 408     private static final HashMap<String, String[]> ERA_SHORT_NAMES = new HashMap<>();
 409     /**
 410      * Full names for eras.
 411      */
 412     private static final HashMap<String, String[]> ERA_FULL_NAMES = new HashMap<>();
 413     /**
 414      * Fallback language for the era names.
 415      */
 416     private static final String FALLBACK_LANGUAGE = "en";
 417 
 418     /**
 419      * Singleton instance of the Hijrah chronology.
 420      * Must be initialized after the rest of the static initialization.
 421      */
 422     public static final HijrahChrono INSTANCE;
 423 
 424     /**
 425      * Name data.
 426      */
 427     static {
 428         ERA_NARROW_NAMES.put(FALLBACK_LANGUAGE, new String[]{"BH", "HE"});
 429         ERA_SHORT_NAMES.put(FALLBACK_LANGUAGE, new String[]{"B.H.", "H.E."});
 430         ERA_FULL_NAMES.put(FALLBACK_LANGUAGE, new String[]{"Before Hijrah", "Hijrah Era"});
 431 
 432         DEFAULT_MONTH_DAYS = Arrays.copyOf(NUM_DAYS, NUM_DAYS.length);
 433 
 434         DEFAULT_LEAP_MONTH_DAYS = Arrays.copyOf(LEAP_NUM_DAYS, LEAP_NUM_DAYS.length);
 435 
 436         DEFAULT_MONTH_LENGTHS = Arrays.copyOf(MONTH_LENGTH, MONTH_LENGTH.length);
 437 
 438         DEFAULT_LEAP_MONTH_LENGTHS = Arrays.copyOf(LEAP_MONTH_LENGTH, LEAP_MONTH_LENGTH.length);
 439 
 440         DEFAULT_CYCLE_YEARS = Arrays.copyOf(CYCLEYEAR_START_DATE, CYCLEYEAR_START_DATE.length);
 441 
 442         INSTANCE = new HijrahChrono();
 443 
 444         String extraCalendars = java.security.AccessController.doPrivileged(
 445             new sun.security.action.GetPropertyAction("java.time.calendar.HijrahCalendars"));
 446         if (extraCalendars != null) {
 447             try {
 448                 // Split on whitespace
 449                 String[] splits = extraCalendars.split("\\s");
 450                 for (String cal : splits) {
 451                     if (!cal.isEmpty()) {
 452                         // Split on the delimiter between typeId "-" calendarType
 453                         String[] type = cal.split("-");
 454                         Chrono<?> cal2 = new HijrahChrono(type[0], type.length > 1 ? type[1] : type[0]);
 455                     }
 456                 }
 457             } catch (Exception ex) {
 458                 // Log the error
 459                 // ex.printStackTrace();
 460             }
 461         }
 462     }
 463 
 464     /**
 465      * Restricted constructor.
 466      */
 467     private HijrahChrono() {
 468         this("Hijrah", "islamicc");
 469     }
 470     /**
 471      * Constructor for name and type HijrahChrono.
 472      * @param id the id of the calendar
 473      * @param calendarType the calendar type
 474      */
 475     private HijrahChrono(String id, String calendarType) {
 476         this.typeId = id;
 477         this.calendarType = calendarType;
 478 
 479         ADJUSTED_CYCLES = new long[MAX_ADJUSTED_CYCLE];
 480         for (int i = 0; i < ADJUSTED_CYCLES.length; i++) {
 481             ADJUSTED_CYCLES[i] = (10631L * i);
 482         }
 483         // Initialize min values, least max values and max values.
 484         ADJUSTED_MIN_VALUES = Arrays.copyOf(MIN_VALUES, MIN_VALUES.length);
 485         ADJUSTED_LEAST_MAX_VALUES = Arrays.copyOf(LEAST_MAX_VALUES, LEAST_MAX_VALUES.length);
 486         ADJUSTED_MAX_VALUES = Arrays.copyOf(MAX_VALUES,MAX_VALUES.length);
 487 
 488         try {
 489             // Implicitly reads deviation data for this HijrahChronology.
 490             boolean any = HijrahDeviationReader.readDeviation(typeId, calendarType, this::addDeviationAsHijrah);
 491         } catch (IOException | ParseException e) {
 492             // do nothing. Log deviation config errors.
 493             //e.printStackTrace();
 494         }
 495     }
 496 
 497     /**
 498      * Resolve singleton.
 499      *
 500      * @return the singleton instance, not null
 501      */
 502     private Object readResolve() {
 503         return INSTANCE;
 504     }
 505 
 506     //-----------------------------------------------------------------------
 507     /**
 508      * Gets the ID of the chronology - 'Hijrah'.
 509      * <p>
 510      * The ID uniquely identifies the {@code Chrono}.
 511      * It can be used to lookup the {@code Chrono} using {@link #of(String)}.
 512      *
 513      * @return the chronology ID - 'Hijrah'
 514      * @see #getCalendarType()
 515      */
 516     @Override
 517     public String getId() {
 518         return typeId;
 519     }
 520 
 521     /**
 522      * Gets the calendar type of the underlying calendar system - 'islamicc'.
 523      * <p>
 524      * The calendar type is an identifier defined by the
 525      * <em>Unicode Locale Data Markup Language (LDML)</em> specification.
 526      * It can be used to lookup the {@code Chrono} using {@link #of(String)}.
 527      * It can also be used as part of a locale, accessible via
 528      * {@link Locale#getUnicodeLocaleType(String)} with the key 'ca'.
 529      *
 530      * @return the calendar system type - 'islamicc'
 531      * @see #getId()
 532      */
 533     @Override
 534     public String getCalendarType() {
 535         return calendarType;
 536     }
 537 
 538     //-----------------------------------------------------------------------
 539     @Override
 540     public ChronoLocalDate<HijrahChrono> date(int prolepticYear, int month, int dayOfMonth) {
 541         return HijrahDate.of(this, prolepticYear, month, dayOfMonth);
 542     }
 543 
 544     @Override
 545     public ChronoLocalDate<HijrahChrono> dateYearDay(int prolepticYear, int dayOfYear) {
 546         return HijrahDate.of(this, prolepticYear, 1, 1).plusDays(dayOfYear - 1);  // TODO better
 547     }
 548 
 549     @Override
 550     public ChronoLocalDate<HijrahChrono> date(TemporalAccessor temporal) {
 551         if (temporal instanceof HijrahDate) {
 552             return (HijrahDate) temporal;
 553         }
 554         return HijrahDate.ofEpochDay(this, temporal.getLong(EPOCH_DAY));
 555     }
 556 









































 557     //-----------------------------------------------------------------------
 558     @Override
 559     public boolean isLeapYear(long prolepticYear) {
 560         return isLeapYear0(prolepticYear);
 561     }
 562     /**
 563      * Returns if the year is a leap year.
 564      * @param prolepticYear he year to compute from
 565      * @return {@code true} if the year is a leap year, otherwise {@code false}
 566      */
 567     private static boolean isLeapYear0(long prolepticYear) {
 568         return (14 + 11 * (prolepticYear > 0 ? prolepticYear : -prolepticYear)) % 30 < 11;
 569     }
 570 
 571     @Override
 572     public int prolepticYear(Era<HijrahChrono> era, int yearOfEra) {
 573         if (era instanceof HijrahEra == false) {
 574             throw new DateTimeException("Era must be HijrahEra");
 575         }
 576         return (era == HijrahEra.AH ? yearOfEra : 1 - yearOfEra);
 577     }
 578 
 579     @Override
 580     public Era<HijrahChrono> eraOf(int eraValue) {
 581         switch (eraValue) {
 582             case 0:
 583                 return HijrahEra.BEFORE_AH;
 584             case 1:
 585                 return HijrahEra.AH;
 586             default:
 587                 throw new DateTimeException("invalid Hijrah era");
 588         }
 589     }
 590 
 591     @Override
 592     public List<Era<HijrahChrono>> eras() {
 593         return Arrays.<Era<HijrahChrono>>asList(HijrahEra.values());
 594     }
 595 
 596     //-----------------------------------------------------------------------
 597     @Override
 598     public ValueRange range(ChronoField field) {
 599         return field.range();
 600     }
 601 
 602     /**
 603      * Check the validity of a yearOfEra.
 604      * @param yearOfEra the year to check
 605      */
 606     void checkValidYearOfEra(int yearOfEra) {
 607          if (yearOfEra < MIN_YEAR_OF_ERA  ||
 608                  yearOfEra > MAX_YEAR_OF_ERA) {
 609              throw new DateTimeException("Invalid year of Hijrah Era");
 610          }
 611     }
 612 
 613     void checkValidDayOfYear(int dayOfYear) {




  38  *    this list of conditions and the following disclaimer in the documentation
  39  *    and/or other materials provided with the distribution.
  40  *
  41  *  * Neither the name of JSR-310 nor the names of its contributors
  42  *    may be used to endorse or promote products derived from this software
  43  *    without specific prior written permission.
  44  *
  45  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  46  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  47  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  48  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  49  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  50  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  51  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  52  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  53  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  54  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  55  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  56  */
  57 
  58 package java.time.chrono;
  59 
  60 import static java.time.temporal.ChronoField.EPOCH_DAY;
  61 
  62 import java.io.IOException;
  63 import java.io.Serializable;
  64 import java.text.ParseException;
  65 import java.time.Clock;
  66 import java.time.DateTimeException;
  67 import java.time.Instant;
  68 import java.time.LocalDate;
  69 import java.time.ZoneId;
  70 import java.time.temporal.ChronoField;


  71 import java.time.temporal.TemporalAccessor;
  72 import java.time.temporal.ValueRange;
  73 import java.util.Arrays;
  74 import java.util.HashMap;
  75 import java.util.List;
  76 import java.util.Locale;
  77 
  78 /**
  79  * The Hijrah calendar system.
  80  * <p>
  81  * This chronology defines the rules of the Hijrah calendar system.
  82  * <p>
  83  * The implementation follows the Freeman-Grenville algorithm (*1) and has following features.
  84  * <p><ul>
  85  * <li>A year has 12 months.</li>
  86  * <li>Over a cycle of 30 years there are 11 leap years.</li>
  87  * <li>There are 30 days in month number 1, 3, 5, 7, 9, and 11,
  88  * and 29 days in month number 2, 4, 6, 8, 10, and 12.</li>
  89  * <li>In a leap year month 12 has 30 days.</li>
  90  * <li>In a 30 year cycle, year 2, 5, 7, 10, 13, 16, 18, 21, 24,


 159  *     </tr>
 160  *     <tr>
 161  *       <td>12</td>
 162  *       <td>Dhu 'l-Hijja</td>
 163  *       <td>29, but 30 days in years 2, 5, 7, 10,<br>
 164  * 13, 16, 18, 21, 24, 26, and 29</td>
 165  *     </tr>
 166  *   </tbody>
 167  * </table>
 168  * </blockquote>
 169  * <p>
 170  * (*1) The algorithm is taken from the book,
 171  * The Muslim and Christian Calendars by G.S.P. Freeman-Grenville.
 172  * <p>
 173  *
 174  * <h3>Specification for implementors</h3>
 175  * This class is immutable and thread-safe.
 176  *
 177  * @since 1.8
 178  */
 179 public final class HijrahChronology extends Chronology implements Serializable {
 180 
 181     /**
 182      * The Hijrah Calendar id.
 183      */
 184     private final String typeId;
 185 
 186     /**
 187      * The Hijrah calendarType.
 188      */
 189     private final String calendarType;
 190 
 191     /**
 192      * The singleton instance for the era before the current one - Before Hijrah -
 193      * which has the value 0.
 194      */
 195     public static final Era ERA_BEFORE_AH = HijrahEra.BEFORE_AH;
 196     /**
 197      * The singleton instance for the current era - Hijrah - which has the value 1.
 198      */
 199     public static final Era ERA_AH = HijrahEra.AH;
 200     /**
 201      * Serialization version.
 202      */
 203     private static final long serialVersionUID = 3127340209035924785L;
 204     /**
 205      * The minimum valid year-of-era.
 206      */
 207     public static final int MIN_YEAR_OF_ERA = 1;
 208     /**
 209      * The maximum valid year-of-era.
 210      * This is currently set to 9999 but may be changed to increase the valid range
 211      * in a future version of the specification.
 212      */
 213     public static final int MAX_YEAR_OF_ERA = 9999;
 214 
 215     /**
 216      * Number of Gregorian day of July 19, year 622 (Gregorian), which is epoch day
 217      * of Hijrah calendar.
 218      */
 219     private static final int HIJRAH_JAN_1_1_GREGORIAN_DAY = -492148;


 403      * Narrow names for eras.
 404      */
 405     private static final HashMap<String, String[]> ERA_NARROW_NAMES = new HashMap<>();
 406     /**
 407      * Short names for eras.
 408      */
 409     private static final HashMap<String, String[]> ERA_SHORT_NAMES = new HashMap<>();
 410     /**
 411      * Full names for eras.
 412      */
 413     private static final HashMap<String, String[]> ERA_FULL_NAMES = new HashMap<>();
 414     /**
 415      * Fallback language for the era names.
 416      */
 417     private static final String FALLBACK_LANGUAGE = "en";
 418 
 419     /**
 420      * Singleton instance of the Hijrah chronology.
 421      * Must be initialized after the rest of the static initialization.
 422      */
 423     public static final HijrahChronology INSTANCE;
 424 
 425     /**
 426      * Name data.
 427      */
 428     static {
 429         ERA_NARROW_NAMES.put(FALLBACK_LANGUAGE, new String[]{"BH", "HE"});
 430         ERA_SHORT_NAMES.put(FALLBACK_LANGUAGE, new String[]{"B.H.", "H.E."});
 431         ERA_FULL_NAMES.put(FALLBACK_LANGUAGE, new String[]{"Before Hijrah", "Hijrah Era"});
 432 
 433         DEFAULT_MONTH_DAYS = Arrays.copyOf(NUM_DAYS, NUM_DAYS.length);
 434 
 435         DEFAULT_LEAP_MONTH_DAYS = Arrays.copyOf(LEAP_NUM_DAYS, LEAP_NUM_DAYS.length);
 436 
 437         DEFAULT_MONTH_LENGTHS = Arrays.copyOf(MONTH_LENGTH, MONTH_LENGTH.length);
 438 
 439         DEFAULT_LEAP_MONTH_LENGTHS = Arrays.copyOf(LEAP_MONTH_LENGTH, LEAP_MONTH_LENGTH.length);
 440 
 441         DEFAULT_CYCLE_YEARS = Arrays.copyOf(CYCLEYEAR_START_DATE, CYCLEYEAR_START_DATE.length);
 442 
 443         INSTANCE = new HijrahChronology();
 444 
 445         String extraCalendars = java.security.AccessController.doPrivileged(
 446             new sun.security.action.GetPropertyAction("java.time.chrono.HijrahCalendars"));
 447         if (extraCalendars != null) {
 448             try {
 449                 // Split on whitespace
 450                 String[] splits = extraCalendars.split("\\s");
 451                 for (String cal : splits) {
 452                     if (!cal.isEmpty()) {
 453                         // Split on the delimiter between typeId "-" calendarType
 454                         String[] type = cal.split("-");
 455                         Chronology cal2 = new HijrahChronology(type[0], type.length > 1 ? type[1] : type[0]);
 456                     }
 457                 }
 458             } catch (Exception ex) {
 459                 // Log the error
 460                 // ex.printStackTrace();
 461             }
 462         }
 463     }
 464 
 465     /**
 466      * Restricted constructor.
 467      */
 468     private HijrahChronology() {
 469         this("Hijrah", "islamicc");
 470     }
 471     /**
 472      * Constructor for name and type HijrahChronology.
 473      * @param id the id of the calendar
 474      * @param calendarType the calendar type
 475      */
 476     private HijrahChronology(String id, String calendarType) {
 477         this.typeId = id;
 478         this.calendarType = calendarType;
 479 
 480         ADJUSTED_CYCLES = new long[MAX_ADJUSTED_CYCLE];
 481         for (int i = 0; i < ADJUSTED_CYCLES.length; i++) {
 482             ADJUSTED_CYCLES[i] = (10631L * i);
 483         }
 484         // Initialize min values, least max values and max values.
 485         ADJUSTED_MIN_VALUES = Arrays.copyOf(MIN_VALUES, MIN_VALUES.length);
 486         ADJUSTED_LEAST_MAX_VALUES = Arrays.copyOf(LEAST_MAX_VALUES, LEAST_MAX_VALUES.length);
 487         ADJUSTED_MAX_VALUES = Arrays.copyOf(MAX_VALUES,MAX_VALUES.length);
 488 
 489         try {
 490             // Implicitly reads deviation data for this HijrahChronology.
 491             boolean any = HijrahDeviationReader.readDeviation(typeId, calendarType, this::addDeviationAsHijrah);
 492         } catch (IOException | ParseException e) {
 493             // do nothing. Log deviation config errors.
 494             //e.printStackTrace();
 495         }
 496     }
 497 
 498     /**
 499      * Resolve singleton.
 500      *
 501      * @return the singleton instance, not null
 502      */
 503     private Object readResolve() {
 504         return INSTANCE;
 505     }
 506 
 507     //-----------------------------------------------------------------------
 508     /**
 509      * Gets the ID of the chronology - 'Hijrah'.
 510      * <p>
 511      * The ID uniquely identifies the {@code Chronology}.
 512      * It can be used to lookup the {@code Chronology} using {@link #of(String)}.
 513      *
 514      * @return the chronology ID - 'Hijrah'
 515      * @see #getCalendarType()
 516      */
 517     @Override
 518     public String getId() {
 519         return typeId;
 520     }
 521 
 522     /**
 523      * Gets the calendar type of the underlying calendar system - 'islamicc'.
 524      * <p>
 525      * The calendar type is an identifier defined by the
 526      * <em>Unicode Locale Data Markup Language (LDML)</em> specification.
 527      * It can be used to lookup the {@code Chronology} using {@link #of(String)}.
 528      * It can also be used as part of a locale, accessible via
 529      * {@link Locale#getUnicodeLocaleType(String)} with the key 'ca'.
 530      *
 531      * @return the calendar system type - 'islamicc'
 532      * @see #getId()
 533      */
 534     @Override
 535     public String getCalendarType() {
 536         return calendarType;
 537     }
 538 
 539     //-----------------------------------------------------------------------
 540     @Override
 541     public HijrahDate date(int prolepticYear, int month, int dayOfMonth) {
 542         return HijrahDate.of(this, prolepticYear, month, dayOfMonth);
 543     }
 544 
 545     @Override
 546     public HijrahDate dateYearDay(int prolepticYear, int dayOfYear) {
 547         return HijrahDate.of(this, prolepticYear, 1, 1).plusDays(dayOfYear - 1);  // TODO better
 548     }
 549 
 550     @Override
 551     public HijrahDate date(TemporalAccessor temporal) {
 552         if (temporal instanceof HijrahDate) {
 553             return (HijrahDate) temporal;
 554         }
 555         return HijrahDate.ofEpochDay(this, temporal.getLong(EPOCH_DAY));
 556     }
 557 
 558     @Override
 559     public HijrahDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
 560         return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
 561 
 562     }
 563 
 564     @Override
 565     public HijrahDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
 566         return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
 567     }
 568 
 569     @Override
 570     public HijrahDate dateNow() {
 571         return dateNow(Clock.systemDefaultZone());
 572     }
 573 
 574     @Override
 575     public HijrahDate dateNow(ZoneId zone) {
 576         return dateNow(Clock.system(zone));
 577     }
 578 
 579     @Override
 580     public HijrahDate dateNow(Clock clock) {
 581         return date(LocalDate.now(clock));
 582     }
 583 
 584     @Override
 585     public ChronoLocalDateTime<HijrahDate> localDateTime(TemporalAccessor temporal) {
 586         return (ChronoLocalDateTime<HijrahDate>)super.localDateTime(temporal);
 587     }
 588 
 589     @Override
 590     public ChronoZonedDateTime<HijrahDate> zonedDateTime(TemporalAccessor temporal) {
 591         return (ChronoZonedDateTime<HijrahDate>)super.zonedDateTime(temporal);
 592     }
 593 
 594     @Override
 595     public ChronoZonedDateTime<HijrahDate> zonedDateTime(Instant instant, ZoneId zone) {
 596         return (ChronoZonedDateTime<HijrahDate>)super.zonedDateTime(instant, zone);
 597     }
 598 
 599     //-----------------------------------------------------------------------
 600     @Override
 601     public boolean isLeapYear(long prolepticYear) {
 602         return isLeapYear0(prolepticYear);
 603     }
 604     /**
 605      * Returns if the year is a leap year.
 606      * @param prolepticYear he year to compute from
 607      * @return {@code true} if the year is a leap year, otherwise {@code false}
 608      */
 609     private static boolean isLeapYear0(long prolepticYear) {
 610         return (14 + 11 * (prolepticYear > 0 ? prolepticYear : -prolepticYear)) % 30 < 11;
 611     }
 612 
 613     @Override
 614     public int prolepticYear(Era era, int yearOfEra) {
 615         if (era instanceof HijrahEra == false) {
 616             throw new DateTimeException("Era must be HijrahEra");
 617         }
 618         return (era == HijrahEra.AH ? yearOfEra : 1 - yearOfEra);
 619     }
 620 
 621     @Override
 622     public Era eraOf(int eraValue) {
 623         switch (eraValue) {
 624             case 0:
 625                 return HijrahEra.BEFORE_AH;
 626             case 1:
 627                 return HijrahEra.AH;
 628             default:
 629                 throw new DateTimeException("invalid Hijrah era");
 630         }
 631     }
 632 
 633     @Override
 634     public List<Era> eras() {
 635         return Arrays.<Era>asList(HijrahEra.values());
 636     }
 637 
 638     //-----------------------------------------------------------------------
 639     @Override
 640     public ValueRange range(ChronoField field) {
 641         return field.range();
 642     }
 643 
 644     /**
 645      * Check the validity of a yearOfEra.
 646      * @param yearOfEra the year to check
 647      */
 648     void checkValidYearOfEra(int yearOfEra) {
 649          if (yearOfEra < MIN_YEAR_OF_ERA  ||
 650                  yearOfEra > MAX_YEAR_OF_ERA) {
 651              throw new DateTimeException("Invalid year of Hijrah Era");
 652          }
 653     }
 654 
 655     void checkValidDayOfYear(int dayOfYear) {