887 *
888 * <p><em>Add rule 1</em>. The value of <code>field</code>
889 * after the call minus the value of <code>field</code> before the
890 * call is <code>amount</code>, modulo any overflow that has occurred in
891 * <code>field</code>. Overflow occurs when a field value exceeds its
892 * range and, as a result, the next larger field is incremented or
893 * decremented and the field value is adjusted back into its range.</p>
894 *
895 * <p><em>Add rule 2</em>. If a smaller field is expected to be
896 * invariant, but it is impossible for it to be equal to its
897 * prior value because of changes in its minimum or maximum after
898 * <code>field</code> is changed, then its value is adjusted to be as close
899 * as possible to its expected value. A smaller field represents a
900 * smaller unit of time. <code>HOUR</code> is a smaller field than
901 * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
902 * that are not expected to be invariant. The calendar system
903 * determines what fields are expected to be invariant.</p>
904 *
905 * @param field the calendar field.
906 * @param amount the amount of date or time to be added to the field.
907 * @exception IllegalArgumentException if <code>field</code> is
908 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
909 * or if any calendar fields have out-of-range values in
910 * non-lenient mode.
911 */
912 @Override
913 public void add(int field, int amount) {
914 // If amount == 0, do nothing even the given field is out of
915 // range. This is tested by JCK.
916 if (amount == 0) {
917 return; // Do nothing!
918 }
919
920 if (field < 0 || field >= ZONE_OFFSET) {
921 throw new IllegalArgumentException();
922 }
923
924 // Sync the time and calendar fields.
925 complete();
926
927 if (field == YEAR) {
1084 // If the adjustment has changed the date, then take
1085 // the previous one.
1086 if (fd2 != fd) {
1087 setTimeInMillis(time - zoneOffset);
1088 }
1089 }
1090 }
1091 }
1092
1093 /**
1094 * Adds or subtracts (up/down) a single unit of time on the given time
1095 * field without changing larger fields.
1096 * <p>
1097 * <em>Example</em>: Consider a <code>GregorianCalendar</code>
1098 * originally set to December 31, 1999. Calling {@link #roll(int,boolean) roll(Calendar.MONTH, true)}
1099 * sets the calendar to January 31, 1999. The <code>YEAR</code> field is unchanged
1100 * because it is a larger field than <code>MONTH</code>.</p>
1101 *
1102 * @param up indicates if the value of the specified calendar field is to be
1103 * rolled up or rolled down. Use <code>true</code> if rolling up, <code>false</code> otherwise.
1104 * @exception IllegalArgumentException if <code>field</code> is
1105 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
1106 * or if any calendar fields have out-of-range values in
1107 * non-lenient mode.
1108 * @see #add(int,int)
1109 * @see #set(int,int)
1110 */
1111 @Override
1112 public void roll(int field, boolean up) {
1113 roll(field, up ? +1 : -1);
1114 }
1115
1116 /**
1117 * Adds a signed amount to the specified calendar field without changing larger fields.
1118 * A negative roll amount means to subtract from field without changing
1119 * larger fields. If the specified amount is 0, this method performs nothing.
1120 *
1121 * <p>This method calls {@link #complete()} before adding the
1122 * amount so that all the calendar fields are normalized. If there
1123 * is any calendar field having an out-of-range value in non-lenient mode, then an
1124 * <code>IllegalArgumentException</code> is thrown.
1131 * be 31 in the month April. <code>DAY_OF_MONTH</code> is set to the closest possible
1132 * value, 30. The <code>YEAR</code> field maintains the value of 1999 because it
1133 * is a larger field than <code>MONTH</code>.
1134 * <p>
1135 * <em>Example</em>: Consider a <code>GregorianCalendar</code>
1136 * originally set to Sunday June 6, 1999. Calling
1137 * <code>roll(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
1138 * Tuesday June 1, 1999, whereas calling
1139 * <code>add(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
1140 * Sunday May 30, 1999. This is because the roll rule imposes an
1141 * additional constraint: The <code>MONTH</code> must not change when the
1142 * <code>WEEK_OF_MONTH</code> is rolled. Taken together with add rule 1,
1143 * the resultant date must be between Tuesday June 1 and Saturday June
1144 * 5. According to add rule 2, the <code>DAY_OF_WEEK</code>, an invariant
1145 * when changing the <code>WEEK_OF_MONTH</code>, is set to Tuesday, the
1146 * closest possible value to Sunday (where Sunday is the first day of the
1147 * week).</p>
1148 *
1149 * @param field the calendar field.
1150 * @param amount the signed amount to add to <code>field</code>.
1151 * @exception IllegalArgumentException if <code>field</code> is
1152 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
1153 * or if any calendar fields have out-of-range values in
1154 * non-lenient mode.
1155 * @see #roll(int,boolean)
1156 * @see #add(int,int)
1157 * @see #set(int,int)
1158 * @since 1.2
1159 */
1160 @Override
1161 public void roll(int field, int amount) {
1162 // If amount == 0, do nothing even the given field is out of
1163 // range. This is tested by JCK.
1164 if (amount == 0) {
1165 return;
1166 }
1167
1168 if (field < 0 || field >= ZONE_OFFSET) {
1169 throw new IllegalArgumentException();
1170 }
1171
2166 * the ISO 8601 standard, and that the {@code weekOfYear}
2167 * numbering is compatible with the standard when {@code
2168 * getFirstDayOfWeek()} is {@code MONDAY} and {@code
2169 * getMinimalDaysInFirstWeek()} is 4.
2170 *
2171 * <p>Unlike the {@code set} method, all of the calendar fields
2172 * and the instant of time value are calculated upon return.
2173 *
2174 * <p>If {@code weekOfYear} is out of the valid week-of-year
2175 * range in {@code weekYear}, the {@code weekYear}
2176 * and {@code weekOfYear} values are adjusted in lenient
2177 * mode, or an {@code IllegalArgumentException} is thrown in
2178 * non-lenient mode.
2179 *
2180 * @param weekYear the week year
2181 * @param weekOfYear the week number based on {@code weekYear}
2182 * @param dayOfWeek the day of week value: one of the constants
2183 * for the {@link #DAY_OF_WEEK DAY_OF_WEEK} field:
2184 * {@link Calendar#SUNDAY SUNDAY}, ...,
2185 * {@link Calendar#SATURDAY SATURDAY}.
2186 * @exception IllegalArgumentException
2187 * if any of the given date specifiers is invalid,
2188 * or if any of the calendar fields are inconsistent
2189 * with the given date specifiers in non-lenient mode
2190 * @see GregorianCalendar#isWeekDateSupported()
2191 * @see Calendar#getFirstDayOfWeek()
2192 * @see Calendar#getMinimalDaysInFirstWeek()
2193 * @since 1.7
2194 */
2195 @Override
2196 public void setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) {
2197 if (dayOfWeek < SUNDAY || dayOfWeek > SATURDAY) {
2198 throw new IllegalArgumentException("invalid dayOfWeek: " + dayOfWeek);
2199 }
2200
2201 // To avoid changing the time of day fields by date
2202 // calculations, use a clone with the GMT time zone.
2203 GregorianCalendar gc = (GregorianCalendar) clone();
2204 gc.setLenient(true);
2205 int era = gc.get(ERA);
2206 gc.clear();
2609 // We can always use `gcal' since Julian and Gregorian are the
2610 // same thing for this calculation.
2611 long fixedDay1st = Gregorian.getDayOfWeekDateOnOrBefore(fixedDay1 + 6,
2612 getFirstDayOfWeek());
2613 int ndays = (int)(fixedDay1st - fixedDay1);
2614 assert ndays <= 7;
2615 if (ndays >= getMinimalDaysInFirstWeek()) {
2616 fixedDay1st -= 7;
2617 }
2618 int normalizedDayOfPeriod = (int)(fixedDate - fixedDay1st);
2619 if (normalizedDayOfPeriod >= 0) {
2620 return normalizedDayOfPeriod / 7 + 1;
2621 }
2622 return CalendarUtils.floorDivide(normalizedDayOfPeriod, 7) + 1;
2623 }
2624
2625 /**
2626 * Converts calendar field values to the time value (millisecond
2627 * offset from the <a href="Calendar.html#Epoch">Epoch</a>).
2628 *
2629 * @exception IllegalArgumentException if any calendar fields are invalid.
2630 */
2631 @Override
2632 protected void computeTime() {
2633 // In non-lenient mode, perform brief checking of calendar
2634 // fields which have been set externally. Through this
2635 // checking, the field values are stored in originalFields[]
2636 // to see if any of them are normalized later.
2637 if (!isLenient()) {
2638 if (originalFields == null) {
2639 originalFields = new int[FIELD_COUNT];
2640 }
2641 for (int field = 0; field < FIELD_COUNT; field++) {
2642 int value = internalGet(field);
2643 if (isExternallySet(field)) {
2644 // Quick validation for any out of range values
2645 if (value < getMinimum(field) || value > getMaximum(field)) {
2646 throw new IllegalArgumentException(getFieldName(field));
2647 }
2648 }
2649 originalFields[field] = value;
3262
3263 /**
3264 * Obtains an instance of {@code GregorianCalendar} with the default locale
3265 * from a {@code ZonedDateTime} object.
3266 * <p>
3267 * Since {@code ZonedDateTime} does not support a Julian-Gregorian cutover
3268 * date and uses ISO calendar system, the return GregorianCalendar is a pure
3269 * Gregorian calendar and uses ISO 8601 standard for week definitions,
3270 * which has {@code MONDAY} as the {@link Calendar#getFirstDayOfWeek()
3271 * FirstDayOfWeek} and {@code 4} as the value of the
3272 * {@link Calendar#getMinimalDaysInFirstWeek() MinimalDaysInFirstWeek}.
3273 * <p>
3274 * {@code ZoneDateTime} can store points on the time-line further in the
3275 * future and further in the past than {@code GregorianCalendar}. In this
3276 * scenario, this method will throw an {@code IllegalArgumentException}
3277 * exception.
3278 *
3279 * @param zdt the zoned date-time object to convert
3280 * @return the gregorian calendar representing the same point on the
3281 * time-line as the zoned date-time provided
3282 * @exception NullPointerException if {@code zdt} is null
3283 * @exception IllegalArgumentException if the zoned date-time is too
3284 * large to represent as a {@code GregorianCalendar}
3285 * @since 1.8
3286 */
3287 public static GregorianCalendar from(ZonedDateTime zdt) {
3288 GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone(zdt.getZone()));
3289 cal.setGregorianChange(new Date(Long.MIN_VALUE));
3290 cal.setFirstDayOfWeek(MONDAY);
3291 cal.setMinimalDaysInFirstWeek(4);
3292 try {
3293 cal.setTimeInMillis(Math.addExact(Math.multiplyExact(zdt.toEpochSecond(), 1000),
3294 zdt.get(ChronoField.MILLI_OF_SECOND)));
3295 } catch (ArithmeticException ex) {
3296 throw new IllegalArgumentException(ex);
3297 }
3298 return cal;
3299 }
3300 }
|
887 *
888 * <p><em>Add rule 1</em>. The value of <code>field</code>
889 * after the call minus the value of <code>field</code> before the
890 * call is <code>amount</code>, modulo any overflow that has occurred in
891 * <code>field</code>. Overflow occurs when a field value exceeds its
892 * range and, as a result, the next larger field is incremented or
893 * decremented and the field value is adjusted back into its range.</p>
894 *
895 * <p><em>Add rule 2</em>. If a smaller field is expected to be
896 * invariant, but it is impossible for it to be equal to its
897 * prior value because of changes in its minimum or maximum after
898 * <code>field</code> is changed, then its value is adjusted to be as close
899 * as possible to its expected value. A smaller field represents a
900 * smaller unit of time. <code>HOUR</code> is a smaller field than
901 * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
902 * that are not expected to be invariant. The calendar system
903 * determines what fields are expected to be invariant.</p>
904 *
905 * @param field the calendar field.
906 * @param amount the amount of date or time to be added to the field.
907 * @throws IllegalArgumentException if <code>field</code> is
908 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
909 * or if any calendar fields have out-of-range values in
910 * non-lenient mode.
911 */
912 @Override
913 public void add(int field, int amount) {
914 // If amount == 0, do nothing even the given field is out of
915 // range. This is tested by JCK.
916 if (amount == 0) {
917 return; // Do nothing!
918 }
919
920 if (field < 0 || field >= ZONE_OFFSET) {
921 throw new IllegalArgumentException();
922 }
923
924 // Sync the time and calendar fields.
925 complete();
926
927 if (field == YEAR) {
1084 // If the adjustment has changed the date, then take
1085 // the previous one.
1086 if (fd2 != fd) {
1087 setTimeInMillis(time - zoneOffset);
1088 }
1089 }
1090 }
1091 }
1092
1093 /**
1094 * Adds or subtracts (up/down) a single unit of time on the given time
1095 * field without changing larger fields.
1096 * <p>
1097 * <em>Example</em>: Consider a <code>GregorianCalendar</code>
1098 * originally set to December 31, 1999. Calling {@link #roll(int,boolean) roll(Calendar.MONTH, true)}
1099 * sets the calendar to January 31, 1999. The <code>YEAR</code> field is unchanged
1100 * because it is a larger field than <code>MONTH</code>.</p>
1101 *
1102 * @param up indicates if the value of the specified calendar field is to be
1103 * rolled up or rolled down. Use <code>true</code> if rolling up, <code>false</code> otherwise.
1104 * @throws IllegalArgumentException if <code>field</code> is
1105 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
1106 * or if any calendar fields have out-of-range values in
1107 * non-lenient mode.
1108 * @see #add(int,int)
1109 * @see #set(int,int)
1110 */
1111 @Override
1112 public void roll(int field, boolean up) {
1113 roll(field, up ? +1 : -1);
1114 }
1115
1116 /**
1117 * Adds a signed amount to the specified calendar field without changing larger fields.
1118 * A negative roll amount means to subtract from field without changing
1119 * larger fields. If the specified amount is 0, this method performs nothing.
1120 *
1121 * <p>This method calls {@link #complete()} before adding the
1122 * amount so that all the calendar fields are normalized. If there
1123 * is any calendar field having an out-of-range value in non-lenient mode, then an
1124 * <code>IllegalArgumentException</code> is thrown.
1131 * be 31 in the month April. <code>DAY_OF_MONTH</code> is set to the closest possible
1132 * value, 30. The <code>YEAR</code> field maintains the value of 1999 because it
1133 * is a larger field than <code>MONTH</code>.
1134 * <p>
1135 * <em>Example</em>: Consider a <code>GregorianCalendar</code>
1136 * originally set to Sunday June 6, 1999. Calling
1137 * <code>roll(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
1138 * Tuesday June 1, 1999, whereas calling
1139 * <code>add(Calendar.WEEK_OF_MONTH, -1)</code> sets the calendar to
1140 * Sunday May 30, 1999. This is because the roll rule imposes an
1141 * additional constraint: The <code>MONTH</code> must not change when the
1142 * <code>WEEK_OF_MONTH</code> is rolled. Taken together with add rule 1,
1143 * the resultant date must be between Tuesday June 1 and Saturday June
1144 * 5. According to add rule 2, the <code>DAY_OF_WEEK</code>, an invariant
1145 * when changing the <code>WEEK_OF_MONTH</code>, is set to Tuesday, the
1146 * closest possible value to Sunday (where Sunday is the first day of the
1147 * week).</p>
1148 *
1149 * @param field the calendar field.
1150 * @param amount the signed amount to add to <code>field</code>.
1151 * @throws IllegalArgumentException if <code>field</code> is
1152 * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
1153 * or if any calendar fields have out-of-range values in
1154 * non-lenient mode.
1155 * @see #roll(int,boolean)
1156 * @see #add(int,int)
1157 * @see #set(int,int)
1158 * @since 1.2
1159 */
1160 @Override
1161 public void roll(int field, int amount) {
1162 // If amount == 0, do nothing even the given field is out of
1163 // range. This is tested by JCK.
1164 if (amount == 0) {
1165 return;
1166 }
1167
1168 if (field < 0 || field >= ZONE_OFFSET) {
1169 throw new IllegalArgumentException();
1170 }
1171
2166 * the ISO 8601 standard, and that the {@code weekOfYear}
2167 * numbering is compatible with the standard when {@code
2168 * getFirstDayOfWeek()} is {@code MONDAY} and {@code
2169 * getMinimalDaysInFirstWeek()} is 4.
2170 *
2171 * <p>Unlike the {@code set} method, all of the calendar fields
2172 * and the instant of time value are calculated upon return.
2173 *
2174 * <p>If {@code weekOfYear} is out of the valid week-of-year
2175 * range in {@code weekYear}, the {@code weekYear}
2176 * and {@code weekOfYear} values are adjusted in lenient
2177 * mode, or an {@code IllegalArgumentException} is thrown in
2178 * non-lenient mode.
2179 *
2180 * @param weekYear the week year
2181 * @param weekOfYear the week number based on {@code weekYear}
2182 * @param dayOfWeek the day of week value: one of the constants
2183 * for the {@link #DAY_OF_WEEK DAY_OF_WEEK} field:
2184 * {@link Calendar#SUNDAY SUNDAY}, ...,
2185 * {@link Calendar#SATURDAY SATURDAY}.
2186 * @throws IllegalArgumentException
2187 * if any of the given date specifiers is invalid,
2188 * or if any of the calendar fields are inconsistent
2189 * with the given date specifiers in non-lenient mode
2190 * @see GregorianCalendar#isWeekDateSupported()
2191 * @see Calendar#getFirstDayOfWeek()
2192 * @see Calendar#getMinimalDaysInFirstWeek()
2193 * @since 1.7
2194 */
2195 @Override
2196 public void setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) {
2197 if (dayOfWeek < SUNDAY || dayOfWeek > SATURDAY) {
2198 throw new IllegalArgumentException("invalid dayOfWeek: " + dayOfWeek);
2199 }
2200
2201 // To avoid changing the time of day fields by date
2202 // calculations, use a clone with the GMT time zone.
2203 GregorianCalendar gc = (GregorianCalendar) clone();
2204 gc.setLenient(true);
2205 int era = gc.get(ERA);
2206 gc.clear();
2609 // We can always use `gcal' since Julian and Gregorian are the
2610 // same thing for this calculation.
2611 long fixedDay1st = Gregorian.getDayOfWeekDateOnOrBefore(fixedDay1 + 6,
2612 getFirstDayOfWeek());
2613 int ndays = (int)(fixedDay1st - fixedDay1);
2614 assert ndays <= 7;
2615 if (ndays >= getMinimalDaysInFirstWeek()) {
2616 fixedDay1st -= 7;
2617 }
2618 int normalizedDayOfPeriod = (int)(fixedDate - fixedDay1st);
2619 if (normalizedDayOfPeriod >= 0) {
2620 return normalizedDayOfPeriod / 7 + 1;
2621 }
2622 return CalendarUtils.floorDivide(normalizedDayOfPeriod, 7) + 1;
2623 }
2624
2625 /**
2626 * Converts calendar field values to the time value (millisecond
2627 * offset from the <a href="Calendar.html#Epoch">Epoch</a>).
2628 *
2629 * @throws IllegalArgumentException if any calendar fields are invalid.
2630 */
2631 @Override
2632 protected void computeTime() {
2633 // In non-lenient mode, perform brief checking of calendar
2634 // fields which have been set externally. Through this
2635 // checking, the field values are stored in originalFields[]
2636 // to see if any of them are normalized later.
2637 if (!isLenient()) {
2638 if (originalFields == null) {
2639 originalFields = new int[FIELD_COUNT];
2640 }
2641 for (int field = 0; field < FIELD_COUNT; field++) {
2642 int value = internalGet(field);
2643 if (isExternallySet(field)) {
2644 // Quick validation for any out of range values
2645 if (value < getMinimum(field) || value > getMaximum(field)) {
2646 throw new IllegalArgumentException(getFieldName(field));
2647 }
2648 }
2649 originalFields[field] = value;
3262
3263 /**
3264 * Obtains an instance of {@code GregorianCalendar} with the default locale
3265 * from a {@code ZonedDateTime} object.
3266 * <p>
3267 * Since {@code ZonedDateTime} does not support a Julian-Gregorian cutover
3268 * date and uses ISO calendar system, the return GregorianCalendar is a pure
3269 * Gregorian calendar and uses ISO 8601 standard for week definitions,
3270 * which has {@code MONDAY} as the {@link Calendar#getFirstDayOfWeek()
3271 * FirstDayOfWeek} and {@code 4} as the value of the
3272 * {@link Calendar#getMinimalDaysInFirstWeek() MinimalDaysInFirstWeek}.
3273 * <p>
3274 * {@code ZoneDateTime} can store points on the time-line further in the
3275 * future and further in the past than {@code GregorianCalendar}. In this
3276 * scenario, this method will throw an {@code IllegalArgumentException}
3277 * exception.
3278 *
3279 * @param zdt the zoned date-time object to convert
3280 * @return the gregorian calendar representing the same point on the
3281 * time-line as the zoned date-time provided
3282 * @throws NullPointerException if {@code zdt} is null
3283 * @throws IllegalArgumentException if the zoned date-time is too
3284 * large to represent as a {@code GregorianCalendar}
3285 * @since 1.8
3286 */
3287 public static GregorianCalendar from(ZonedDateTime zdt) {
3288 GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone(zdt.getZone()));
3289 cal.setGregorianChange(new Date(Long.MIN_VALUE));
3290 cal.setFirstDayOfWeek(MONDAY);
3291 cal.setMinimalDaysInFirstWeek(4);
3292 try {
3293 cal.setTimeInMillis(Math.addExact(Math.multiplyExact(zdt.toEpochSecond(), 1000),
3294 zdt.get(ChronoField.MILLI_OF_SECOND)));
3295 } catch (ArithmeticException ex) {
3296 throw new IllegalArgumentException(ex);
3297 }
3298 return cal;
3299 }
3300 }
|