]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/main/classes/core/src/com/ibm/icu/util/PersianCalendar.java
Clean up imports.
[Dictionary.git] / jars / icu4j-52_1 / main / classes / core / src / com / ibm / icu / util / PersianCalendar.java
1 /*
2  *******************************************************************************
3  * Copyright (C) 1996-2012, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7
8 package com.ibm.icu.util;
9
10 import java.util.Date;
11 import java.util.Locale;
12
13 import com.ibm.icu.util.ULocale.Category;
14
15 /**
16  * <code>PersianCalendar</code> is a subclass of <code>Calendar</code> that
17  * that implements the Persian calendar.  It is used as the main civil
18  * calendar in Iran and Afghanistan, and by Iranians and Afghans worldwide.
19  * <p>
20  * The Persian calendar is solar, and is similar to the Gregorian calendar
21  * in various ways, except its leap year rule, which is determined
22  * astronomically.  The Persian year starts around the March equinox.
23  * <p>
24  * The modern Persian calendar (used in Iran since 1925 CE and in
25  * Afghanistan since 1957 CE), has the lengths of the months fixed.  The
26  * first six months are 31 days each, the next five months are 30 days each,
27  * and the final month is 29 days in non-leap years and 30 days in leap
28  * ones.  Historically, the lengths of the month differed in different
29  * years, but they were finally fixed at the times mentioned above.  Partial
30  * information is available about the historical lengths.
31  * <p>
32  * The official rule for determination of the beginning of the Persian year
33  * is locale dependent, but at the same time, it has not specified a locale. 
34  * Iranians around the world traditionally follow the calendar authorities
35  * of Iran, which haven't officially specified the locale.  Some
36  * calendarists use some point in Tehran as the locale, while others have
37  * tried the more neutral 52.5 degrees east meridian.  It is not clear which
38  * locale should be used for the Persian calendar of Afghanistan, but it is
39  * expected that for about one year in every twenty-four years, the Afghan
40  * calendar may become different from the Iranian one.
41  * <p> 
42  * The exact locale to be used for the Iranian calendar starts to make a
43  * difference at around 2090 CE.  The specific arithmetic method implemented
44  * here, commonly known as the 33-year cycle rule, matches the astronomical
45  * calendar at least for the whole period that the calendar has been both
46  * well-defined and official, from 1925 to around 2090 CE.  The other
47  * commonly known algorithm, the 2820-year cycle, has been incorrectly
48  * designed to follow the tropical year instead of the spring equinoctial
49  * year, and fails to match the astronomical one as early as 2025 CE.
50  * <p>
51  * This class should not be subclassed.</p>
52  * <p>
53  * PersianCalendar usually should be instantiated using
54  * {@link com.ibm.icu.util.Calendar#getInstance(ULocale)} passing in a
55  * <code>ULocale</code> with the tag <code>"@calendar=persian"</code>.</p>
56  *
57  * @see com.ibm.icu.util.GregorianCalendar
58  * @see com.ibm.icu.util.Calendar
59  *
60  * @author Roozbeh Pournader
61  *
62  * @internal
63  * @deprecated This API is ICU internal only.
64  */
65 public class PersianCalendar extends Calendar {
66     private static final long serialVersionUID = -6727306982975111643L;
67
68     //-------------------------------------------------------------------------
69     // Constants...
70     //-------------------------------------------------------------------------
71     
72     private static final int[][] MONTH_COUNT = {
73         //len len2   st
74         {  31,  31,   0 }, // Farvardin
75         {  31,  31,  31 }, // Ordibehesht
76         {  31,  31,  62 }, // Khordad
77         {  31,  31,  93 }, // Tir
78         {  31,  31, 124 }, // Mordad
79         {  31,  31, 155 }, // Shahrivar
80         {  30,  30, 186 }, // Mehr
81         {  30,  30, 216 }, // Aban
82         {  30,  30, 246 }, // Azar
83         {  30,  30, 276 }, // Dey
84         {  30,  30, 306 }, // Bahman
85         {  29,  30, 336 }  // Esfand
86         // len  length of month
87         // len2 length of month in a leap year
88         // st   days in year before start of month
89     };
90     
91     private static final int PERSIAN_EPOCH = 1948320;
92
93     //-------------------------------------------------------------------------
94     // Constructors...
95     //-------------------------------------------------------------------------
96
97     /**
98      * Constructs a default <code>PersianCalendar</code> using the current time
99      * in the default time zone with the default <code>FORMAT</code> locale.
100      * @see Category#FORMAT
101      *
102      * @internal
103      * @deprecated This API is ICU internal only.
104      */
105     public PersianCalendar()
106     {
107         this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
108     }
109
110     /**
111      * Constructs a <code>PersianCalendar</code> based on the current time
112      * in the given time zone with the default <code>FORMAT</code> locale.
113      * @param zone the given time zone.
114      * @see Category#FORMAT
115      *
116      * @internal
117      * @deprecated This API is ICU internal only.
118      */
119     public PersianCalendar(TimeZone zone)
120     {
121         this(zone, ULocale.getDefault(Category.FORMAT));
122     }
123
124     /**
125      * Constructs a <code>PersianCalendar</code> based on the current time
126      * in the default time zone with the given locale.
127      *
128      * @param aLocale the given locale.
129      *
130      * @internal
131      * @deprecated This API is ICU internal only.
132      */
133     public PersianCalendar(Locale aLocale)
134     {
135         this(TimeZone.getDefault(), aLocale);
136     }
137
138     /**
139      * Constructs a <code>PersianCalendar</code> based on the current time
140      * in the default time zone with the given locale.
141      *
142      * @param locale the given ulocale.
143      *
144      * @internal
145      * @deprecated This API is ICU internal only.
146      */
147     public PersianCalendar(ULocale locale)
148     {
149         this(TimeZone.getDefault(), locale);
150     }
151
152     /**
153      * Constructs a <code>PersianCalendar</code> based on the current time
154      * in the given time zone with the given locale.
155      *
156      * @param zone the given time zone.
157      * @param aLocale the given locale.
158      *
159      * @internal
160      * @deprecated This API is ICU internal only.
161      */
162     public PersianCalendar(TimeZone zone, Locale aLocale)
163     {
164         super(zone, aLocale);
165         setTimeInMillis(System.currentTimeMillis());
166     }
167
168     /**
169      * Constructs a <code>PersianCalendar</code> based on the current time
170      * in the given time zone with the given locale.
171      *
172      * @param zone the given time zone.
173      * @param locale the given ulocale.
174      *
175      * @internal
176      * @deprecated This API is ICU internal only.
177      */
178     public PersianCalendar(TimeZone zone, ULocale locale)
179     {
180         super(zone, locale);
181         setTimeInMillis(System.currentTimeMillis());
182     }
183
184     /**
185      * Constructs a <code>PersianCalendar</code> with the given date set
186      * in the default time zone with the default <code>FORMAT</code> locale.
187      *
188      * @param date      The date to which the new calendar is set.
189      * @see Category#FORMAT
190      *
191      * @internal
192      * @deprecated This API is ICU internal only.
193      */
194     public PersianCalendar(Date date) {
195         super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
196         this.setTime(date);
197     }
198
199     /**
200      * Constructs a <code>PersianCalendar</code> with the given date set
201      * in the default time zone with the default <code>FORMAT</code> locale.
202      *
203      * @param year the value used to set the {@link #YEAR YEAR} time field in the calendar.
204      * @param month the value used to set the {@link #MONTH MONTH} time field in the calendar.
205      *              Note that the month value is 0-based. e.g., 0 for Farvardin.
206      * @param date the value used to set the {@link #DATE DATE} time field in the calendar.
207      * @see Category#FORMAT
208      *
209      * @internal
210      * @deprecated This API is ICU internal only.
211      */
212     public PersianCalendar(int year, int month, int date)
213     {
214         super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
215         this.set(Calendar.YEAR, year);
216         this.set(Calendar.MONTH, month);
217         this.set(Calendar.DATE, date);
218     }
219
220     /**
221      * Constructs a <code>PersianCalendar</code> with the given date
222      * and time set for the default time zone with the default <code>FORMAT</code> locale.
223      *
224      * @param year  the value used to set the {@link #YEAR YEAR} time field in the calendar.
225      * @param month the value used to set the {@link #MONTH MONTH} time field in the calendar.
226      *              Note that the month value is 0-based. e.g., 0 for Farvardin.
227      * @param date  the value used to set the {@link #DATE DATE} time field in the calendar.
228      * @param hour  the value used to set the {@link #HOUR_OF_DAY HOUR_OF_DAY} time field
229      *              in the calendar.
230      * @param minute the value used to set the {@link #MINUTE MINUTE} time field
231      *              in the calendar.
232      * @param second the value used to set the {@link #SECOND SECOND} time field
233      *              in the calendar.
234      * @see Category#FORMAT
235      *
236      * @internal
237      * @deprecated This API is ICU internal only.
238      */
239     public PersianCalendar(int year, int month, int date, int hour,
240                            int minute, int second)
241     {
242         super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
243         this.set(Calendar.YEAR, year);
244         this.set(Calendar.MONTH, month);
245         this.set(Calendar.DATE, date);
246         this.set(Calendar.HOUR_OF_DAY, hour);
247         this.set(Calendar.MINUTE, minute);
248         this.set(Calendar.SECOND, second);
249     }
250
251     //-------------------------------------------------------------------------
252     // Minimum / Maximum access functions
253     //-------------------------------------------------------------------------
254
255     private static final int LIMITS[][] = {
256         // Minimum  Greatest     Least   Maximum
257         //           Minimum   Maximum
258         {        0,        0,        0,        0}, // ERA
259         { -5000000, -5000000,  5000000,  5000000}, // YEAR
260         {        0,        0,       11,       11}, // MONTH
261         {        1,        1,       52,       53}, // WEEK_OF_YEAR
262         {/*                                   */}, // WEEK_OF_MONTH
263         {        1,        1,       29,       31}, // DAY_OF_MONTH
264         {        1,        1,      365,      366}, // DAY_OF_YEAR
265         {/*                                   */}, // DAY_OF_WEEK
266         {       -1,       -1,        5,        5}, // DAY_OF_WEEK_IN_MONTH
267         {/*                                   */}, // AM_PM
268         {/*                                   */}, // HOUR
269         {/*                                   */}, // HOUR_OF_DAY
270         {/*                                   */}, // MINUTE
271         {/*                                   */}, // SECOND
272         {/*                                   */}, // MILLISECOND
273         {/*                                   */}, // ZONE_OFFSET
274         {/*                                   */}, // DST_OFFSET
275         { -5000000, -5000000,  5000000,  5000000}, // YEAR_WOY
276         {/*                                   */}, // DOW_LOCAL
277         { -5000000, -5000000,  5000000,  5000000}, // EXTENDED_YEAR
278         {/*                                   */}, // JULIAN_DAY
279         {/*                                   */}, // MILLISECONDS_IN_DAY
280     };
281
282     /**
283      * @internal
284      * @deprecated This API is ICU internal only.
285      */
286     protected int handleGetLimit(int field, int limitType) {
287         return LIMITS[field][limitType];
288     }
289
290     //-------------------------------------------------------------------------
291     // Assorted calculation utilities
292     //
293
294     /**
295      * Determine whether a year is a leap year in the Persian calendar
296      */
297     private final static boolean isLeapYear(int year)
298     {
299         int[] remainder = new int[1];
300         floorDivide(25 * year + 11, 33, remainder);
301         return remainder[0] < 8;
302         
303     }
304
305     //----------------------------------------------------------------------
306     // Calendar framework
307     //----------------------------------------------------------------------
308
309     /**
310      * Return the length (in days) of the given month.
311      *
312      * @param extendedYear  The Persian year
313      * @param month The Persian month, 0-based
314      *
315      * @internal
316      * @deprecated This API is ICU internal only.
317      */
318     protected int handleGetMonthLength(int extendedYear, int month) {
319         // If the month is out of range, adjust it into range, and
320         // modify the extended year value accordingly.
321         if (month < 0 || month > 11) {
322             int[] rem = new int[1];
323             extendedYear += floorDivide(month, 12, rem);
324             month = rem[0];
325         }
326
327         return MONTH_COUNT[month][isLeapYear(extendedYear)?1:0];
328     }
329
330     /**
331      * Return the number of days in the given Persian year
332      *
333      * @internal
334      * @deprecated This API is ICU internal only.
335      */
336     protected int handleGetYearLength(int extendedYear) {
337         return isLeapYear(extendedYear) ? 366 : 365;
338     }
339     
340     //-------------------------------------------------------------------------
341     // Functions for converting from field values to milliseconds....
342     //-------------------------------------------------------------------------
343
344     /**
345      * Return JD of start of given month/year
346      *
347      * @internal
348      * @deprecated This API is ICU internal only.
349      */
350     protected int handleComputeMonthStart(int eyear, int month, boolean useMonth) {
351         // If the month is out of range, adjust it into range, and
352         // modify the extended year value accordingly.
353         if (month < 0 || month > 11) {
354             int[] rem = new int[1];
355             eyear += floorDivide(month, 12, rem);
356             month = rem[0];
357         }
358
359         int julianDay = PERSIAN_EPOCH - 1 + 365 * (eyear - 1) + floorDivide(8 * eyear + 21, 33);
360         if (month != 0) {
361             julianDay += MONTH_COUNT[month][2];
362         }
363         return julianDay;
364     }    
365
366     //-------------------------------------------------------------------------
367     // Functions for converting from milliseconds to field values
368     //-------------------------------------------------------------------------
369
370     /**
371      * @internal
372      * @deprecated This API is ICU internal only.
373      */
374     protected int handleGetExtendedYear() {
375         int year;
376         if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR) {
377             year = internalGet(EXTENDED_YEAR, 1); // Default to year 1
378         } else {
379             year = internalGet(YEAR, 1); // Default to year 1
380         }
381         return year;
382     }
383
384     /**
385      * Override Calendar to compute several fields specific to the Persian
386      * calendar system.  These are:
387      *
388      * <ul><li>ERA
389      * <li>YEAR
390      * <li>MONTH
391      * <li>DAY_OF_MONTH
392      * <li>DAY_OF_YEAR
393      * <li>EXTENDED_YEAR</ul>
394      * 
395      * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this
396      * method is called.
397      *
398      * @internal
399      * @deprecated This API is ICU internal only.
400      */
401     protected void handleComputeFields(int julianDay) {
402         int year, month, dayOfMonth, dayOfYear;
403
404         long daysSinceEpoch = julianDay - PERSIAN_EPOCH;
405         year = 1 + (int) floorDivide(33 * daysSinceEpoch + 3, 12053);
406
407         long farvardin1 = 365 * (year - 1) + floorDivide(8 * year + 21, 33);
408         dayOfYear = (int)(daysSinceEpoch - farvardin1); // 0-based
409         if (dayOfYear < 216) { // Compute 0-based month
410             month = dayOfYear / 31;
411         } else {
412             month = (dayOfYear - 6) / 30;
413         }
414         dayOfMonth = dayOfYear - MONTH_COUNT[month][2] + 1;
415         ++dayOfYear; // Make it 1-based now
416         
417         internalSet(ERA, 0);
418         internalSet(YEAR, year);
419         internalSet(EXTENDED_YEAR, year);
420         internalSet(MONTH, month);
421         internalSet(DAY_OF_MONTH, dayOfMonth);
422         internalSet(DAY_OF_YEAR, dayOfYear);       
423     }    
424
425     /**
426      * {@inheritDoc}
427      *
428      * @internal
429      * @deprecated This API is ICU internal only.
430      */
431     public String getType() {
432         return "persian";
433     }
434 }