• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2016 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 /*
5  *******************************************************************************
6  * Copyright (C) 1996-2011, International Business Machines Corporation and    *
7  * others. All Rights Reserved.                                                *
8  *******************************************************************************
9  */
10 
11 package ohos.global.icu.util;
12 
13 import java.util.Date;
14 import java.util.Locale;
15 
16 import ohos.global.icu.util.ULocale.Category;
17 
18 /**
19  * <code>IndianCalendar</code> is a subclass of <code>GregorianCalendar</code>
20  * that numbers years since the birth of the Buddha.  This is the civil calendar
21  * which is accepted by government of India as Indian National Calendar.
22  * The two calendars most widely used in India today are the Vikrama calendar
23  * followed in North India and the Shalivahana or Saka calendar which is followed
24  * in South India and Maharashtra.
25 
26  * A variant of the Shalivahana Calendar was reformed and standardized as the
27  * Indian National calendar in 1957.
28  * <p>
29  * Some details of Indian National Calendar (to be implemented) :
30  * The Months
31  * Month          Length      Start date (Gregorian)
32  * =================================================
33  * 1 Chaitra      30/31          March 22*
34  * 2 Vaisakha     31             April 21
35  * 3 Jyaistha     31             May 22
36  * 4 Asadha       31             June 22
37  * 5 Sravana      31             July 23
38  * 6 Bhadra       31             August 23
39  * 7 Asvina       30             September 23
40  * 8 Kartika      30             October 23
41  * 9 Agrahayana   30             November 22
42  * 10 Pausa       30             December 22
43  * 11 Magha       30             January 21
44  * 12 Phalguna    30             February 20
45 
46  * In leap years, Chaitra has 31 days and starts on March 21 instead.
47  * The leap years of Gregorian calendar and Indian National Calendar are in synchornization.
48  * So When its a leap year in Gregorian calendar then Chaitra has 31 days.
49  *
50  * The Years
51  * Years are counted in the Saka Era, which starts its year 0 in 78AD (by gregorian calendar).
52  * So for eg. 9th June 2006 by Gregorian Calendar, is same as 19th of Jyaistha in 1928 of Saka
53  * era by Indian National Calendar.
54  * <p>
55  * The Indian Calendar has only one allowable era: <code>Saka Era</code>.  If the
56  * calendar is not in lenient mode (see <code>setLenient</code>), dates before
57  * 1/1/1 Saka Era are rejected with an <code>IllegalArgumentException</code>.
58  * <p>
59  * This class should not be subclassed.</p>
60  * <p>
61  * IndianCalendar usually should be instantiated using
62  * {@link ohos.global.icu.util.Calendar#getInstance(ULocale)} passing in a <code>ULocale</code>
63  * with the tag <code>"@calendar=Indian"</code>.</p>
64  *
65  * @see ohos.global.icu.util.Calendar
66  * @see ohos.global.icu.util.GregorianCalendar
67  */
68 public class IndianCalendar extends Calendar {
69     // jdk1.4.2 serialver
70     private static final long serialVersionUID = 3617859668165014834L;
71 
72     /**
73      * Constant for Chaitra, the 1st month of the Indian year.
74      */
75     public static final int CHAITRA = 0;
76 
77     /**
78      * Constant for Vaisakha, the 2nd month of the Indian year.
79      */
80     public static final int VAISAKHA = 1;
81 
82     /**
83      * Constant for Jyaistha, the 3rd month of the Indian year.
84      */
85     public static final int JYAISTHA = 2;
86 
87     /**
88      * Constant for Asadha, the 4th month of the Indian year.
89      */
90     public static final int ASADHA = 3;
91 
92     /**
93      * Constant for Sravana, the 5th month of the Indian year.
94      */
95     public static final int SRAVANA = 4 ;
96 
97     /**
98      * Constant for Bhadra, the 6th month of the Indian year.
99      */
100     public static final int BHADRA = 5 ;
101 
102     /**
103      * Constant for Asvina, the 7th month of the Indian year.
104      */
105     public static final int ASVINA = 6 ;
106 
107     /**
108      * Constant for Kartika, the 8th month of the Indian year.
109      */
110     public static final int KARTIKA = 7 ;
111 
112     /**
113      * Constant for Agrahayana, the 9th month of the Indian year.
114      */
115     public static final int AGRAHAYANA = 8 ;
116 
117     /**
118      * Constant for Pausa, the 10th month of the Indian year.
119      */
120     public static final int PAUSA = 9 ;
121 
122     /**
123      * Constant for Magha, the 11th month of the Indian year.
124      */
125     public static final int MAGHA = 10;
126 
127     /**
128      * Constant for Phalguna, the 12th month of the Indian year.
129      */
130     public static final int PHALGUNA = 11;
131 
132     //-------------------------------------------------------------------------
133     // Constructors...
134     //-------------------------------------------------------------------------
135 
136     /**
137      * Constant for the Indian Era.  This is the only allowable <code>ERA</code>
138      * value for the Indian calendar.
139      *
140      * @see ohos.global.icu.util.Calendar#ERA
141      */
142     public static final int IE = 0;
143 
144     /**
145      * Constructs a <code>IndianCalendar</code> using the current time
146      * in the default time zone with the default <code>FORMAT</code> locale.
147      * @see Category#FORMAT
148      */
IndianCalendar()149     public IndianCalendar() {
150        this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
151     }
152 
153     /**
154      * Constructs a <code>IndianCalendar</code> based on the current time
155      * in the given time zone with the default <code>FORMAT</code> locale.
156      *
157      * @param zone the given time zone.
158      * @see Category#FORMAT
159      */
IndianCalendar(TimeZone zone)160     public IndianCalendar(TimeZone zone) {
161        this(zone, ULocale.getDefault(Category.FORMAT));
162     }
163 
164     /**
165      * Constructs a <code>IndianCalendar</code> based on the current time
166      * in the default time zone with the given locale.
167      *
168      * @param aLocale the given locale.
169      */
IndianCalendar(Locale aLocale)170     public IndianCalendar(Locale aLocale) {
171         this(TimeZone.getDefault(), aLocale);
172     }
173 
174     /**
175      * Constructs a <code>IndianCalendar</code> based on the current time
176      * in the default time zone with the given locale.
177      *
178      * @param locale the given ulocale.
179      */
IndianCalendar(ULocale locale)180     public IndianCalendar(ULocale locale) {
181        this(TimeZone.getDefault(), locale);
182     }
183 
184     /**
185      * Constructs a <code>IndianCalendar</code> based on the current time
186      * in the given time zone with the given locale.
187      *
188      * @param zone the given time zone.
189      *
190      * @param aLocale the given locale.
191      */
IndianCalendar(TimeZone zone, Locale aLocale)192     public IndianCalendar(TimeZone zone, Locale aLocale) {
193         super(zone, aLocale);
194         setTimeInMillis(System.currentTimeMillis());
195     }
196 
197     /**
198      * Constructs a <code>IndianCalendar</code> based on the current time
199      * in the given time zone with the given locale.
200      *
201      * @param zone the given time zone.
202      *
203      * @param locale the given ulocale.
204      */
IndianCalendar(TimeZone zone, ULocale locale)205     public IndianCalendar(TimeZone zone, ULocale locale) {
206         super(zone, locale);
207         setTimeInMillis(System.currentTimeMillis());
208     }
209 
210     /**
211      * Constructs a <code>IndianCalendar</code> with the given date set
212      * in the default time zone with the default <code>FORMAT</code> locale.
213      *
214      * @param date      The date to which the new calendar is set.
215      * @see Category#FORMAT
216      */
IndianCalendar(Date date)217     public IndianCalendar(Date date) {
218         super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
219         this.setTime(date);
220     }
221 
222     /**
223      * Constructs a <code>IndianCalendar</code> with the given date set
224      * in the default time zone with the default <code>FORMAT</code> locale.
225      *
226      * @param year      The value used to set the calendar's {@link #YEAR YEAR} time field.
227      *
228      * @param month     The value used to set the calendar's {@link #MONTH MONTH} time field.
229      *                  The value is 0-based. e.g., 0 for January.
230      *
231      * @param date      The value used to set the calendar's {@link #DATE DATE} time field.
232      * @see Category#FORMAT
233      */
IndianCalendar(int year, int month, int date)234     public IndianCalendar(int year, int month, int date) {
235        super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
236        this.set(Calendar.YEAR, year);
237        this.set(Calendar.MONTH, month);
238        this.set(Calendar.DATE, date);
239 
240     }
241 
242     /**
243      * Constructs a IndianCalendar with the given date
244      * and time set for the default time zone with the default <code>FORMAT</code> locale.
245      *
246      * @param year      The value used to set the calendar's {@link #YEAR YEAR} time field.
247      *
248      * @param month     The value used to set the calendar's {@link #MONTH MONTH} time field.
249      *                  The value is 0-based. e.g., 0 for January.
250      *
251      * @param date      The value used to set the calendar's {@link #DATE DATE} time field.
252      *
253      * @param hour      The value used to set the calendar's {@link #HOUR_OF_DAY HOUR_OF_DAY} time field.
254      *
255      * @param minute    The value used to set the calendar's {@link #MINUTE MINUTE} time field.
256      *
257      * @param second    The value used to set the calendar's {@link #SECOND SECOND} time field.
258      * @see Category#FORMAT
259      */
IndianCalendar(int year, int month, int date, int hour, int minute, int second)260     public IndianCalendar(int year, int month, int date, int hour,
261                              int minute, int second)
262     {
263        super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
264        this.set(Calendar.YEAR, year);
265        this.set(Calendar.MONTH, month);
266        this.set(Calendar.DATE, date);
267        this.set(Calendar.HOUR_OF_DAY, hour);
268        this.set(Calendar.MINUTE, minute);
269        this.set(Calendar.SECOND, second);
270     }
271 
272 
273     //-------------------------------------------------------------------------
274     // The only practical difference from a Gregorian calendar is that years
275     // are numbered since the Saka Era.  A couple of overrides will
276     // take care of that....
277     //-------------------------------------------------------------------------
278 
279     // Starts in 78 AD,
280     private static final int INDIAN_ERA_START = 78;
281 
282     // The Indian year starts 80 days later than the Gregorian year.
283     private static final int INDIAN_YEAR_START = 80;
284 
285     /**
286      * {@inheritDoc}
287      */
handleGetExtendedYear()288     protected int handleGetExtendedYear() {
289         int year;
290 
291         if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR) {
292             year = internalGet(EXTENDED_YEAR, 1);
293         } else {
294             // Ignore the era, as there is only one
295             year = internalGet(YEAR, 1);
296         }
297 
298         return year;
299     }
300 
301     /**
302      * {@inheritDoc}
303      */
handleGetYearLength(int extendedYear)304     protected int handleGetYearLength(int extendedYear) {
305        return super.handleGetYearLength(extendedYear);
306     }
307 
308     /**
309      * {@inheritDoc}
310      */
handleGetMonthLength(int extendedYear, int month)311     protected int handleGetMonthLength(int extendedYear, int month) {
312         if (month < 0 || month > 11) {
313             int[] remainder = new int[1];
314             extendedYear += floorDivide(month, 12, remainder);
315             month = remainder[0];
316         }
317 
318         if(isGregorianLeap(extendedYear + INDIAN_ERA_START) && month == 0) {
319             return 31;
320         }
321 
322         if(month >= 1 && month <=5) {
323             return 31;
324         }
325 
326         return 30;
327     }
328 
329     /**
330      * {@inheritDoc}
331      */
handleComputeFields(int julianDay)332     protected void handleComputeFields(int julianDay){
333         double jdAtStartOfGregYear;
334         int leapMonth, IndianYear, yday, IndianMonth, IndianDayOfMonth, mday;
335         int[] gregorianDay;          // Stores gregorian date corresponding to Julian day;
336 
337         gregorianDay = jdToGregorian(julianDay);                    // Gregorian date for Julian day
338         IndianYear = gregorianDay[0] - INDIAN_ERA_START;            // Year in Saka era
339         jdAtStartOfGregYear = gregorianToJD(gregorianDay[0], 1, 1); // JD at start of Gregorian year
340         yday = (int)(julianDay - jdAtStartOfGregYear);              // Day number in Gregorian year (starting from 0)
341 
342         if (yday < INDIAN_YEAR_START) {
343             //  Day is at the end of the preceding Saka year
344             IndianYear -= 1;
345             leapMonth = isGregorianLeap(gregorianDay[0] - 1) ? 31 : 30; // Days in leapMonth this year, previous Gregorian year
346             yday += leapMonth + (31 * 5) + (30 * 3) + 10;
347         } else {
348             leapMonth = isGregorianLeap(gregorianDay[0]) ? 31 : 30; // Days in leapMonth this year
349             yday -= INDIAN_YEAR_START;
350         }
351 
352         if (yday < leapMonth) {
353             IndianMonth = 0;
354             IndianDayOfMonth = yday + 1;
355         } else {
356               mday = yday - leapMonth;
357               if (mday < (31 * 5)) {
358                  IndianMonth = mday / 31 + 1;
359                  IndianDayOfMonth = (mday % 31) + 1;
360               } else {
361                  mday -= 31 * 5;
362                  IndianMonth = mday / 30 + 6;
363                  IndianDayOfMonth = (mday % 30) + 1;
364               }
365         }
366 
367         internalSet(ERA, 0);
368         internalSet(EXTENDED_YEAR, IndianYear);
369         internalSet(YEAR, IndianYear);
370         internalSet(MONTH, IndianMonth);
371         internalSet(DAY_OF_MONTH, IndianDayOfMonth );
372         internalSet(DAY_OF_YEAR, yday + 1); // yday is 0-based
373      }
374 
375     private static final int LIMITS[][] = {
376         // Minimum  Greatest     Least    Maximum
377         //           Minimum   Maximum
378         {        0,        0,        0,        0}, // ERA
379         { -5000000, -5000000,  5000000,  5000000}, // YEAR
380         {        0,        0,       11,       11}, // MONTH
381         {        1,        1,       52,       53}, // WEEK_OF_YEAR
382         {/*                                   */}, // WEEK_OF_MONTH
383         {        1,        1,       30,       31}, // DAY_OF_MONTH
384         {        1,        1,      365,      366}, // DAY_OF_YEAR
385         {/*                                   */}, // DAY_OF_WEEK
386         {       -1,       -1,        5,        5}, // DAY_OF_WEEK_IN_MONTH
387         {/*                                   */}, // AM_PM
388         {/*                                   */}, // HOUR
389         {/*                                   */}, // HOUR_OF_DAY
390         {/*                                   */}, // MINUTE
391         {/*                                   */}, // SECOND
392         {/*                                   */}, // MILLISECOND
393         {/*                                   */}, // ZONE_OFFSET
394         {/*                                   */}, // DST_OFFSET
395         { -5000000, -5000000,  5000000,  5000000}, // YEAR_WOY
396         {/*                                   */}, // DOW_LOCAL
397         { -5000000, -5000000,  5000000,  5000000}, // EXTENDED_YEAR
398         {/*                                   */}, // JULIAN_DAY
399         {/*                                   */}, // MILLISECONDS_IN_DAY
400     };
401 
402 
403     /**
404      * {@inheritDoc}
405      */
handleGetLimit(int field, int limitType)406     protected int handleGetLimit(int field, int limitType) {
407        return LIMITS[field][limitType];
408     }
409 
410     /**
411      * {@inheritDoc}
412      */
handleComputeMonthStart(int year, int month, boolean useMonth)413     protected int handleComputeMonthStart(int year, int month, boolean useMonth) {
414 
415        //month is 0 based; converting it to 1-based
416        int imonth;
417 
418        // If the month is out of range, adjust it into range, and adjust the extended year accordingly
419        if (month < 0 || month > 11) {
420            year += month / 12;
421            month %= 12;
422        }
423 
424        imonth = month + 1;
425 
426        double jd = IndianToJD(year ,imonth, 1);
427 
428        return (int)jd;
429     }
430 
431 
432 
433     /*
434      * This routine converts an Indian date to the corresponding Julian date"
435      * @param year   The year in Saka Era according to Indian calendar.
436      * @param month  The month according to Indian calendar (between 1 to 12)
437      * @param date   The date in month
438      */
IndianToJD(int year, int month, int date)439     private static double IndianToJD(int year, int month, int date) {
440        int leapMonth, gyear, m;
441        double start, jd;
442 
443        gyear = year + INDIAN_ERA_START;
444 
445 
446        if(isGregorianLeap(gyear)) {
447           leapMonth = 31;
448           start = gregorianToJD(gyear, 3, 21);
449        } else {
450           leapMonth = 30;
451           start = gregorianToJD(gyear, 3, 22);
452        }
453 
454        if (month == 1) {
455           jd = start + (date - 1);
456        } else {
457           jd = start + leapMonth;
458           m = month - 2;
459           m = Math.min(m, 5);
460           jd += m * 31;
461           if (month >= 8) {
462              m = month - 7;
463              jd += m * 30;
464           }
465           jd += date - 1;
466        }
467 
468        return jd;
469     }
470 
471     /*
472      * The following function is not needed for basic calendar functioning.
473      * This routine converts a gregorian date to the corresponding Julian date"
474      * @param year   The year in standard Gregorian calendar (AD/BC) .
475      * @param month  The month according to Gregorian calendar (between 0 to 11)
476      * @param date   The date in month
477      */
gregorianToJD(int year, int month, int date)478     private static double gregorianToJD(int year, int month, int date) {
479        double JULIAN_EPOCH = 1721425.5;
480        int y = year - 1;
481        int result = (365 * y)
482                   + (y / 4)
483                   - (y / 100)
484                   + (y / 400)
485                   + (((367 * month) - 362) / 12)
486                   + ((month <= 2) ? 0 : (isGregorianLeap(year) ? -1 : -2))
487                   + date;
488        return result - 1 + JULIAN_EPOCH;
489     }
490 
491     /*
492      * The following function is not needed for basic calendar functioning.
493      * This routine converts a julian day (jd) to the corresponding date in Gregorian calendar"
494      * @param jd The Julian date in Julian Calendar which is to be converted to Indian date"
495      */
jdToGregorian(double jd)496     private static int[] jdToGregorian(double jd) {
497        double JULIAN_EPOCH = 1721425.5;
498        double wjd, depoch, quadricent, dqc, cent, dcent, quad, dquad, yindex, yearday, leapadj;
499        int year, month, day;
500 
501        wjd = Math.floor(jd - 0.5) + 0.5;
502        depoch = wjd - JULIAN_EPOCH;
503        quadricent = Math.floor(depoch / 146097);
504        dqc = depoch % 146097;
505        cent = Math.floor(dqc / 36524);
506        dcent = dqc % 36524;
507        quad = Math.floor(dcent / 1461);
508        dquad = dcent % 1461;
509        yindex = Math.floor(dquad / 365);
510        year = (int)((quadricent * 400) + (cent * 100) + (quad * 4) + yindex);
511 
512        if (!((cent == 4) || (yindex == 4))) {
513           year++;
514        }
515 
516        yearday = wjd - gregorianToJD(year, 1, 1);
517        leapadj = ((wjd < gregorianToJD(year, 3, 1)) ? 0
518              :
519              (isGregorianLeap(year) ? 1 : 2)
520              );
521 
522        month = (int)Math.floor((((yearday + leapadj) * 12) + 373) / 367);
523        day = (int)(wjd - gregorianToJD(year, month, 1)) + 1;
524 
525        int[] julianDate = new int[3];
526 
527        julianDate[0] = year;
528        julianDate[1] = month;
529        julianDate[2] = day;
530 
531        return julianDate;
532     }
533 
534     /*
535      * The following function is not needed for basic calendar functioning.
536      * This routine checks if the Gregorian year is a leap year"
537      * @param year      The year in Gregorian Calendar
538      */
isGregorianLeap(int year)539     private static boolean isGregorianLeap(int year)
540     {
541        return ((year % 4) == 0) &&
542           (!(((year % 100) == 0) && ((year % 400) != 0)));
543     }
544 
545 
546     /**
547      * {@inheritDoc}
548      */
getType()549     public String getType() {
550         return "indian";
551     }
552 }
553