📄 gregoriancalendar.java
字号:
return (cal.gregorianCutover == gregorianCutover && super.equals(o)); } /** * 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 one of the time field constants. * @param amount the amount of time to add. * @exception IllegalArgumentException if <code>field</code> is * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or invalid; or * if <code>amount</code> contains an out-of-range value and the calendar * is not in lenient mode. */ 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]--; } int maxDay = getActualMaximum(DAY_OF_MONTH); if (fields[DAY_OF_MONTH] > maxDay) fields[DAY_OF_MONTH] = maxDay; set(YEAR, fields[YEAR]); set(MONTH, fields[MONTH]); 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) computeTime(); time += amount * (7 * 24 * 60 * 60 * 1000L); areFieldsSet = false; break; case AM_PM: if (! isTimeSet) computeTime(); time += amount * (12 * 60 * 60 * 1000L); areFieldsSet = false; break; case HOUR: case HOUR_OF_DAY: if (! isTimeSet) computeTime(); time += amount * (60 * 60 * 1000L); areFieldsSet = false; break; case MINUTE: if (! isTimeSet) computeTime(); time += amount * (60 * 1000L); areFieldsSet = false; break; case SECOND: if (! isTimeSet) computeTime(); time += amount * (1000L); areFieldsSet = false; break; case MILLISECOND: if (! isTimeSet) computeTime(); time += amount; areFieldsSet = false; break; case ZONE_OFFSET: case DST_OFFSET:default: throw new IllegalArgumentException("Invalid or unknown field"); } } /** * Rolls the specified time field up or down. This means add one * to the specified field, but don't change the other fields. If * the maximum for this field is reached, start over with the * minimum value. * * <strong>Note:</strong> There may be situation, where the other * fields must be changed, e.g rolling the month on May, 31. * The date June, 31 is automatically converted to July, 1. * This requires lenient settings. * * @param field the time field. One of the time field constants. * @param up the direction, true for up, false for down. * @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 void roll(int field, boolean up) { roll(field, up ? 1 : -1); } /** * Checks that the fields are still within their legal bounds, * following use of the <code>roll()</code> method. * * @param field the field to check. * @param delta multipler for alterations to the <code>time</code>. * @see #roll(int, boolean) * @see #roll(int, int) */ private void cleanUpAfterRoll(int field, int delta) { switch (field) { case ERA: case YEAR: case MONTH: // check that day of month is still in correct range if (fields[DAY_OF_MONTH] > getActualMaximum(DAY_OF_MONTH)) fields[DAY_OF_MONTH] = getActualMaximum(DAY_OF_MONTH); isTimeSet = false; isSet[WEEK_OF_MONTH] = false; isSet[DAY_OF_WEEK] = false; isSet[DAY_OF_WEEK_IN_MONTH] = false; isSet[DAY_OF_YEAR] = false; isSet[WEEK_OF_YEAR] = false; break; case DAY_OF_MONTH: isSet[WEEK_OF_MONTH] = false; isSet[DAY_OF_WEEK] = false; isSet[DAY_OF_WEEK_IN_MONTH] = false; isSet[DAY_OF_YEAR] = false; isSet[WEEK_OF_YEAR] = false; time += delta * (24 * 60 * 60 * 1000L); break; case WEEK_OF_MONTH: isSet[DAY_OF_MONTH] = false; isSet[DAY_OF_WEEK_IN_MONTH] = false; isSet[DAY_OF_YEAR] = false; isSet[WEEK_OF_YEAR] = false; time += delta * (7 * 24 * 60 * 60 * 1000L); break; case DAY_OF_WEEK_IN_MONTH: isSet[DAY_OF_MONTH] = false; isSet[WEEK_OF_MONTH] = false; isSet[DAY_OF_YEAR] = false; isSet[WEEK_OF_YEAR] = false; time += delta * (7 * 24 * 60 * 60 * 1000L); break; case DAY_OF_YEAR: isSet[MONTH] = false; isSet[DAY_OF_MONTH] = false; isSet[WEEK_OF_MONTH] = false; isSet[DAY_OF_WEEK_IN_MONTH] = false; isSet[DAY_OF_WEEK] = false; isSet[WEEK_OF_YEAR] = false; time += delta * (24 * 60 * 60 * 1000L); break; case WEEK_OF_YEAR: isSet[MONTH] = false; isSet[DAY_OF_MONTH] = false; isSet[WEEK_OF_MONTH] = false; isSet[DAY_OF_WEEK_IN_MONTH] = false; isSet[DAY_OF_YEAR] = false; time += delta * (7 * 24 * 60 * 60 * 1000L); break; case AM_PM: isSet[HOUR_OF_DAY] = false; time += delta * (12 * 60 * 60 * 1000L); break; case HOUR: isSet[HOUR_OF_DAY] = false; time += delta * (60 * 60 * 1000L); break; case HOUR_OF_DAY: isSet[HOUR] = false; isSet[AM_PM] = false; time += delta * (60 * 60 * 1000L); break; case MINUTE: time += delta * (60 * 1000L); break; case SECOND: time += delta * (1000L); break; case MILLISECOND: time += delta; break; } } /** * Rolls the specified time field by the given amount. This means * add amount to the specified field, but don't change the other * fields. If the maximum for this field is reached, start over * with the minimum value and vice versa for negative amounts. * * <strong>Note:</strong> There may be situation, where the other * fields must be changed, e.g rolling the month on May, 31. * The date June, 31 is automatically corrected to June, 30. * * @param field the time field. One of the time field constants. * @param amount the amount by which we should roll. * @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 void roll(int field, int amount) { switch (field) { case DAY_OF_WEEK: // day of week is special: it rolls automatically add(field, amount); return; case ZONE_OFFSET: case DST_OFFSET: throw new IllegalArgumentException("Can't roll time zone"); } complete(); int min = getActualMinimum(field); int range = getActualMaximum(field) - min + 1; int oldval = fields[field]; int newval = (oldval - min + range + amount) % range + min; if (newval < min) newval += range; fields[field] = newval; cleanUpAfterRoll(field, newval - oldval); } /** * The minimum values for the calendar fields. */ private static final int[] minimums = { BC, 1, 0, 0, 1, 1, 1, SUNDAY, 1, AM, 1, 0, 0, 0, 0, -(12 * 60 * 60 * 1000), 0 }; /** * The maximum values for the calendar fields. */ private static final int[] maximums = { AD, 5000000, 11, 53, 5, 31, 366, SATURDAY, 5, PM, 12, 23, 59, 59, 999, +(12 * 60 * 60 * 1000), (12 * 60 * 60 * 1000) }; /** * Gets the smallest value that is allowed for the specified field. * * @param field one of the time field constants. * @return the smallest value for the specified field. */ public int getMinimum(int field) { return minimums[field]; } /** * Gets the biggest value that is allowed for the specified field. * * @param field one of the time field constants. * @return the biggest value. */ public int getMaximum(int field) { return maximums[field]; } /** * Gets the greatest minimum value that is allowed for the specified field. * This is the largest value returned by the <code>getActualMinimum(int)</code> * method. * * @param field the time field. One of the time field constants. * @return the greatest minimum value. * @see #getActualMinimum(int) */ public int getGreatestMinimum(int field) { if (field == WEEK_OF_YEAR) return 1; return minimums[field]; } /** * Gets the smallest maximum value that is allowed for the * specified field. This is the smallest value returned * by the <code>getActualMaximum(int)</code>. For example, * this is 28 for DAY_OF_MONTH (as all months have at least * 28 days). * * @param field the time field. One of the time field constants. * @return the least maximum value. * @see #getActualMaximum(int) * @since 1.2 */ public int getLeastMaximum(int field) { switch (field) { case WEEK_OF_YEAR: return 52; case DAY_OF_MONTH: return 28; case DAY_OF_YEAR: return 365; case DAY_OF_WEEK_IN_MONTH: case WEEK_OF_MONTH: return 4; default: return maximums[field]; } } /** * Gets the actual minimum value that is allowed for the specified field. * This value is dependent on the values of the other fields. Note that * this calls <code>complete()</code> if not enough fields are set. This * can have ugly side effects. The value given depends on the current * time used by this instance. * * @param field the time field. One of the time field constants. * @return the actual minimum value. * @since 1.2 */ public int getActualMinimum(int field) { if (field == WEEK_OF_YEAR) { int min = getMinimalDaysInFirstWeek(); if (min == 0) return 1; if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR]) complete(); int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; int weekday = getWeekDay(year, min); if ((7 + weekday - getFirstDayOfWeek()) % 7 >= min - 1) return 1; return 0; } return minimums[field]; } /** * Gets the actual maximum value that is allowed for the specified field. * This value is dependent on the values of the other fields. Note that * this calls <code>complete()</code> if not enough fields are set. This * can have ugly side effects. The value given depends on the current time * used by this instance; thus, leap years have a maximum day of month value of * 29, rather than 28. * * @param field the time field. One of the time field constants. * @return the actual maximum value. */ public int getActualMaximum(int field) { switch (field) { case WEEK_OF_YEAR: { if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR]) complete(); // This is wrong for the year that contains the gregorian change. // I.e it gives the weeks in the julian year or in the gregorian // year in that case. int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; int lastDay = isLeapYear(year) ? 366 : 365; int weekday = getWeekDay(year, lastDay); int week = (lastDay + 6 - (7 + weekday - getFirstDayOfWeek()) % 7) / 7; int minimalDays = getMinimalDaysInFirstWeek(); int firstWeekday = getWeekDay(year, minimalDays); /* * Is there a set of days at the beginning of the year, before the * first day of the week, equal to or greater than the minimum number * of days required in the first week? */ if (minimalDays - (7 + firstWeekday - getFirstDayOfWeek()) % 7 < 1) return week + 1; /* Add week 1: firstWeekday through to firstDayOfWeek */ } case DAY_OF_MONTH: { if (! areFieldsSet || ! isSet[MONTH]) complete(); int month = fields[MONTH]; // If you change this, you should also change // SimpleTimeZone.getDaysInMonth(); if (month == FEBRUARY) { if (! isSet[YEAR] || ! isSet[ERA]) complete(); int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; return isLeapYear(year) ? 29 : 28; } else if (month < AUGUST) return 31 - (month & 1); else return 30 + (month & 1); } case DAY_OF_YEAR: { if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR]) complete(); int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; return isLeapYear(year) ? 366 : 365; } case DAY_OF_WEEK_IN_MONTH: { // This is wrong for the month that contains the gregorian change. int daysInMonth = getActualMaximum(DAY_OF_MONTH); // That's black magic, I know return (daysInMonth - (fields[DAY_OF_MONTH] - 1) % 7 + 6) / 7; } case WEEK_OF_MONTH: { int daysInMonth = getActualMaximum(DAY_OF_MONTH); int weekday = (daysInMonth - fields[DAY_OF_MONTH] + fields[DAY_OF_WEEK] - SUNDAY) % 7 + SUNDAY; return (daysInMonth + 6 - (7 + weekday - getFirstDayOfWeek()) % 7) / 7; } default: return maximums[field]; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -