001/* 002 * Copyright (c) 2007-2013, Stephen Colebourne & Michael Nascimento Santos 003 * 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions are met: 008 * 009 * * Redistributions of source code must retain the above copyright notice, 010 * this list of conditions and the following disclaimer. 011 * 012 * * Redistributions in binary form must reproduce the above copyright notice, 013 * this list of conditions and the following disclaimer in the documentation 014 * and/or other materials provided with the distribution. 015 * 016 * * Neither the name of JSR-310 nor the names of its contributors 017 * may be used to endorse or promote products derived from this software 018 * without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 021 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 023 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 031 */ 032package org.threeten.bp.calendar; 033 034import static org.threeten.bp.temporal.ChronoField.YEAR; 035 036import java.io.Serializable; 037import java.util.Arrays; 038import java.util.List; 039import java.util.Locale; 040 041import org.threeten.bp.DateTimeException; 042import org.threeten.bp.LocalDate; 043import org.threeten.bp.temporal.Chrono; 044import org.threeten.bp.temporal.ChronoField; 045import org.threeten.bp.temporal.ChronoLocalDate; 046import org.threeten.bp.temporal.Era; 047import org.threeten.bp.temporal.ISOChrono; 048import org.threeten.bp.temporal.TemporalAccessor; 049import org.threeten.bp.temporal.ValueRange; 050 051/** 052 * The Minguo calendar system. 053 * <p> 054 * This chronology defines the rules of the Minguo calendar system. 055 * This calendar system is primarily used in the Republic of China, often known as Taiwan. 056 * Dates are aligned such that {@code 0001-01-01 (Minguo)} is {@code 1911-01-01 (ISO)}. 057 * <p> 058 * The fields are defined as follows: 059 * <p><ul> 060 * <li>era - There are two eras, the current 'Republic' (ERA_ROC) and the previous era (ERA_BEFORE_ROC). 061 * <li>year-of-era - The year-of-era for the current era increases uniformly from the epoch at year one. 062 * For the previous era the year increases from one as time goes backwards. 063 * The value for the current era is equal to the ISO proleptic-year minus 1911. 064 * <li>proleptic-year - The proleptic year is the same as the year-of-era for the 065 * current era. For the previous era, years have zero, then negative values. 066 * The value is equal to the ISO proleptic-year minus 1911. 067 * <li>month-of-year - The Minguo month-of-year exactly matches ISO. 068 * <li>day-of-month - The Minguo day-of-month exactly matches ISO. 069 * <li>day-of-year - The Minguo day-of-year exactly matches ISO. 070 * <li>leap-year - The Minguo leap-year pattern exactly matches ISO, such that the two calendars 071 * are never out of step. 072 * </ul><p> 073 * 074 * <h3>Specification for implementors</h3> 075 * This class is immutable and thread-safe. 076 */ 077public final class MinguoChrono extends Chrono<MinguoChrono> implements Serializable { 078 079 /** 080 * Singleton instance for the Minguo chronology. 081 */ 082 public static final MinguoChrono INSTANCE = new MinguoChrono(); 083 084 /** 085 * The singleton instance for the era ROC. 086 */ 087 public static final Era<MinguoChrono> ERA_ROC = MinguoEra.ROC; 088 089 /** 090 * The singleton instance for the era BEFORE_ROC. 091 */ 092 public static final Era<MinguoChrono> ERA_BEFORE_ROC = MinguoEra.BEFORE_ROC; 093 094 /** 095 * Serialization version. 096 */ 097 private static final long serialVersionUID = 1039765215346859963L; 098 /** 099 * The difference in years between ISO and Minguo. 100 */ 101 static final int YEARS_DIFFERENCE = 1911; 102 103 /** 104 * Restricted constructor. 105 */ 106 private MinguoChrono() { 107 } 108 109 /** 110 * Resolve singleton. 111 * 112 * @return the singleton instance, not null 113 */ 114 private Object readResolve() { 115 return INSTANCE; 116 } 117 118 //----------------------------------------------------------------------- 119 /** 120 * Gets the ID of the chronology - 'Minguo'. 121 * <p> 122 * The ID uniquely identifies the {@code Chrono}. 123 * It can be used to lookup the {@code Chrono} using {@link #of(String)}. 124 * 125 * @return the chronology ID - 'Minguo' 126 * @see #getCalendarType() 127 */ 128 @Override 129 public String getId() { 130 return "Minguo"; 131 } 132 133 /** 134 * Gets the calendar type of the underlying calendar system - 'roc'. 135 * <p> 136 * The calendar type is an identifier defined by the 137 * <em>Unicode Locale Data Markup Language (LDML)</em> specification. 138 * It can be used to lookup the {@code Chrono} using {@link #of(String)}. 139 * It can also be used as part of a locale, accessible via 140 * {@link Locale#getUnicodeLocaleType(String)} with the key 'ca'. 141 * 142 * @return the calendar system type - 'roc' 143 * @see #getId() 144 */ 145 @Override 146 public String getCalendarType() { 147 return "roc"; 148 } 149 150 //----------------------------------------------------------------------- 151 @Override 152 public ChronoLocalDate<MinguoChrono> date(int prolepticYear, int month, int dayOfMonth) { 153 return new MinguoDate(LocalDate.of(prolepticYear + YEARS_DIFFERENCE, month, dayOfMonth)); 154 } 155 156 @Override 157 public ChronoLocalDate<MinguoChrono> dateYearDay(int prolepticYear, int dayOfYear) { 158 return new MinguoDate(LocalDate.ofYearDay(prolepticYear + YEARS_DIFFERENCE, dayOfYear)); 159 } 160 161 @Override 162 public ChronoLocalDate<MinguoChrono> date(TemporalAccessor temporal) { 163 if (temporal instanceof MinguoDate) { 164 return (MinguoDate) temporal; 165 } 166 return new MinguoDate(LocalDate.from(temporal)); 167 } 168 169 //----------------------------------------------------------------------- 170 /** 171 * Checks if the specified year is a leap year. 172 * <p> 173 * Minguo leap years occur exactly in line with ISO leap years. 174 * This method does not validate the year passed in, and only has a 175 * well-defined result for years in the supported range. 176 * 177 * @param prolepticYear the proleptic-year to check, not validated for range 178 * @return true if the year is a leap year 179 */ 180 @Override 181 public boolean isLeapYear(long prolepticYear) { 182 return ISOChrono.INSTANCE.isLeapYear(prolepticYear + YEARS_DIFFERENCE); 183 } 184 185 @Override 186 public int prolepticYear(Era<MinguoChrono> era, int yearOfEra) { 187 if (era instanceof MinguoEra == false) { 188 throw new DateTimeException("Era must be MinguoEra"); 189 } 190 return (era == MinguoEra.ROC ? yearOfEra : 1 - yearOfEra); 191 } 192 193 @Override 194 public Era<MinguoChrono> eraOf(int eraValue) { 195 return MinguoEra.of(eraValue); 196 } 197 198 @Override 199 public List<Era<MinguoChrono>> eras() { 200 return Arrays.<Era<MinguoChrono>>asList(MinguoEra.values()); 201 } 202 203 //----------------------------------------------------------------------- 204 @Override 205 public ValueRange range(ChronoField field) { 206 switch (field) { 207 case YEAR_OF_ERA: { 208 ValueRange range = YEAR.range(); 209 return ValueRange.of(1, range.getMaximum() - YEARS_DIFFERENCE, -range.getMinimum() + 1 + YEARS_DIFFERENCE); 210 } 211 case YEAR: { 212 ValueRange range = YEAR.range(); 213 return ValueRange.of(range.getMinimum() - YEARS_DIFFERENCE, range.getMaximum() - YEARS_DIFFERENCE); 214 } 215 } 216 return field.range(); 217 } 218 219}