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