| GNU Classpath (0.95) | |
| Frames | No Frames |
1: /* java.util.GregorianCalendar 2: Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2007 3: Free Software Foundation, Inc. 4: 5: This file is part of GNU Classpath. 6: 7: GNU Classpath is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU Classpath is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU Classpath; see the file COPYING. If not, write to the 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20: 02110-1301 USA. 21: 22: Linking this library statically or dynamically with other modules is 23: making a combined work based on this library. Thus, the terms and 24: conditions of the GNU General Public License cover the whole 25: combination. 26: 27: As a special exception, the copyright holders of this library give you 28: permission to link this library with independent modules to produce an 29: executable, regardless of the license terms of these independent 30: modules, and to copy and distribute the resulting executable under 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: 40: package java.util; 41: 42: 43: /** 44: * <p> 45: * This class represents the Gregorian calendar, that is used in most 46: * countries all over the world. It does also handle the Julian calendar 47: * for dates smaller than the date of the change to the Gregorian calendar. 48: * The Gregorian calendar differs from the Julian calendar by a different 49: * leap year rule (no leap year every 100 years, except if year is divisible 50: * by 400). 51: * </p> 52: * <p> 53: * This change date is different from country to country, and can be changed with 54: * <code>setGregorianChange</code>. The first countries to adopt the Gregorian 55: * calendar did so on the 15th of October, 1582. This date followed October 56: * the 4th, 1582 in the Julian calendar system. The non-existant days that were 57: * omitted when the change took place are interpreted as Gregorian dates. 58: * </p> 59: * <p> 60: * Prior to the changeover date, New Year's Day occurred on the 25th of March. 61: * However, this class always takes New Year's Day as being the 1st of January. 62: * Client code should manually adapt the year value, if required, for dates 63: * between January the 1st and March the 24th in years prior to the changeover. 64: * </p> 65: * <p> 66: * Any date infinitely forwards or backwards in time can be represented by 67: * this class. A <em>proleptic</em> calendar system is used, which allows 68: * future dates to be created via the existing rules. This allows meaningful 69: * and consistent dates to be produced for all years. However, dates are only 70: * historically accurate following March the 1st, 4AD when the Julian calendar 71: * system was adopted. Prior to this, leap year rules were applied erraticly. 72: * </p> 73: * <p> 74: * There are two eras available for the Gregorian calendar, namely BC and AD. 75: * </p> 76: * <p> 77: * Weeks are defined as a period of seven days, beginning on the first day 78: * of the week, as returned by <code>getFirstDayOfWeek()</code>, and ending 79: * on the day prior to this. 80: * </p> 81: * <p> 82: * The weeks of the year are numbered from 1 to a possible 53. The first week 83: * of the year is defined as the first week that contains at least the minimum 84: * number of days of the first week in the new year (retrieved via 85: * <code>getMinimalDaysInFirstWeek()</code>). All weeks after this are numbered 86: * from 2 onwards. 87: * </p> 88: * <p> 89: * For example, take the year 2004. It began on a Thursday. The first week 90: * of 2004 depends both on where a week begins and how long it must minimally 91: * last. Let's say that the week begins on a Monday and must have a minimum 92: * of 5 days. In this case, the first week begins on Monday, the 5th of January. 93: * The first 4 days (Thursday to Sunday) are not eligible, as they are too few 94: * to make up the minimum number of days of the first week which must be in 95: * the new year. If the minimum was lowered to 4 days, then the first week 96: * would instead begin on Monday, the 29th of December, 2003. This first week 97: * has 4 of its days in the new year, and is now eligible. 98: * </p> 99: * <p> 100: * The weeks of the month are numbered from 0 to a possible 6. The first week 101: * of the month (numbered 1) is a set of days, prior to the first day of the week, 102: * which number at least the minimum number of days in a week. Unlike the first 103: * week of the year, the first week of the month only uses days from that particular 104: * month. As a consequence, it may have a variable number of days (from the minimum 105: * number required up to a full week of 7) and it need not start on the first day of 106: * the week. It must, however, be following by the first day of the week, as this 107: * marks the beginning of week 2. Any days of the month which occur prior to the 108: * first week (because the first day of the week occurs before the minimum number 109: * of days is met) are seen as week 0. 110: * </p> 111: * <p> 112: * Again, we will take the example of the year 2004 to demonstrate this. September 113: * 2004 begins on a Wednesday. Taking our first day of the week as Monday, and the 114: * minimum length of the first week as 6, we find that week 1 runs from Monday, 115: * the 6th of September to Sunday the 12th. Prior to the 6th, there are only 116: * 5 days (Wednesday through to Sunday). This is too small a number to meet the 117: * minimum, so these are classed as being days in week 0. Week 2 begins on the 118: * 13th, and so on. This changes if we reduce the minimum to 5. In this case, 119: * week 1 is a truncated week from Wednesday the 1st to Sunday the 5th, and week 120: * 0 doesn't exist. The first seven day week is week 2, starting on the 6th. 121: * </p> 122: * <p> 123: * On using the <code>clear()</code> method, the Gregorian calendar returns 124: * to its default value of the 1st of January, 1970 AD 00:00:00 (the epoch). 125: * The day of the week is set to the correct day for that particular time. 126: * The day is also the first of the month, and the date is in week 0. 127: * </p> 128: * 129: * @see Calendar 130: * @see TimeZone 131: * @see Calendar#getFirstDayOfWeek() 132: * @see Calendar#getMinimalDaysInFirstWeek() 133: */ 134: public class GregorianCalendar extends Calendar 135: { 136: /** 137: * Constant representing the era BC (Before Christ). 138: */ 139: public static final int BC = 0; 140: 141: /** 142: * Constant representing the era AD (Anno Domini). 143: */ 144: public static final int AD = 1; 145: 146: /** 147: * The point at which the Gregorian calendar rules were used. 148: * This may be changed by using setGregorianChange; 149: * The default is midnight (UTC) on October 5, 1582 (Julian), 150: * or October 15, 1582 (Gregorian). 151: * 152: * @serial the changeover point from the Julian calendar 153: * system to the Gregorian. 154: */ 155: private long gregorianCutover = (new Date((24 * 60 * 60 * 1000L) * (((1582 * (365 * 4 156: + 1)) / 4 157: + (java.util.Calendar.OCTOBER * (31 158: + 30 + 31 + 30 + 31) - 9) / 5 + 5) 159: - ((1970 * (365 * 4 + 1)) / 4 + 1 160: - 13)))).getTime(); 161: 162: /** 163: * For compatability with Sun's JDK. 164: */ 165: static final long serialVersionUID = -8125100834729963327L; 166: 167: /** 168: * Days in the epoch. Relative Jan 1, year '0' which is not a leap year. 169: * (although there is no year zero, this does not matter.) 170: * This is consistent with the formula: 171: * = (year-1)*365L + ((year-1) >> 2) 172: * 173: * Plus the gregorian correction: 174: * Math.floor((year-1) / 400.) - Math.floor((year-1) / 100.); 175: * For a correct julian date, the correction is -2 instead. 176: * 177: * The gregorian cutover in 1582 was 10 days, so by calculating the 178: * correction from year zero, we have 15 non-leap days (even centuries) 179: * minus 3 leap days (year 400,800,1200) = 12. Subtracting two corrects 180: * this to the correct number 10. 181: */ 182: private static final int EPOCH_DAYS = 719162; 183: 184: /** 185: * Constructs a new GregorianCalender representing the current 186: * time, using the default time zone and the default locale. 187: */ 188: public GregorianCalendar() 189: { 190: this(TimeZone.getDefault(), Locale.getDefault()); 191: } 192: 193: /** 194: * Constructs a new GregorianCalender representing the current 195: * time, using the specified time zone and the default locale. 196: * 197: * @param zone a time zone. 198: */ 199: public GregorianCalendar(TimeZone zone) 200: { 201: this(zone, Locale.getDefault()); 202: } 203: 204: /** 205: * Constructs a new GregorianCalender representing the current 206: * time, using the default time zone and the specified locale. 207: * 208: * @param locale a locale. 209: */ 210: public GregorianCalendar(Locale locale) 211: { 212: this(TimeZone.getDefault(), locale); 213: } 214: 215: /** 216: * Constructs a new GregorianCalender representing the current 217: * time with the given time zone and the given locale. 218: * 219: * @param zone a time zone. 220: * @param locale a locale. 221: */ 222: public GregorianCalendar(TimeZone zone, Locale locale) 223: { 224: this(zone, locale, false); 225: setTimeInMillis(System.currentTimeMillis()); 226: } 227: 228: /** 229: * Common constructor that all constructors should call. 230: * @param zone a time zone. 231: * @param locale a locale. 232: * @param unused unused parameter to make the signature differ from 233: * the public constructor (TimeZone, Locale). 234: */ 235: private GregorianCalendar(TimeZone zone, Locale locale, boolean unused) 236: { 237: super(zone, locale); 238: } 239: 240: /** 241: * Constructs a new GregorianCalendar representing midnight on the 242: * given date with the default time zone and locale. 243: * 244: * @param year corresponds to the YEAR time field. 245: * @param month corresponds to the MONTH time field. 246: * @param day corresponds to the DAY time field. 247: */ 248: public GregorianCalendar(int year, int month, int day) 249: { 250: this(TimeZone.getDefault(), Locale.getDefault(), false); 251: set(year, month, day); 252: } 253: 254: /** 255: * Constructs a new GregorianCalendar representing midnight on the 256: * given date with the default time zone and locale. 257: * 258: * @param year corresponds to the YEAR time field. 259: * @param month corresponds to the MONTH time field. 260: * @param day corresponds to the DAY time field. 261: * @param hour corresponds to the HOUR_OF_DAY time field. 262: * @param minute corresponds to the MINUTE time field. 263: */ 264: public GregorianCalendar(int year, int month, int day, int hour, int minute) 265: { 266: this(TimeZone.getDefault(), Locale.getDefault(), false); 267: set(year, month, day, hour, minute); 268: } 269: 270: /** 271: * Constructs a new GregorianCalendar representing midnight on the 272: * given date with the default time zone and locale. 273: * 274: * @param year corresponds to the YEAR time field. 275: * @param month corresponds to the MONTH time field. 276: * @param day corresponds to the DAY time field. 277: * @param hour corresponds to the HOUR_OF_DAY time field. 278: * @param minute corresponds to the MINUTE time field. 279: * @param second corresponds to the SECOND time field. 280: */ 281: public GregorianCalendar(int year, int month, int day, int hour, int minute, 282: int second) 283: { 284: this(TimeZone.getDefault(), Locale.getDefault(), false); 285: set(year, month, day, hour, minute, second); 286: } 287: 288: /** 289: * Sets the date of the switch from Julian dates to Gregorian dates. 290: * You can use <code>new Date(Long.MAX_VALUE)</code> to use a pure 291: * Julian calendar, or <code>Long.MIN_VALUE</code> for a pure Gregorian 292: * calendar. 293: * 294: * @param date the date of the change. 295: */ 296: public void setGregorianChange(Date date) 297: { 298: gregorianCutover = date.getTime(); 299: } 300: 301: /** 302: * Gets the date of the switch from Julian dates to Gregorian dates. 303: * 304: * @return the date of the change. 305: */ 306: public final Date getGregorianChange() 307: { 308: return new Date(gregorianCutover); 309: } 310: 311: /** 312: * <p> 313: * Determines if the given year is a leap year. The result is 314: * undefined if the Gregorian change took place in 1800, so that 315: * the end of February is skipped, and that year is specified. 316: * (well...). 317: * </p> 318: * <p> 319: * To specify a year in the BC era, use a negative value calculated 320: * as 1 - y, where y is the required year in BC. So, 1 BC is 0, 321: * 2 BC is -1, 3 BC is -2, etc. 322: * </p> 323: * 324: * @param year a year (use a negative value for BC). 325: * @return true, if the given year is a leap year, false otherwise. 326: */ 327: public boolean isLeapYear(int year) 328: { 329: // Only years divisible by 4 can be leap years 330: if ((year & 3) != 0) 331: return false; 332: 333: // Is the leap-day a Julian date? Then it's a leap year 334: if (! isGregorian(year, 31 + 29 - 1)) 335: return true; 336: 337: // Apply gregorian rules otherwise 338: return ((year % 100) != 0 || (year % 400) == 0); 339: } 340: 341: /** 342: * Retrieves the day of the week corresponding to the specified 343: * day of the specified year. 344: * 345: * @param year the year in which the dayOfYear occurs. 346: * @param dayOfYear the day of the year (an integer between 0 and 347: * and 366) 348: */ 349: private int getWeekDay(int year, int dayOfYear) 350: { 351: boolean greg = isGregorian(year, dayOfYear); 352: int day = (int) getLinearDay(year, dayOfYear, greg); 353: 354: // The epoch was a thursday. 355: int weekday = (day + THURSDAY) % 7; 356: if (weekday <= 0) 357: weekday += 7; 358: return weekday; 359: } 360: 361: /** 362: * Returns the day of the week for the first day of a given month (0..11) 363: */ 364: private int getFirstDayOfMonth(int year, int month) 365: { 366: int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; 367: 368: if (month > 11) 369: { 370: year += (month / 12); 371: month = month % 12; 372: } 373: 374: if (month < 0) 375: { 376: year += (int) month / 12; 377: month = month % 12; 378: if (month < 0) 379: { 380: month += 12; 381: year--; 382: } 383: } 384: 385: int dayOfYear = dayCount[month] + 1; 386: if (month > 1) 387: if (isLeapYear(year)) 388: dayOfYear++; 389: 390: boolean greg = isGregorian(year, dayOfYear); 391: int day = (int) getLinearDay(year, dayOfYear, greg); 392: 393: // The epoch was a thursday. 394: int weekday = (day + THURSDAY) % 7; 395: if (weekday <= 0) 396: weekday += 7; 397: return weekday; 398: } 399: 400: /** 401: * Takes a year, and a (zero based) day of year and determines 402: * if it is gregorian or not. 403: */ 404: private boolean isGregorian(int year, int dayOfYear) 405: { 406: int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear 407: - EPOCH_DAYS; // gregorian days from 1 to epoch. 408: int gregFactor = (int) Math.floor((double) (year - 1) / 400.) 409: - (int) Math.floor((double) (year - 1) / 100.); 410: 411: return ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover); 412: } 413: 414: /** 415: * Check set fields for validity, without leniency. 416: * 417: * @throws IllegalArgumentException if a field is invalid 418: */ 419: private void nonLeniencyCheck() throws IllegalArgumentException 420: { 421: int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 422: int year = fields[YEAR]; 423: int month = fields[MONTH]; 424: int leap = isLeapYear(year) ? 1 : 0; 425: 426: if (isSet[ERA] && fields[ERA] != AD && fields[ERA] != BC) 427: throw new IllegalArgumentException("Illegal ERA."); 428: if (isSet[YEAR] && fields[YEAR] < 1) 429: throw new IllegalArgumentException("Illegal YEAR."); 430: if (isSet[MONTH] && (month < 0 || month > 11)) 431: throw new IllegalArgumentException("Illegal MONTH."); 432: if (isSet[WEEK_OF_YEAR]) 433: { 434: int daysInYear = 365 + leap; 435: daysInYear += (getFirstDayOfMonth(year, 0) - 1); // pad first week 436: int last = getFirstDayOfMonth(year, 11) + 4; 437: if (last > 7) 438: last -= 7; 439: daysInYear += 7 - last; 440: int weeks = daysInYear / 7; 441: if (fields[WEEK_OF_YEAR] < 1 || fields[WEEK_OF_YEAR] > weeks) 442: throw new IllegalArgumentException("Illegal WEEK_OF_YEAR."); 443: } 444: 445: if (isSet[WEEK_OF_MONTH]) 446: { 447: int weeks = (month == 1 && leap == 0) ? 5 : 6; 448: if (fields[WEEK_OF_MONTH] < 1 || fields[WEEK_OF_MONTH] > weeks) 449: throw new IllegalArgumentException("Illegal WEEK_OF_MONTH."); 450: } 451: 452: if (isSet[DAY_OF_MONTH]) 453: if (fields[DAY_OF_MONTH] < 1 454: || fields[DAY_OF_MONTH] > month_days[month] 455: + ((month == 1) ? leap : 0)) 456: throw new IllegalArgumentException("Illegal DAY_OF_MONTH."); 457: 458: if (isSet[DAY_OF_YEAR] 459: && (fields[DAY_OF_YEAR] < 1 || fields[DAY_OF_YEAR] > 365 + leap)) 460: throw new IllegalArgumentException("Illegal DAY_OF_YEAR."); 461: 462: if (isSet[DAY_OF_WEEK] 463: && (fields[DAY_OF_WEEK] < 1 || fields[DAY_OF_WEEK] > 7)) 464: throw new IllegalArgumentException("Illegal DAY_OF_WEEK."); 465: 466: if (isSet[DAY_OF_WEEK_IN_MONTH]) 467: { 468: int weeks = (month == 1 && leap == 0) ? 4 : 5; 469: if (fields[DAY_OF_WEEK_IN_MONTH] < -weeks 470: || fields[DAY_OF_WEEK_IN_MONTH] > weeks) 471: throw new IllegalArgumentException("Illegal DAY_OF_WEEK_IN_MONTH."); 472: } 473: 474: if (isSet[AM_PM] && fields[AM_PM] != AM && fields[AM_PM] != PM) 475: throw new IllegalArgumentException("Illegal AM_PM."); 476: if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11)) 477: throw new IllegalArgumentException("Illegal HOUR."); 478: if (isSet[HOUR_OF_DAY] 479: && (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23)) 480: throw new IllegalArgumentException("Illegal HOUR_OF_DAY."); 481: if (isSet[MINUTE] && (fields[MINUTE] < 0 || fields[MINUTE] > 59)) 482: throw new IllegalArgumentException("Illegal MINUTE."); 483: if (isSet[SECOND] && (fields[SECOND] < 0 || fields[SECOND] > 59)) 484: throw new IllegalArgumentException("Illegal SECOND."); 485: if (isSet[MILLISECOND] 486: && (fields[MILLISECOND] < 0 || fields[MILLISECOND] > 999)) 487: throw new IllegalArgumentException("Illegal MILLISECOND."); 488: if (isSet[ZONE_OFFSET] 489: && (fields[ZONE_OFFSET] < -12 * 60 * 60 * 1000L 490: || fields[ZONE_OFFSET] > 12 * 60 * 60 * 1000L)) 491: throw new IllegalArgumentException("Illegal ZONE_OFFSET."); 492: if (isSet[DST_OFFSET] 493: && (fields[DST_OFFSET] < -12 * 60 * 60 * 1000L 494: || fields[DST_OFFSET] > 12 * 60 * 60 * 1000L)) 495: throw new IllegalArgumentException("Illegal DST_OFFSET."); 496: } 497: 498: /** 499: * Converts the time field values (<code>fields</code>) to 500: * milliseconds since the epoch UTC (<code>time</code>). 501: * 502: * @throws IllegalArgumentException if any calendar fields 503: * are invalid. 504: */ 505: protected synchronized void computeTime() 506: { 507: int millisInDay = 0; 508: int era = fields[ERA]; 509: int year = fields[YEAR]; 510: int month = fields[MONTH]; 511: int day = fields[DAY_OF_MONTH]; 512: 513: int minute = fields[MINUTE]; 514: int second = fields[SECOND]; 515: int millis = fields[MILLISECOND]; 516: int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 517: int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; 518: int hour = 0; 519: 520: if (! isLenient()) 521: nonLeniencyCheck(); 522: 523: if (! isSet[MONTH] && (! isSet[DAY_OF_WEEK] || isSet[WEEK_OF_YEAR])) 524: { 525: // 5: YEAR + DAY_OF_WEEK + WEEK_OF_YEAR 526: if (isSet[WEEK_OF_YEAR]) 527: { 528: int first = getFirstDayOfMonth(year, 0); 529: int offs = 1; 530: int daysInFirstWeek = getFirstDayOfWeek() - first; 531: if (daysInFirstWeek <= 0) 532: daysInFirstWeek += 7; 533: 534: if (daysInFirstWeek < getMinimalDaysInFirstWeek()) 535: offs += daysInFirstWeek; 536: else 537: offs -= 7 - daysInFirstWeek; 538: month = 0; 539: day = offs + 7 * (fields[WEEK_OF_YEAR] - 1); 540: offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek(); 541: 542: if (offs < 0) 543: offs += 7; 544: day += offs; 545: } 546: else 547: { 548: // 4: YEAR + DAY_OF_YEAR 549: month = 0; 550: day = fields[DAY_OF_YEAR]; 551: } 552: } 553: else 554: { 555: if (isSet[DAY_OF_WEEK]) 556: { 557: int first = getFirstDayOfMonth(year, month); 558: 559: // 3: YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK 560: if (isSet[DAY_OF_WEEK_IN_MONTH]) 561: { 562: if (fields[DAY_OF_WEEK_IN_MONTH] < 0) 563: { 564: month++; 565: first = getFirstDayOfMonth(year, month); 566: day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH]); 567: } 568: else 569: day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH] - 1); 570: 571: int offs = fields[DAY_OF_WEEK] - first; 572: if (offs < 0) 573: offs += 7; 574: day += offs; 575: } 576: else 577: { // 2: YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK 578: int offs = 1; 579: int daysInFirstWeek = getFirstDayOfWeek() - first; 580: if (daysInFirstWeek <= 0) 581: daysInFirstWeek += 7; 582: 583: if (daysInFirstWeek < getMinimalDaysInFirstWeek()) 584: offs += daysInFirstWeek; 585: else 586: offs -= 7 - daysInFirstWeek; 587: 588: day = offs + 7 * (fields[WEEK_OF_MONTH] - 1); 589: offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek(); 590: if (offs < 0) 591: offs += 7; 592: day += offs; 593: } 594: } 595: 596: // 1: YEAR + MONTH + DAY_OF_MONTH 597: } 598: if (era == BC && year > 0) 599: year = 1 - year; 600: 601: // rest of code assumes day/month/year set 602: // should negative BC years be AD? 603: // get the hour (but no check for validity) 604: if (isSet[HOUR]) 605: { 606: hour = fields[HOUR]; 607: if (fields[AM_PM] == PM) 608: hour += 12; 609: } 610: else 611: hour = fields[HOUR_OF_DAY]; 612: 613: // Read the era,year,month,day fields and convert as appropriate. 614: // Calculate number of milliseconds into the day 615: // This takes care of both h, m, s, ms over/underflows. 616: long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L + millis; 617: day += allMillis / (24 * 60 * 60 * 1000L); 618: millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L)); 619: 620: if (month < 0) 621: { 622: year += (int) month / 12; 623: month = month % 12; 624: if (month < 0) 625: { 626: month += 12; 627: year--; 628: } 629: } 630: if (month > 11) 631: { 632: year += (month / 12); 633: month = month % 12; 634: } 635: 636: month_days[1] = isLeapYear(year) ? 29 : 28; 637: 638: while (day <= 0) 639: { 640: if (month == 0) 641: { 642: year--; 643: month_days[1] = isLeapYear(year) ? 29 : 28; 644: } 645: month = (month + 11) % 12; 646: day += month_days[month]; 647: } 648: while (day > month_days[month]) 649: { 650: day -= (month_days[month]); 651: month = (month + 1) % 12; 652: if (month == 0) 653: { 654: year++; 655: month_days[1] = isLeapYear(year) ? 29 : 28; 656: } 657: } 658: 659: // ok, by here we have valid day,month,year,era and millisinday 660: int dayOfYear = dayCount[month] + day - 1; // (day starts on 1) 661: if (isLeapYear(year) && month > 1) 662: dayOfYear++; 663: 664: int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear 665: - EPOCH_DAYS; // gregorian days from 1 to epoch. 666: int gregFactor = (int) Math.floor((double) (year - 1) / 400.) 667: - (int) Math.floor((double) (year - 1) / 100.); 668: 669: if ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover) 670: relativeDay += gregFactor; 671: else 672: relativeDay -= 2; 673: 674: time = relativeDay * (24 * 60 * 60 * 1000L) + millisInDay; 675: 676: // the epoch was a Thursday. 677: int weekday = (int) (relativeDay + THURSDAY) % 7; 678: if (weekday <= 0) 679: weekday += 7; 680: fields[DAY_OF_WEEK] = weekday; 681: 682: // Time zone corrections. 683: TimeZone zone = getTimeZone(); 684: int rawOffset = isSet[ZONE_OFFSET] ? fields[ZONE_OFFSET] 685: : zone.getRawOffset(); 686: 687: int dstOffset = isSet[DST_OFFSET] ? fields[DST_OFFSET] 688: : (zone.getOffset((year < 0) ? BC : AD, 689: (year < 0) ? 1 - year 690: : year, 691: month, day, weekday, 692: millisInDay) 693: - zone.getRawOffset()); 694: 695: time -= rawOffset + dstOffset; 696: 697: isTimeSet = true; 698: } 699: 700: /** 701: * Get the linear day in days since the epoch, using the 702: * Julian or Gregorian calendar as specified. If you specify a 703: * nonpositive year it is interpreted as BC as following: 0 is 1 704: * BC, -1 is 2 BC and so on. 705: * 706: * @param year the year of the date. 707: * @param dayOfYear the day of year of the date; 1 based. 708: * @param gregorian <code>true</code>, if we should use the Gregorian rules. 709: * @return the days since the epoch, may be negative. 710: */ 711: private long getLinearDay(int year, int dayOfYear, boolean gregorian) 712: { 713: // The 13 is the number of days, that were omitted in the Gregorian 714: // Calender until the epoch. 715: // We shift right by 2 instead of dividing by 4, to get correct 716: // results for negative years (and this is even more efficient). 717: long julianDay = (year - 1) * 365L + ((year - 1) >> 2) + (dayOfYear - 1) 718: - EPOCH_DAYS; // gregorian days from 1 to epoch. 719: 720: if (gregorian) 721: { 722: // subtract the days that are missing in gregorian calendar 723: // with respect to julian calendar. 724: // 725: // Okay, here we rely on the fact that the gregorian 726: // calendar was introduced in the AD era. This doesn't work 727: // with negative years. 728: // 729: // The additional leap year factor accounts for the fact that 730: // a leap day is not seen on Jan 1 of the leap year. 731: int gregOffset = (int) Math.floor((double) (year - 1) / 400.) 732: - (int) Math.floor((double) (year - 1) / 100.); 733: 734: return julianDay + gregOffset; 735: } 736: else 737: julianDay -= 2; 738: return julianDay; 739: } 740: 741: /** 742: * Converts the given linear day into era, year, month, 743: * day_of_year, day_of_month, day_of_week, and writes the result 744: * into the fields array. 745: * 746: * @param day the linear day. 747: * @param gregorian true, if we should use Gregorian rules. 748: */ 749: private void calculateDay(int[] fields, long day, boolean gregorian) 750: { 751: // the epoch was a Thursday. 752: int weekday = (int) (day + THURSDAY) % 7; 753: if (weekday <= 0) 754: weekday += 7; 755: fields[DAY_OF_WEEK] = weekday; 756: 757: // get a first approximation of the year. This may be one 758: // year too big. 759: int year = 1970 760: + (int) (gregorian 761: ? ((day - 100L) * 400L) / (365L * 400L + 100L - 4L 762: + 1L) : ((day - 100L) * 4L) / (365L * 4L + 1L)); 763: if (day >= 0) 764: year++; 765: 766: long firstDayOfYear = getLinearDay(year, 1, gregorian); 767: 768: // Now look in which year day really lies. 769: if (day < firstDayOfYear) 770: { 771: year--; 772: firstDayOfYear = getLinearDay(year, 1, gregorian); 773: } 774: 775: day -= firstDayOfY