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