?? gregoriancalendar.java
字號:
complete(); // Force update of DST_OFFSET field return internalGet(DST_OFFSET) != 0; } /** * Return the year that corresponds to the <code>WEEK_OF_YEAR</code> field. * This may be one year before or after the calendar year stored * in the <code>YEAR</code> field. For example, January 1, 1999 is considered * Friday of week 53 of 1998 (if minimal days in first week is * 2 or less, and the first day of the week is Sunday). Given * these same settings, the ISO year of January 1, 1999 is * 1998. * <p> * Warning: This method will complete all fields. * @return the year corresponding to the <code>WEEK_OF_YEAR</code> field, which * may be one year before or after the <code>YEAR</code> field. * @see #WEEK_OF_YEAR */ int getISOYear() { complete(); int woy = internalGet(WEEK_OF_YEAR); // Get the ISO year, which matches the week of year. This // may be one year before or after the calendar year. int isoYear = internalGet(YEAR); if (internalGet(MONTH) == Calendar.JANUARY) { if (woy >= 52) { --isoYear; } } else { if (woy == 1) { ++isoYear; } } return isoYear; }/////////////////////////////// Time => Fields computation///////////////////////////// /** * Converts UTC as milliseconds to time field values. * The time is <em>not</em> * recomputed first; to recompute the time, then the fields, call the * <code>complete</code> method. * @see Calendar#complete */ protected void computeFields() { computeFieldsImpl(); // Careful here: We are manually setting the time stamps[] // flags to INTERNALLY_SET, so we must be sure that the // computeFieldsImpl method actually does set all the fields. for (int i = 0; i < FIELD_COUNT; ++i) { stamp[i] = INTERNALLY_SET; isSet[i] = true; } } /** * This computeFieldsImpl implements the conversion from UTC (a * millisecond offset from 1970-01-01T00:00:00.000Z) to calendar * field values. */ private void computeFieldsImpl() { TimeZone tz = getTimeZone(); int[] offsets = new int[2]; int offset; if (tz instanceof ZoneInfo) { offset = ((ZoneInfo)tz).getOffsets(time, offsets); } else { offset = tz.getOffsets(time, offsets); } long localMillis = time + offset; // here localMillis is wall /* Check for very extreme values -- millis near Long.MIN_VALUE or * Long.MAX_VALUE. For these values, adding the zone offset can push * the millis past MAX_VALUE to MIN_VALUE, or vice versa. This produces * the undesirable effect that the time can wrap around at the ends, * yielding, for example, a Date(Long.MAX_VALUE) with a big BC year * (should be AD). Handle this by pinning such values to Long.MIN_VALUE * or Long.MAX_VALUE. - liu 8/11/98 bug 4149677 */ if (time > 0 && localMillis < 0 && offset > 0) { localMillis = Long.MAX_VALUE; } else if (time < 0 && localMillis > 0 && offset < 0) { localMillis = Long.MIN_VALUE; } // Time to fields takes the wall millis (Standard or DST). timeToFields(localMillis, false); long days = floorDivide(localMillis, ONE_DAY); int millisInDay = (int) (localMillis - (days * ONE_DAY)); if (millisInDay < 0) { millisInDay += ONE_DAY; } // Fill in all time-related fields based on millisInDay. Call internalSet() // so as not to perturb flags. internalSet(MILLISECOND, millisInDay % 1000); millisInDay /= 1000; internalSet(SECOND, millisInDay % 60); millisInDay /= 60; internalSet(MINUTE, millisInDay % 60); millisInDay /= 60; internalSet(HOUR_OF_DAY, millisInDay); internalSet(AM_PM, millisInDay / 12); // Assume AM == 0 internalSet(HOUR, millisInDay % 12); internalSet(ZONE_OFFSET, offsets[0]); internalSet(DST_OFFSET, offsets[1]); } /** * Convert the time as milliseconds to the date fields. Millis must be * given as local wall millis to get the correct local day. For example, * if it is 11:30 pm Standard, and DST is in effect, the correct DST millis * must be passed in to get the right date. * <p> * Fields that are completed by this method: ERA, YEAR, MONTH, DATE, * DAY_OF_WEEK, DAY_OF_YEAR, WEEK_OF_YEAR, WEEK_OF_MONTH, * DAY_OF_WEEK_IN_MONTH. * @param theTime the wall-clock time in milliseconds (either Standard or DST), * whichever is in effect * @param quick if true, only compute the ERA, YEAR, MONTH, DATE, * DAY_OF_WEEK, and DAY_OF_YEAR. */ private final void timeToFields(long theTime, boolean quick) { int rawYear, year, month, date, dayOfWeek, dayOfYear, weekCount, era; boolean isLeap; // Compute the year, month, and day of month from the given millis if (theTime >= normalizedGregorianCutover) { // The Gregorian epoch day is zero for Monday January 1, year 1. long gregorianEpochDay = millisToJulianDay(theTime) - JAN_1_1_JULIAN_DAY; // Here we convert from the day number to the multiple radix // representation. We use 400-year, 100-year, and 4-year cycles. // For example, the 4-year cycle has 4 years + 1 leap day; giving // 1461 == 365*4 + 1 days. int n400, n100, n4, n1; if (gregorianEpochDay > 0) { n400 = (int)(gregorianEpochDay / 146097); dayOfYear = (int)(gregorianEpochDay % 146097); n100 = dayOfYear / 36524; dayOfYear %= 36524; n4 = dayOfYear / 1461; dayOfYear %= 1461; n1 = dayOfYear / 365; dayOfYear %= 365; // zero-based day of year } else { int[] rem = new int[1]; n400 = floorDivide(gregorianEpochDay, 146097, rem); // 400-year cycle length n100 = floorDivide(rem[0], 36524, rem); // 100-year cycle length n4 = floorDivide(rem[0], 1461, rem); // 4-year cycle length n1 = floorDivide(rem[0], 365, rem); dayOfYear = rem[0]; // zero-based day of year } rawYear = 400*n400 + 100*n100 + 4*n4 + n1; if (n100 == 4 || n1 == 4) { dayOfYear = 365; // Dec 31 at end of 4- or 400-yr cycle } else { ++rawYear; } isLeap = ((rawYear&0x3) == 0) && // equiv. to (rawYear%4 == 0) (rawYear%100 != 0 || rawYear%400 == 0); // Gregorian day zero is a Monday dayOfWeek = (int)((gregorianEpochDay+1) % 7); } else { // The Julian epoch day (not the same as Julian Day) // is zero on Saturday December 30, 0 (Gregorian). long julianEpochDay = millisToJulianDay(theTime) - (JAN_1_1_JULIAN_DAY - 2); rawYear = (int) floorDivide(4*julianEpochDay + 1464, 1461); // Compute the Julian calendar day number for January 1, rawYear long january1 = 365*(rawYear-1) + floorDivide(rawYear-1, 4); dayOfYear = (int)(julianEpochDay - january1); // 0-based // Julian leap years occurred historically every 4 years starting // with 8 AD. Before 8 AD the spacing is irregular; every 3 years // from 45 BC to 9 BC, and then none until 8 AD. However, we don't // implement this historical detail; instead, we implement the // computationally cleaner proleptic calendar, which assumes // consistent 4-year cycles throughout time. isLeap = ((rawYear&0x3) == 0); // equiv. to (rawYear%4 == 0) // Julian calendar day zero is a Saturday dayOfWeek = (int)((julianEpochDay-1) % 7); } // Common Julian/Gregorian calculation int correction = 0; int march1 = isLeap ? 60 : 59; // zero-based DOY for March 1 if (dayOfYear >= march1) { correction = isLeap ? 1 : 2; } month = (12 * (dayOfYear + correction) + 6) / 367; // zero-based month date = dayOfYear - (isLeap ? LEAP_NUM_DAYS[month] : NUM_DAYS[month]) + 1; // one-based DOM // Normalize day of week dayOfWeek += (dayOfWeek < 0) ? (SUNDAY+7) : SUNDAY; era = AD; year = rawYear; if (year < 1) { era = BC; year = 1 - year; } internalSet(ERA, era); internalSet(YEAR, year); internalSet(MONTH, month + JANUARY); // 0-based internalSet(DATE, date); internalSet(DAY_OF_WEEK, dayOfWeek); internalSet(DAY_OF_YEAR, ++dayOfYear); // Convert from 0-based to 1-based if (quick) { return; } // WEEK_OF_YEAR start // Compute the week of the year. Valid week numbers run from 1 to 52 // or 53, depending on the year, the first day of the week, and the // minimal days in the first week. Days at the start of the year may // fall into the last week of the previous year; days at the end of // the year may fall into the first week of the next year. int relDow = (dayOfWeek + 7 - getFirstDayOfWeek()) % 7; // 0..6 int relDowJan1 = (dayOfWeek - dayOfYear + 701 - getFirstDayOfWeek()) % 7; // 0..6 int woy = (dayOfYear - 1 + relDowJan1) / 7; // 0..53 if ((7 - relDowJan1) >= getMinimalDaysInFirstWeek()) { ++woy; } // XXX: The calculation of dayOfYear does not take into account // Gregorian cut over date. The next if statement depends on that // assumption. if (dayOfYear > 359) { // Fast check which eliminates most cases // Check to see if we are in the last week; if so, we need // to handle the case in which we are the first week of the // next year. int lastDoy = yearLength(); int lastRelDow = (relDow + lastDoy - dayOfYear) % 7; if (lastRelDow < 0) { lastRelDow += 7; } if (((6 - lastRelDow) >= getMinimalDaysInFirstWeek()) && ((dayOfYear + 7 - relDow) > lastDoy)) { woy = 1; } } else if (woy == 0) { // We are the last week of the previous year. int prevDoy = dayOfYear + yearLength(rawYear - 1); woy = weekNumber(prevDoy, dayOfWeek); } internalSet(WEEK_OF_YEAR, woy); // WEEK_OF_YEAR end internalSet(WEEK_OF_MONTH, weekNumber(date, dayOfWeek)); internalSet(DAY_OF_WEEK_IN_MONTH, (date-1) / 7 + 1); }/////////////////////////////// Fields => Time computation///////////////////////////// /** * Overrides Calendar * Converts time field values to UTC as milliseconds. * @exception IllegalArgumentException if any fields are invalid. */ protected void computeTime() { if (!isLenient() && !validateFields()) { throw new IllegalArgumentException(); } // This function takes advantage of the fact that unset fields in // the time field list have a value of zero. // The year defaults to the epoch start. int year = (stamp[YEAR] != UNSET) ? internalGet(YEAR) : EPOCH_YEAR; // The YEAR field must always be used regardless of its SET // state because YEAR is a mandatory field to determine the date // and the default value (EPOCH_YEAR) may change through the // normalization process. int fieldMask = 1 << YEAR; int era = AD; if (stamp[ERA] != UNSET) { era = internalGet(ERA); fieldMask |= 1 << ERA; if (era == BC) { year = 1 - year; } else if (era != AD) { // Even in lenient mode we disallow ERA values other than AD & BC throw new IllegalArgumentException("Invalid era"); } } int[] fieldMaskParam = { fieldMask }; // First, use the year to determine whether to use the Gregorian or the // Julian calendar. If the year is not the year of the cutover, this // computation will be correct. But if the year is the cutover year, // this may be incorrect. In that case, assume the Gregorian calendar, // make the computation, and then recompute if the resultant mi
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -