📄 gregoriancalendar.java
字号:
+ 7 * (fields[WEEK_OF_YEAR] + (fields[DAY_OF_WEEK] < getFirstDayOfWeek()? 0 : -1) + (weekday < getFirstDayOfWeek()? -1 : 0))}; } // As last resort return Jan, 1st. return new int[] {1, 0}; } /** * Converts the time field values (<code>fields</code>) to * milliseconds since the epoch UTC (<code>time</code>). */ protected synchronized void computeTime() { int era = isSet[ERA] ? fields[ERA] : AD; int year = isSet[YEAR] ? fields[YEAR] : 1970; if (era == BC) year = 1 - year; int[] daysOfYear = getDayOfYear(year); int hour = 0; if (isSet[HOUR_OF_DAY]) hour = fields[HOUR_OF_DAY]; else if (isSet[HOUR]) { hour = fields[HOUR]; if (isSet[AM_PM] && fields[AM_PM] == PM) hour += 12; } int minute = isSet[MINUTE] ? fields[MINUTE] : 0; int second = isSet[SECOND] ? fields[SECOND] : 0; int millis = isSet[MILLISECOND] ? fields[MILLISECOND] : 0; int millisInDay; if (isLenient()) { // prevent overflow long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L + millis; daysOfYear[1] += allMillis / (24 * 60 * 60 * 1000L); millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L)); } else { if (hour < 0 || hour >= 24 || minute < 0 || minute > 59 || second < 0 || second > 59 || millis < 0 || millis >= 1000) throw new IllegalArgumentException(); millisInDay = (((hour * 60) + minute) * 60 + second) * 1000 + millis; } time = getLinearTime(year, daysOfYear[0], millisInDay); // Add the relative days after calculating the linear time, to // get right behaviour when jumping over the gregorianCutover. time += daysOfYear[1] * (24 * 60 * 60 * 1000L); TimeZone zone = getTimeZone(); int rawOffset = isSet[ZONE_OFFSET] ? fields[ZONE_OFFSET] : zone.getRawOffset(); int dayOfYear = daysOfYear[0] + daysOfYear[1]; int month = (dayOfYear * 5 + 3) / (31 + 30 + 31 + 30 + 31); int day = (6 + (dayOfYear * 5 + 3) % (31 + 30 + 31 + 30 + 31)) / 5; int weekday = ((int) (time / (24 * 60 * 60 * 1000L)) + THURSDAY) % 7; if (weekday <= 0) weekday += 7; 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; } /** * Determines if the given year is a leap year. * * The year should be positive and you can't give an ERA. But * remember that before 4 BC there wasn't a consistent leap year * rule, so who cares. * * @param year a year use nonnegative value for BC. * @param gregorian if true, use gregorian leap year rule. * @return true, if the given year is a leap year, false otherwise. */ private boolean isLeapYear(int year, boolean gregorian) { if ((year & 3) != 0) // Only years divisible by 4 can be leap years return false; if (!gregorian) return true; // We rely on AD area here. return ((year % 100) != 0 || (year % 400) == 0); } /** * 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 True, if we should use Gregorian rules. * @return the days since the epoch, may be negative. */ private int 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). int julianDay = ((year * (365 * 4 + 1)) >> 2) + dayOfYear - ((1970 * (365 * 4 + 1)) / 4 + 1 - 13); 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 = (year / 400) - (year / 100) + 2; if (isLeapYear (year, true) && dayOfYear < 31 + 29) --gregOffset; julianDay += gregOffset; } 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. */ private void calculateDay(int day, boolean gregorian) { // the epoch is a Thursday. int weekday = (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 to big. int year = 1970 + (gregorian ? ((day - 100) * 400) / (365 * 400 + 100 - 4 + 1) : ((day - 100) * 4) / (365 * 4 + 1)); if (day >= 0) year++; int 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] = day; if (year <= 0) { fields[ERA] = BC; fields[YEAR] = 1 - year; } else { fields[ERA] = AD; fields[YEAR] = year; } int leapday = isLeapYear(year, gregorian) ? 1 : 0; if (day <= 31 + 28 + leapday) { fields[MONTH] = day / 32; // 31->JANUARY, 32->FEBRUARY fields[DAY_OF_MONTH] = day - 31 * fields[MONTH]; } else { // A few more magic formulas int scaledDay = (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]; int day = (int) (localTime / (24 * 60 * 60 * 1000L)); int millisInDay = (int) (localTime % (24 * 60 * 60 * 1000L)); if (millisInDay < 0) { millisInDay += (24 * 60 * 60 * 1000); day--; } calculateDay(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(++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 + 6) / 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 == 0) ? 12 : 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; } /** * Compares the given calender with this. * @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 necessary have the same fields). * @XXX Should we check if time zones, locale, cutover etc. are equal? */ public boolean equals(Object o) { if (!(o instanceof GregorianCalendar)) return false; GregorianCalendar cal = (GregorianCalendar) o; return (cal.getTimeInMillis() == getTimeInMillis()); }// /**// * Compares the given calender with this. // * @param o the object to that we should compare.// * @return true, if the given object is a calendar, and this calendar// * represents a smaller time than the calender o.// */// public boolean before(Object o) {// if (!(o instanceof GregorianCalendar))// return false;// GregorianCalendar cal = (GregorianCalendar) o;// return (cal.getTimeInMillis() < getTimeInMillis());// }// /**// * Compares the given calender with this. // * @param o the object to that we should compare.// * @return true, if the given object is a calendar, and this calendar// * represents a bigger time than the calender o.// */// public boolean after(Object o) {// if (!(o instanceof GregorianCalendar))// return false;// GregorianCalendar cal = (GregorianCalendar) o;// return (cal.getTimeInMillis() > getTimeInMillis());// } /** * Adds the specified amount of time to the given time field. The * amount may be negative to subtract the time. If the field overflows * it does what you expect: Jan, 25 + 10 Days is Feb, 4. * @param field the time field. One of the time field constants. * @param amount the amount of time. */ public void add(int field, int amount) { switch (field) { case YEAR: complete(); fields[YEAR] += amount; isTimeSet = false; break; case MONTH: complete(); int months = fields[MONTH] + amount; fields[YEAR] += months / 12; fields[MONTH] = months % 12; if (fields[MONTH] < 0) { fields[MONTH] += 12; fields[YEAR]--; } isTimeSet = false; int maxDay = getActualMaximum(DAY_OF_MONTH); if (fields[DAY_OF_MONTH] > maxDay) { fields[DAY_OF_MONTH] = maxDay; isTimeSet = false; } break; case DAY_OF_MONTH: case DAY_OF_YEAR: case DAY_OF_WEEK: if (!isTimeSet) computeTime(); time += amount * (24 * 60 * 60 * 1000L); areFieldsSet = false; break; case WEEK_OF_YEAR: case WEEK_OF_MONTH: case DAY_OF_WEEK_IN_MONTH: if (!isTimeSet)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -