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) 1996-2010, International Business Machines Corporation and    *
6 * others. All Rights Reserved.                                                *
7 *******************************************************************************
8 */
9
10package com.ibm.icu.util;
11
12import java.util.Date;
13import java.util.Locale;
14
15/**
16 * <code>TaiwanCalendar</code> is a subclass of <code>GregorianCalendar</code>
17 * that numbers years since 1912.
18 * <p>
19 * The Taiwan calendar is identical to the Gregorian calendar in all respects
20 * except for the year and era.  Years are numbered since 1912 AD (Gregorian).
21 * <p>
22 * The Taiwan Calendar has one era: <code>MINGUO</code>.
23 * <p>
24 * This class should not be subclassed.</p>
25 * <p>
26 * TaiwanCalendar usually should be instantiated using
27 * {@link com.ibm.icu.util.Calendar#getInstance(ULocale)} passing in a <code>ULocale</code>
28 * with the tag <code>"@calendar=roc"</code>.</p>
29 *
30 * @see com.ibm.icu.util.Calendar
31 * @see com.ibm.icu.util.GregorianCalendar
32 *
33 * @author Laura Werner
34 * @author Alan Liu
35 * @author Steven R. Loomis
36 * @stable ICU 3.8
37 */
38public class TaiwanCalendar extends GregorianCalendar {
39    // jdk1.4.2 serialver
40    private static final long serialVersionUID = 2583005278132380631L;
41
42    //-------------------------------------------------------------------------
43    // Constructors...
44    //-------------------------------------------------------------------------
45
46    /**
47     * Constant for the Taiwan Era for years before Minguo 1.
48     * Brefore Minuo 1 is Gregorian 1911, Before Minguo 2 is Gregorian 1910
49     * and so on.
50     *
51     * @see com.ibm.icu.util.Calendar#ERA
52     * @stable ICU 3.8
53     */
54    public static final int BEFORE_MINGUO = 0;
55
56    /**
57     * Constant for the Taiwan Era for Minguo.  Minguo 1 is 1912 in
58     * Gregorian calendar.
59     *
60     * @see com.ibm.icu.util.Calendar#ERA
61     * @stable ICU 3.8
62     */
63    public static final int MINGUO = 1;
64
65    /**
66     * Constructs a <code>TaiwanCalendar</code> using the current time
67     * in the default time zone with the default locale.
68     * @stable ICU 3.8
69     */
70    public TaiwanCalendar() {
71        super();
72    }
73
74    /**
75     * Constructs a <code>TaiwanCalendar</code> based on the current time
76     * in the given time zone with the default locale.
77     *
78     * @param zone the given time zone.
79     * @stable ICU 3.8
80     */
81    public TaiwanCalendar(TimeZone zone) {
82        super(zone);
83    }
84
85    /**
86     * Constructs a <code>TaiwanCalendar</code> based on the current time
87     * in the default time zone with the given locale.
88     *
89     * @param aLocale the given locale.
90     * @stable ICU 3.8
91     */
92    public TaiwanCalendar(Locale aLocale) {
93        super(aLocale);
94    }
95
96    /**
97     * Constructs a <code>TaiwanCalendar</code> based on the current time
98     * in the default time zone with the given locale.
99     *
100     * @param locale the given ulocale.
101     * @stable ICU 3.8
102     */
103    public TaiwanCalendar(ULocale locale) {
104        super(locale);
105    }
106
107    /**
108     * Constructs a <code>TaiwanCalendar</code> based on the current time
109     * in the given time zone with the given locale.
110     *
111     * @param zone the given time zone.
112     *
113     * @stable ICU 3.8
114     */
115    public TaiwanCalendar(TimeZone zone, Locale aLocale) {
116        super(zone, aLocale);
117    }
118
119    /**
120     * Constructs a <code>TaiwanCalendar</code> based on the current time
121     * in the given time zone with the given locale.
122     *
123     * @param zone the given time zone.
124     * @param locale the given ulocale.
125     * @stable ICU 3.8
126     */
127    public TaiwanCalendar(TimeZone zone, ULocale locale) {
128        super(zone, locale);
129    }
130
131    /**
132     * Constructs a <code>TaiwanCalendar</code> with the given date set
133     * in the default time zone with the default locale.
134     *
135     * @param date      The date to which the new calendar is set.
136     * @stable ICU 3.8
137     */
138    public TaiwanCalendar(Date date) {
139        this();
140        setTime(date);
141    }
142
143    /**
144     * Constructs a <code>TaiwanCalendar</code> with the given date set
145     * in the default time zone with the default locale.
146     *
147     * @param year      The value used to set the calendar's {@link #YEAR YEAR} time field.
148     *
149     * @param month     The value used to set the calendar's {@link #MONTH MONTH} time field.
150     *                  The value is 0-based. e.g., 0 for January.
151     *
152     * @param date      The value used to set the calendar's {@link #DATE DATE} time field.
153     * @stable ICU 3.8
154     */
155    public TaiwanCalendar(int year, int month, int date) {
156        super(year, month, date);
157    }
158
159    /**
160     * Constructs a TaiwanCalendar with the given date
161     * and time set for the default time zone with the default locale.
162     *
163     * @param year      The value used to set the calendar's {@link #YEAR YEAR} time field.
164     *
165     * @param month     The value used to set the calendar's {@link #MONTH MONTH} time field.
166     *                  The value is 0-based. e.g., 0 for January.
167     * @param date      The value used to set the calendar's {@link #DATE DATE} time field.
168     * @param hour      The value used to set the calendar's {@link #HOUR_OF_DAY HOUR_OF_DAY} time field.
169     * @param minute    The value used to set the calendar's {@link #MINUTE MINUTE} time field.
170     * @param second    The value used to set the calendar's {@link #SECOND SECOND} time field.
171     * @stable ICU 3.8
172     */
173    public TaiwanCalendar(int year, int month, int date, int hour,
174                             int minute, int second)
175    {
176        super(year, month, date, hour, minute, second);
177    }
178
179
180    //-------------------------------------------------------------------------
181    // The only practical difference from a Gregorian calendar is that years
182    // are numbered since 1912, inclusive.  A couple of overrides will
183    // take care of that....
184    //-------------------------------------------------------------------------
185
186    private static final int Taiwan_ERA_START = 1911; // 0=1911, 1=1912
187
188    // Use 1970 as the default value of EXTENDED_YEAR
189    private static final int GREGORIAN_EPOCH = 1970;
190
191
192    /**
193     * {@inheritDoc}
194     * @stable ICU 3.8
195     */
196    protected int handleGetExtendedYear() {
197        // EXTENDED_YEAR in TaiwanCalendar is a Gregorian year
198        // The default value of EXTENDED_YEAR is 1970 (Minguo 59)
199        int year = GREGORIAN_EPOCH;
200        if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR
201                && newerField(EXTENDED_YEAR, ERA) == EXTENDED_YEAR) {
202            year = internalGet(EXTENDED_YEAR, GREGORIAN_EPOCH);
203        } else {
204            int era = internalGet(ERA, MINGUO);
205            if (era == MINGUO) {
206                year = internalGet(YEAR, 1) + Taiwan_ERA_START;
207            } else {
208                year = 1 - internalGet(YEAR, 1) + Taiwan_ERA_START;
209            }
210        }
211        return year;
212    }
213
214    /**
215     * {@inheritDoc}
216     * @stable ICU 3.8
217     */
218    protected void handleComputeFields(int julianDay) {
219        super.handleComputeFields(julianDay);
220        int y = internalGet(EXTENDED_YEAR) - Taiwan_ERA_START;
221        if (y > 0) {
222            internalSet(ERA, MINGUO);
223            internalSet(YEAR, y);
224        } else {
225            internalSet(ERA, BEFORE_MINGUO);
226            internalSet(YEAR, 1- y);
227        }
228    }
229
230    /**
231     * Override GregorianCalendar.  There is only one Taiwan ERA.  We
232     * should really handle YEAR, YEAR_WOY, and EXTENDED_YEAR here too to
233     * implement the 1..5000000 range, but it's not critical.
234     * @stable ICU 3.8
235     */
236    protected int handleGetLimit(int field, int limitType) {
237        if (field == ERA) {
238            if (limitType == MINIMUM || limitType == GREATEST_MINIMUM) {
239                return BEFORE_MINGUO;
240            } else {
241                return MINGUO;
242            }
243        }
244        return super.handleGetLimit(field, limitType);
245    }
246
247    /**
248     * {@inheritDoc}
249     * @stable ICU 3.8
250     */
251    public String getType() {
252        return "roc";
253    }
254}
255