Home | History | Annotate | Download | only in util
      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 android.icu.util;
     12 
     13 import java.util.Date;
     14 import java.util.Locale;
     15 
     16 import android.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 android.icu.util.Calendar#getInstance(ULocale)} passing in a <code>ULocale</code>
     63  * with the tag <code>"@calendar=Indian"</code>.</p>
     64  *
     65  * @see android.icu.util.Calendar
     66  * @see android.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 android.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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    304     protected int handleGetYearLength(int extendedYear) {
    305        return super.handleGetYearLength(extendedYear);
    306     }
    307 
    308     /**
    309      * {@inheritDoc}
    310      */
    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      */
    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      */
    406     protected int handleGetLimit(int field, int limitType) {
    407        return LIMITS[field][limitType];
    408     }
    409 
    410     /**
    411      * {@inheritDoc}
    412      */
    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      */
    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      */
    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      */
    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      */
    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      */
    549     public String getType() {
    550         return "indian";
    551     }
    552 }
    553