📄 gregoriancalendar.java
字号:
} if (isSet[DAY_OF_MONTH]) if (fields[DAY_OF_MONTH] < 1 || fields[DAY_OF_MONTH] > month_days[month] + ((month == 1) ? leap : 0)) throw new IllegalArgumentException("Illegal DAY_OF_MONTH."); if (isSet[DAY_OF_YEAR] && (fields[DAY_OF_YEAR] < 1 || fields[DAY_OF_YEAR] > 365 + leap)) throw new IllegalArgumentException("Illegal DAY_OF_YEAR."); if (isSet[DAY_OF_WEEK] && (fields[DAY_OF_WEEK] < 1 || fields[DAY_OF_WEEK] > 7)) throw new IllegalArgumentException("Illegal DAY_OF_WEEK."); if (isSet[DAY_OF_WEEK_IN_MONTH]) { int weeks = (month == 1 && leap == 0) ? 4 : 5; if (fields[DAY_OF_WEEK_IN_MONTH] < -weeks || fields[DAY_OF_WEEK_IN_MONTH] > weeks) throw new IllegalArgumentException("Illegal DAY_OF_WEEK_IN_MONTH."); } if (isSet[AM_PM] && fields[AM_PM] != AM && fields[AM_PM] != PM) throw new IllegalArgumentException("Illegal AM_PM."); if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11)) throw new IllegalArgumentException("Illegal HOUR."); if (isSet[HOUR_OF_DAY] && (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23)) throw new IllegalArgumentException("Illegal HOUR_OF_DAY."); if (isSet[MINUTE] && (fields[MINUTE] < 0 || fields[MINUTE] > 59)) throw new IllegalArgumentException("Illegal MINUTE."); if (isSet[SECOND] && (fields[SECOND] < 0 || fields[SECOND] > 59)) throw new IllegalArgumentException("Illegal SECOND."); if (isSet[MILLISECOND] && (fields[MILLISECOND] < 0 || fields[MILLISECOND] > 999)) throw new IllegalArgumentException("Illegal MILLISECOND."); if (isSet[ZONE_OFFSET] && (fields[ZONE_OFFSET] < -12 * 60 * 60 * 1000L || fields[ZONE_OFFSET] > 12 * 60 * 60 * 1000L)) throw new IllegalArgumentException("Illegal ZONE_OFFSET."); if (isSet[DST_OFFSET] && (fields[DST_OFFSET] < -12 * 60 * 60 * 1000L || fields[DST_OFFSET] > 12 * 60 * 60 * 1000L)) throw new IllegalArgumentException("Illegal DST_OFFSET."); } /** * Converts the time field values (<code>fields</code>) to * milliseconds since the epoch UTC (<code>time</code>). * * @throws IllegalArgumentException if any calendar fields * are invalid. */ protected synchronized void computeTime() { int millisInDay = 0; int era = fields[ERA]; int year = fields[YEAR]; int month = fields[MONTH]; int day = fields[DAY_OF_MONTH]; int minute = fields[MINUTE]; int second = fields[SECOND]; int millis = fields[MILLISECOND]; int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; int hour = 0; if (! isLenient()) nonLeniencyCheck(); if (! isSet[MONTH] && (! isSet[DAY_OF_WEEK] || isSet[WEEK_OF_YEAR])) { // 5: YEAR + DAY_OF_WEEK + WEEK_OF_YEAR if (isSet[WEEK_OF_YEAR]) { int first = getFirstDayOfMonth(year, 0); int offs = 1; int daysInFirstWeek = getFirstDayOfWeek() - first; if (daysInFirstWeek <= 0) daysInFirstWeek += 7; if (daysInFirstWeek < getMinimalDaysInFirstWeek()) offs += daysInFirstWeek; else offs -= 7 - daysInFirstWeek; month = 0; day = offs + 7 * (fields[WEEK_OF_YEAR] - 1); offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek(); if (offs < 0) offs += 7; day += offs; } else { // 4: YEAR + DAY_OF_YEAR month = 0; day = fields[DAY_OF_YEAR]; } } else { if (isSet[DAY_OF_WEEK]) { int first = getFirstDayOfMonth(year, month); // 3: YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK if (isSet[DAY_OF_WEEK_IN_MONTH]) { if (fields[DAY_OF_WEEK_IN_MONTH] < 0) { month++; first = getFirstDayOfMonth(year, month); day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH]); } else day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH] - 1); int offs = fields[DAY_OF_WEEK] - first; if (offs < 0) offs += 7; day += offs; } else { // 2: YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK int offs = 1; int daysInFirstWeek = getFirstDayOfWeek() - first; if (daysInFirstWeek <= 0) daysInFirstWeek += 7; if (daysInFirstWeek < getMinimalDaysInFirstWeek()) offs += daysInFirstWeek; else offs -= 7 - daysInFirstWeek; day = offs + 7 * (fields[WEEK_OF_MONTH] - 1); offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek(); if (offs <= 0) offs += 7; day += offs; } } // 1: YEAR + MONTH + DAY_OF_MONTH } if (era == BC && year > 0) year = 1 - year; // rest of code assumes day/month/year set // should negative BC years be AD? // get the hour (but no check for validity) if (isSet[HOUR]) { hour = fields[HOUR]; if (fields[AM_PM] == PM) hour += 12; } else hour = fields[HOUR_OF_DAY]; // Read the era,year,month,day fields and convert as appropriate. // Calculate number of milliseconds into the day // This takes care of both h, m, s, ms over/underflows. long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L + millis; day += allMillis / (24 * 60 * 60 * 1000L); millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L)); if (month < 0) { year += (int) month / 12; month = month % 12; if (month < 0) { month += 12; year--; } } if (month > 11) { year += (month / 12); month = month % 12; } month_days[1] = isLeapYear(year) ? 29 : 28; while (day <= 0) { if (month == 0) { year--; month_days[1] = isLeapYear(year) ? 29 : 28; } month = (month + 11) % 12; day += month_days[month]; } while (day > month_days[month]) { day -= (month_days[month]); month = (month + 1) % 12; if (month == 0) { year++; month_days[1] = isLeapYear(year) ? 29 : 28; } } // ok, by here we have valid day,month,year,era and millisinday int dayOfYear = dayCount[month] + day - 1; // (day starts on 1) if (isLeapYear(year) && month > 1) dayOfYear++; int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear - EPOCH_DAYS; // gregorian days from 1 to epoch. int gregFactor = (int) Math.floor((double) (year - 1) / 400.) - (int) Math.floor((double) (year - 1) / 100.); if ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover) relativeDay += gregFactor; else relativeDay -= 2; time = relativeDay * (24 * 60 * 60 * 1000L) + millisInDay; // the epoch was a Thursday. int weekday = (int) (relativeDay + THURSDAY) % 7; if (weekday <= 0) weekday += 7; fields[DAY_OF_WEEK] = weekday; // Time zone corrections. TimeZone zone = getTimeZone(); int rawOffset = isSet[ZONE_OFFSET] ? fields[ZONE_OFFSET] : zone.getRawOffset(); int dstOffset = isSet[DST_OFFSET] ? fields[DST_OFFSET] : (zone.getOffset((year < 0) ? BC : AD, (year < 0) ? 1 - year : year, month, day, weekday, millisInDay) - zone.getRawOffset()); time -= rawOffset + dstOffset; isTimeSet = true; } /** * Get the linear day in days since the epoch, using the * Julian or Gregorian calendar as specified. If you specify a * nonpositive year it is interpreted as BC as following: 0 is 1 * BC, -1 is 2 BC and so on. * * @param year the year of the date. * @param dayOfYear the day of year of the date; 1 based. * @param gregorian <code>true</code>, if we should use the Gregorian rules. * @return the days since the epoch, may be negative. */ private long getLinearDay(int year, int dayOfYear, boolean gregorian) { // The 13 is the number of days, that were omitted in the Gregorian // Calender until the epoch. // We shift right by 2 instead of dividing by 4, to get correct // results for negative years (and this is even more efficient). long julianDay = (year - 1) * 365L + ((year - 1) >> 2) + (dayOfYear - 1) - EPOCH_DAYS; // gregorian days from 1 to epoch. if (gregorian) { // subtract the days that are missing in gregorian calendar // with respect to julian calendar. // // Okay, here we rely on the fact that the gregorian // calendar was introduced in the AD era. This doesn't work // with negative years. // // The additional leap year factor accounts for the fact that // a leap day is not seen on Jan 1 of the leap year. int gregOffset = (int) Math.floor((double) (year - 1) / 400.) - (int) Math.floor((double) (year - 1) / 100.); return julianDay + gregOffset; } else julianDay -= 2; return julianDay; } /** * Converts the given linear day into era, year, month, * day_of_year, day_of_month, day_of_week, and writes the result * into the fields array. * * @param day the linear day. * @param gregorian true, if we should use Gregorian rules. */ private void calculateDay(int[] fields, long day, boolean gregorian) { // the epoch was a Thursday. int weekday = (int) (day + THURSDAY) % 7; if (weekday <= 0) weekday += 7; fields[DAY_OF_WEEK] = weekday; // get a first approximation of the year. This may be one // year too big. int year = 1970 + (int) (gregorian ? ((day - 100L) * 400L) / (365L * 400L + 100L - 4L + 1L) : ((day - 100L) * 4L) / (365L * 4L + 1L)); if (day >= 0) year++; long firstDayOfYear = getLinearDay(year, 1, gregorian); // Now look in which year day really lies. if (day < firstDayOfYear) { year--; firstDayOfYear = getLinearDay(year, 1, gregorian); } day -= firstDayOfYear - 1; // day of year, one based. fields[DAY_OF_YEAR] = (int) day; if (year <= 0) { fields[ERA] = BC; fields[YEAR] = 1 - year; } else { fields[ERA] = AD; fields[YEAR] = year; } int leapday = isLeapYear(year) ? 1 : 0; if (day <= 31 + 28 + leapday) { fields[MONTH] = (int) day / 32; // 31->JANUARY, 32->FEBRUARY fields[DAY_OF_MONTH] = (int) day - 31 * fields[MONTH]; } else { // A few more magic formulas int scaledDay = ((int) day - leapday) * 5 + 8; fields[MONTH] = scaledDay / (31 + 30 + 31 + 30 + 31); fields[DAY_OF_MONTH] = (scaledDay % (31 + 30 + 31 + 30 + 31)) / 5 + 1; } } /** * Converts the milliseconds since the epoch UTC * (<code>time</code>) to time fields * (<code>fields</code>). */ protected synchronized void computeFields() { boolean gregorian = (time >= gregorianCutover); TimeZone zone = getTimeZone(); fields[ZONE_OFFSET] = zone.getRawOffset(); long localTime = time + fields[ZONE_OFFSET]; long day = localTime / (24 * 60 * 60 * 1000L); int millisInDay = (int) (localTime % (24 * 60 * 60 * 1000L)); if (millisInDay < 0) { millisInDay += (24 * 60 * 60 * 1000); day--; } calculateDay(fields, day, gregorian); fields[DST_OFFSET] = zone.getOffset(fields[ERA], fields[YEAR], fields[MONTH], fields[DAY_OF_MONTH], fields[DAY_OF_WEEK], millisInDay) - fields[ZONE_OFFSET]; millisInDay += fields[DST_OFFSET]; if (millisInDay >= 24 * 60 * 60 * 1000) { millisInDay -= 24 * 60 * 60 * 1000; calculateDay(fields, ++day, gregorian); } fields[DAY_OF_WEEK_IN_MONTH] = (fields[DAY_OF_MONTH] + 6) / 7; // which day of the week are we (0..6), relative to getFirstDayOfWeek int relativeWeekday = (7 + fields[DAY_OF_WEEK] - getFirstDayOfWeek()) % 7; fields[WEEK_OF_MONTH] = (fields[DAY_OF_MONTH] - relativeWeekday + 12) / 7; int weekOfYear = (fields[DAY_OF_YEAR] - relativeWeekday + 6) / 7; // Do the Correction: getMinimalDaysInFirstWeek() is always in the // first week. int minDays = getMinimalDaysInFirstWeek(); int firstWeekday = (7 + getWeekDay(fields[YEAR], minDays) - getFirstDayOfWeek()) % 7; if (minDays - firstWeekday < 1) weekOfYear++; fields[WEEK_OF_YEAR] = weekOfYear; int hourOfDay = millisInDay / (60 * 60 * 1000); fields[AM_PM] = (hourOfDay < 12) ? AM : PM; int hour = hourOfDay % 12; fields[HOUR] = hour; fields[HOUR_OF_DAY] = hourOfDay; millisInDay %= (60 * 60 * 1000); fields[MINUTE] = millisInDay / (60 * 1000); millisInDay %= (60 * 1000); fields[SECOND] = millisInDay / (1000); fields[MILLISECOND] = millisInDay % 1000; areFieldsSet = isSet[ERA] = isSet[YEAR] = isSet[MONTH] = isSet[WEEK_OF_YEAR] = isSet[WEEK_OF_MONTH] = isSet[DAY_OF_MONTH] = isSet[DAY_OF_YEAR] = isSet[DAY_OF_WEEK] = isSet[DAY_OF_WEEK_IN_MONTH] = isSet[AM_PM] = isSet[HOUR] = isSet[HOUR_OF_DAY] = isSet[MINUTE] = isSet[SECOND] = isSet[MILLISECOND] = isSet[ZONE_OFFSET] = isSet[DST_OFFSET] = true; } /** * Return a hash code for this object, following the general contract * specified by {@link Object#hashCode()}. * @return the hash code */ public int hashCode() { int val = (int) ((gregorianCutover >>> 32) ^ (gregorianCutover & 0xffffffff)); return super.hashCode() ^ val; } /** * Compares the given calendar with this. An object, o, is * equivalent to this if it is also a <code>GregorianCalendar</code> * with the same time since the epoch under the same conditions * (same change date and same time zone). * * @param o the object to that we should compare. * @return true, if the given object is a calendar, that represents * the same time (but doesn't necessarily have the same fields). * @throws IllegalArgumentException if one of the fields * <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is * specified, if an unknown field is specified or if one * of the calendar fields receives an illegal value when * leniancy is not enabled. */ public boolean equals(Object o) { if (! (o instanceof GregorianCalendar)) return false; GregorianCalendar cal = (GregorianCalendar) o;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -