1 /* 2 * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * This file is available under and governed by the GNU General Public 28 * License version 2 only, as published by the Free Software Foundation. 29 * However, the following notice accompanied the original version of this 30 * file: 31 * 32 * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos 33 * 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions are met: 38 * 39 * * Redistributions of source code must retain the above copyright notice, 40 * this list of conditions and the following disclaimer. 41 * 42 * * Redistributions in binary form must reproduce the above copyright notice, 43 * this list of conditions and the following disclaimer in the documentation 44 * and/or other materials provided with the distribution. 45 * 46 * * Neither the name of JSR-310 nor the names of its contributors 47 * may be used to endorse or promote products derived from this software 48 * without specific prior written permission. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 54 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 55 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 56 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 57 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 58 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 59 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 60 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 */ 62 package java.time; 63 64 import static java.time.temporal.ChronoField.ERA; 65 import static java.time.temporal.ChronoField.YEAR; 66 import static java.time.temporal.ChronoField.YEAR_OF_ERA; 67 import static java.time.temporal.ChronoUnit.CENTURIES; 68 import static java.time.temporal.ChronoUnit.DECADES; 69 import static java.time.temporal.ChronoUnit.ERAS; 70 import static java.time.temporal.ChronoUnit.MILLENNIA; 71 import static java.time.temporal.ChronoUnit.YEARS; 72 73 import java.io.DataInput; 74 import java.io.DataOutput; 75 import java.io.IOException; 76 import java.io.InvalidObjectException; 77 import java.io.ObjectInputStream; 78 import java.io.Serializable; 79 import java.time.chrono.Chronology; 80 import java.time.chrono.IsoChronology; 81 import java.time.format.DateTimeFormatter; 82 import java.time.format.DateTimeFormatterBuilder; 83 import java.time.format.DateTimeParseException; 84 import java.time.format.SignStyle; 85 import java.time.temporal.ChronoField; 86 import java.time.temporal.ChronoUnit; 87 import java.time.temporal.Temporal; 88 import java.time.temporal.TemporalAccessor; 89 import java.time.temporal.TemporalAdjuster; 90 import java.time.temporal.TemporalAmount; 91 import java.time.temporal.TemporalField; 92 import java.time.temporal.TemporalQueries; 93 import java.time.temporal.TemporalQuery; 94 import java.time.temporal.TemporalUnit; 95 import java.time.temporal.UnsupportedTemporalTypeException; 96 import java.time.temporal.ValueRange; 97 import java.util.Objects; 98 99 /** 100 * A year in the ISO-8601 calendar system, such as {@code 2007}. 101 * <p> 102 * {@code Year} is an immutable date-time object that represents a year. 103 * Any field that can be derived from a year can be obtained. 104 * <p> 105 * <b>Note that years in the ISO chronology only align with years in the 106 * Gregorian-Julian system for modern years. Parts of Russia did not switch to the 107 * modern Gregorian/ISO rules until 1920. 108 * As such, historical years must be treated with caution.</b> 109 * <p> 110 * This class does not store or represent a month, day, time or time-zone. 111 * For example, the value "2007" can be stored in a {@code Year}. 112 * <p> 113 * Years represented by this class follow the ISO-8601 standard and use 114 * the proleptic numbering system. Year 1 is preceded by year 0, then by year -1. 115 * <p> 116 * The ISO-8601 calendar system is the modern civil calendar system used today 117 * in most of the world. It is equivalent to the proleptic Gregorian calendar 118 * system, in which today's rules for leap years are applied for all time. 119 * For most applications written today, the ISO-8601 rules are entirely suitable. 120 * However, any application that makes use of historical dates, and requires them 121 * to be accurate will find the ISO-8601 approach unsuitable. 122 * 123 * <p> 124 * This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a> 125 * class; use of identity-sensitive operations (including reference equality 126 * ({@code ==}), identity hash code, or synchronization) on instances of 127 * {@code Year} may have unpredictable results and should be avoided. 128 * The {@code equals} method should be used for comparisons. 129 * 130 * @implSpec 131 * This class is immutable and thread-safe. 132 * 133 * @since 1.8 134 */ 135 public final class Year 136 implements Temporal, TemporalAdjuster, Comparable<Year>, Serializable { 137 138 /** 139 * The minimum supported year, '-999,999,999'. 140 */ 141 public static final int MIN_VALUE = -999_999_999; 142 /** 143 * The maximum supported year, '+999,999,999'. 144 */ 145 public static final int MAX_VALUE = 999_999_999; 146 147 /** 148 * Serialization version. 149 */ 150 @java.io.Serial 151 private static final long serialVersionUID = -23038383694477807L; 152 /** 153 * Parser. 154 */ 155 private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder() 156 .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD) 157 .toFormatter(); 158 159 /** 160 * The year being represented. 161 */ 162 private final int year; 163 164 //----------------------------------------------------------------------- 165 /** 166 * Obtains the current year from the system clock in the default time-zone. 167 * <p> 168 * This will query the {@link Clock#systemDefaultZone() system clock} in the default 169 * time-zone to obtain the current year. 170 * <p> 171 * Using this method will prevent the ability to use an alternate clock for testing 172 * because the clock is hard-coded. 173 * 174 * @return the current year using the system clock and default time-zone, not null 175 */ now()176 public static Year now() { 177 return now(Clock.systemDefaultZone()); 178 } 179 180 /** 181 * Obtains the current year from the system clock in the specified time-zone. 182 * <p> 183 * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current year. 184 * Specifying the time-zone avoids dependence on the default time-zone. 185 * <p> 186 * Using this method will prevent the ability to use an alternate clock for testing 187 * because the clock is hard-coded. 188 * 189 * @param zone the zone ID to use, not null 190 * @return the current year using the system clock, not null 191 */ now(ZoneId zone)192 public static Year now(ZoneId zone) { 193 return now(Clock.system(zone)); 194 } 195 196 /** 197 * Obtains the current year from the specified clock. 198 * <p> 199 * This will query the specified clock to obtain the current year. 200 * Using this method allows the use of an alternate clock for testing. 201 * The alternate clock may be introduced using {@link Clock dependency injection}. 202 * 203 * @param clock the clock to use, not null 204 * @return the current year, not null 205 */ now(Clock clock)206 public static Year now(Clock clock) { 207 final LocalDate now = LocalDate.now(clock); // called once 208 return Year.of(now.getYear()); 209 } 210 211 //----------------------------------------------------------------------- 212 /** 213 * Obtains an instance of {@code Year}. 214 * <p> 215 * This method accepts a year value from the proleptic ISO calendar system. 216 * <p> 217 * The year 2AD/CE is represented by 2.<br> 218 * The year 1AD/CE is represented by 1.<br> 219 * The year 1BC/BCE is represented by 0.<br> 220 * The year 2BC/BCE is represented by -1.<br> 221 * 222 * @param isoYear the ISO proleptic year to represent, from {@code MIN_VALUE} to {@code MAX_VALUE} 223 * @return the year, not null 224 * @throws DateTimeException if the field is invalid 225 */ of(int isoYear)226 public static Year of(int isoYear) { 227 YEAR.checkValidValue(isoYear); 228 return new Year(isoYear); 229 } 230 231 //----------------------------------------------------------------------- 232 /** 233 * Obtains an instance of {@code Year} from a temporal object. 234 * <p> 235 * This obtains a year based on the specified temporal. 236 * A {@code TemporalAccessor} represents an arbitrary set of date and time information, 237 * which this factory converts to an instance of {@code Year}. 238 * <p> 239 * The conversion extracts the {@link ChronoField#YEAR year} field. 240 * The extraction is only permitted if the temporal object has an ISO 241 * chronology, or can be converted to a {@code LocalDate}. 242 * <p> 243 * This method matches the signature of the functional interface {@link TemporalQuery} 244 * allowing it to be used as a query via method reference, {@code Year::from}. 245 * 246 * @param temporal the temporal object to convert, not null 247 * @return the year, not null 248 * @throws DateTimeException if unable to convert to a {@code Year} 249 */ from(TemporalAccessor temporal)250 public static Year from(TemporalAccessor temporal) { 251 if (temporal instanceof Year) { 252 return (Year) temporal; 253 } 254 Objects.requireNonNull(temporal, "temporal"); 255 try { 256 if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) { 257 temporal = LocalDate.from(temporal); 258 } 259 return of(temporal.get(YEAR)); 260 } catch (DateTimeException ex) { 261 throw new DateTimeException("Unable to obtain Year from TemporalAccessor: " + 262 temporal + " of type " + temporal.getClass().getName(), ex); 263 } 264 } 265 266 //----------------------------------------------------------------------- 267 /** 268 * Obtains an instance of {@code Year} from a text string such as {@code 2007}. 269 * <p> 270 * The string must represent a valid year. 271 * Years outside the range 0000 to 9999 must be prefixed by the plus or minus symbol. 272 * 273 * @param text the text to parse such as "2007", not null 274 * @return the parsed year, not null 275 * @throws DateTimeParseException if the text cannot be parsed 276 */ parse(CharSequence text)277 public static Year parse(CharSequence text) { 278 return parse(text, PARSER); 279 } 280 281 /** 282 * Obtains an instance of {@code Year} from a text string using a specific formatter. 283 * <p> 284 * The text is parsed using the formatter, returning a year. 285 * 286 * @param text the text to parse, not null 287 * @param formatter the formatter to use, not null 288 * @return the parsed year, not null 289 * @throws DateTimeParseException if the text cannot be parsed 290 */ parse(CharSequence text, DateTimeFormatter formatter)291 public static Year parse(CharSequence text, DateTimeFormatter formatter) { 292 Objects.requireNonNull(formatter, "formatter"); 293 return formatter.parse(text, Year::from); 294 } 295 296 //------------------------------------------------------------------------- 297 /** 298 * Checks if the year is a leap year, according to the ISO proleptic 299 * calendar system rules. 300 * <p> 301 * This method applies the current rules for leap years across the whole time-line. 302 * In general, a year is a leap year if it is divisible by four without 303 * remainder. However, years divisible by 100, are not leap years, with 304 * the exception of years divisible by 400 which are. 305 * <p> 306 * For example, 1904 is a leap year it is divisible by 4. 307 * 1900 was not a leap year as it is divisible by 100, however 2000 was a 308 * leap year as it is divisible by 400. 309 * <p> 310 * The calculation is proleptic - applying the same rules into the far future and far past. 311 * This is historically inaccurate, but is correct for the ISO-8601 standard. 312 * 313 * @param year the year to check 314 * @return true if the year is leap, false otherwise 315 */ isLeap(long year)316 public static boolean isLeap(long year) { 317 return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0); 318 } 319 320 //----------------------------------------------------------------------- 321 /** 322 * Constructor. 323 * 324 * @param year the year to represent 325 */ Year(int year)326 private Year(int year) { 327 this.year = year; 328 } 329 330 //----------------------------------------------------------------------- 331 /** 332 * Gets the year value. 333 * <p> 334 * The year returned by this method is proleptic as per {@code get(YEAR)}. 335 * 336 * @return the year, {@code MIN_VALUE} to {@code MAX_VALUE} 337 */ getValue()338 public int getValue() { 339 return year; 340 } 341 342 //----------------------------------------------------------------------- 343 /** 344 * Checks if the specified field is supported. 345 * <p> 346 * This checks if this year can be queried for the specified field. 347 * If false, then calling the {@link #range(TemporalField) range}, 348 * {@link #get(TemporalField) get} and {@link #with(TemporalField, long)} 349 * methods will throw an exception. 350 * <p> 351 * If the field is a {@link ChronoField} then the query is implemented here. 352 * The supported fields are: 353 * <ul> 354 * <li>{@code YEAR_OF_ERA} 355 * <li>{@code YEAR} 356 * <li>{@code ERA} 357 * </ul> 358 * All other {@code ChronoField} instances will return false. 359 * <p> 360 * If the field is not a {@code ChronoField}, then the result of this method 361 * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)} 362 * passing {@code this} as the argument. 363 * Whether the field is supported is determined by the field. 364 * 365 * @param field the field to check, null returns false 366 * @return true if the field is supported on this year, false if not 367 */ 368 @Override isSupported(TemporalField field)369 public boolean isSupported(TemporalField field) { 370 if (field instanceof ChronoField) { 371 return field == YEAR || field == YEAR_OF_ERA || field == ERA; 372 } 373 return field != null && field.isSupportedBy(this); 374 } 375 376 /** 377 * Checks if the specified unit is supported. 378 * <p> 379 * This checks if the specified unit can be added to, or subtracted from, this year. 380 * If false, then calling the {@link #plus(long, TemporalUnit)} and 381 * {@link #minus(long, TemporalUnit) minus} methods will throw an exception. 382 * <p> 383 * If the unit is a {@link ChronoUnit} then the query is implemented here. 384 * The supported units are: 385 * <ul> 386 * <li>{@code YEARS} 387 * <li>{@code DECADES} 388 * <li>{@code CENTURIES} 389 * <li>{@code MILLENNIA} 390 * <li>{@code ERAS} 391 * </ul> 392 * All other {@code ChronoUnit} instances will return false. 393 * <p> 394 * If the unit is not a {@code ChronoUnit}, then the result of this method 395 * is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)} 396 * passing {@code this} as the argument. 397 * Whether the unit is supported is determined by the unit. 398 * 399 * @param unit the unit to check, null returns false 400 * @return true if the unit can be added/subtracted, false if not 401 */ 402 @Override isSupported(TemporalUnit unit)403 public boolean isSupported(TemporalUnit unit) { 404 if (unit instanceof ChronoUnit) { 405 return unit == YEARS || unit == DECADES || unit == CENTURIES || unit == MILLENNIA || unit == ERAS; 406 } 407 return unit != null && unit.isSupportedBy(this); 408 } 409 410 //----------------------------------------------------------------------- 411 /** 412 * Gets the range of valid values for the specified field. 413 * <p> 414 * The range object expresses the minimum and maximum valid values for a field. 415 * This year is used to enhance the accuracy of the returned range. 416 * If it is not possible to return the range, because the field is not supported 417 * or for some other reason, an exception is thrown. 418 * <p> 419 * If the field is a {@link ChronoField} then the query is implemented here. 420 * The {@link #isSupported(TemporalField) supported fields} will return 421 * appropriate range instances. 422 * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. 423 * <p> 424 * If the field is not a {@code ChronoField}, then the result of this method 425 * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)} 426 * passing {@code this} as the argument. 427 * Whether the range can be obtained is determined by the field. 428 * 429 * @param field the field to query the range for, not null 430 * @return the range of valid values for the field, not null 431 * @throws DateTimeException if the range for the field cannot be obtained 432 * @throws UnsupportedTemporalTypeException if the field is not supported 433 */ 434 @Override range(TemporalField field)435 public ValueRange range(TemporalField field) { 436 if (field == YEAR_OF_ERA) { 437 return (year <= 0 ? ValueRange.of(1, MAX_VALUE + 1) : ValueRange.of(1, MAX_VALUE)); 438 } 439 return Temporal.super.range(field); 440 } 441 442 /** 443 * Gets the value of the specified field from this year as an {@code int}. 444 * <p> 445 * This queries this year for the value of the specified field. 446 * The returned value will always be within the valid range of values for the field. 447 * If it is not possible to return the value, because the field is not supported 448 * or for some other reason, an exception is thrown. 449 * <p> 450 * If the field is a {@link ChronoField} then the query is implemented here. 451 * The {@link #isSupported(TemporalField) supported fields} will return valid 452 * values based on this year. 453 * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. 454 * <p> 455 * If the field is not a {@code ChronoField}, then the result of this method 456 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} 457 * passing {@code this} as the argument. Whether the value can be obtained, 458 * and what the value represents, is determined by the field. 459 * 460 * @param field the field to get, not null 461 * @return the value for the field 462 * @throws DateTimeException if a value for the field cannot be obtained or 463 * the value is outside the range of valid values for the field 464 * @throws UnsupportedTemporalTypeException if the field is not supported or 465 * the range of values exceeds an {@code int} 466 * @throws ArithmeticException if numeric overflow occurs 467 */ 468 @Override // override for Javadoc get(TemporalField field)469 public int get(TemporalField field) { 470 return range(field).checkValidIntValue(getLong(field), field); 471 } 472 473 /** 474 * Gets the value of the specified field from this year as a {@code long}. 475 * <p> 476 * This queries this year for the value of the specified field. 477 * If it is not possible to return the value, because the field is not supported 478 * or for some other reason, an exception is thrown. 479 * <p> 480 * If the field is a {@link ChronoField} then the query is implemented here. 481 * The {@link #isSupported(TemporalField) supported fields} will return valid 482 * values based on this year. 483 * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. 484 * <p> 485 * If the field is not a {@code ChronoField}, then the result of this method 486 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} 487 * passing {@code this} as the argument. Whether the value can be obtained, 488 * and what the value represents, is determined by the field. 489 * 490 * @param field the field to get, not null 491 * @return the value for the field 492 * @throws DateTimeException if a value for the field cannot be obtained 493 * @throws UnsupportedTemporalTypeException if the field is not supported 494 * @throws ArithmeticException if numeric overflow occurs 495 */ 496 @Override getLong(TemporalField field)497 public long getLong(TemporalField field) { 498 if (field instanceof ChronoField) { 499 switch ((ChronoField) field) { 500 case YEAR_OF_ERA: return (year < 1 ? 1 - year : year); 501 case YEAR: return year; 502 case ERA: return (year < 1 ? 0 : 1); 503 } 504 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 505 } 506 return field.getFrom(this); 507 } 508 509 //----------------------------------------------------------------------- 510 /** 511 * Checks if the year is a leap year, according to the ISO proleptic 512 * calendar system rules. 513 * <p> 514 * This method applies the current rules for leap years across the whole time-line. 515 * In general, a year is a leap year if it is divisible by four without 516 * remainder. However, years divisible by 100, are not leap years, with 517 * the exception of years divisible by 400 which are. 518 * <p> 519 * For example, 1904 is a leap year it is divisible by 4. 520 * 1900 was not a leap year as it is divisible by 100, however 2000 was a 521 * leap year as it is divisible by 400. 522 * <p> 523 * The calculation is proleptic - applying the same rules into the far future and far past. 524 * This is historically inaccurate, but is correct for the ISO-8601 standard. 525 * 526 * @return true if the year is leap, false otherwise 527 */ isLeap()528 public boolean isLeap() { 529 return Year.isLeap(year); 530 } 531 532 /** 533 * Checks if the month-day is valid for this year. 534 * <p> 535 * This method checks whether this year and the input month and day form 536 * a valid date. 537 * 538 * @param monthDay the month-day to validate, null returns false 539 * @return true if the month and day are valid for this year 540 */ isValidMonthDay(MonthDay monthDay)541 public boolean isValidMonthDay(MonthDay monthDay) { 542 return monthDay != null && monthDay.isValidYear(year); 543 } 544 545 /** 546 * Gets the length of this year in days. 547 * 548 * @return the length of this year in days, 365 or 366 549 */ length()550 public int length() { 551 return isLeap() ? 366 : 365; 552 } 553 554 //----------------------------------------------------------------------- 555 /** 556 * Returns an adjusted copy of this year. 557 * <p> 558 * This returns a {@code Year}, based on this one, with the year adjusted. 559 * The adjustment takes place using the specified adjuster strategy object. 560 * Read the documentation of the adjuster to understand what adjustment will be made. 561 * <p> 562 * The result of this method is obtained by invoking the 563 * {@link TemporalAdjuster#adjustInto(Temporal)} method on the 564 * specified adjuster passing {@code this} as the argument. 565 * <p> 566 * This instance is immutable and unaffected by this method call. 567 * 568 * @param adjuster the adjuster to use, not null 569 * @return a {@code Year} based on {@code this} with the adjustment made, not null 570 * @throws DateTimeException if the adjustment cannot be made 571 * @throws ArithmeticException if numeric overflow occurs 572 */ 573 @Override with(TemporalAdjuster adjuster)574 public Year with(TemporalAdjuster adjuster) { 575 return (Year) adjuster.adjustInto(this); 576 } 577 578 /** 579 * Returns a copy of this year with the specified field set to a new value. 580 * <p> 581 * This returns a {@code Year}, based on this one, with the value 582 * for the specified field changed. 583 * If it is not possible to set the value, because the field is not supported or for 584 * some other reason, an exception is thrown. 585 * <p> 586 * If the field is a {@link ChronoField} then the adjustment is implemented here. 587 * The supported fields behave as follows: 588 * <ul> 589 * <li>{@code YEAR_OF_ERA} - 590 * Returns a {@code Year} with the specified year-of-era 591 * The era will be unchanged. 592 * <li>{@code YEAR} - 593 * Returns a {@code Year} with the specified year. 594 * This completely replaces the date and is equivalent to {@link #of(int)}. 595 * <li>{@code ERA} - 596 * Returns a {@code Year} with the specified era. 597 * The year-of-era will be unchanged. 598 * </ul> 599 * <p> 600 * In all cases, if the new value is outside the valid range of values for the field 601 * then a {@code DateTimeException} will be thrown. 602 * <p> 603 * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. 604 * <p> 605 * If the field is not a {@code ChronoField}, then the result of this method 606 * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)} 607 * passing {@code this} as the argument. In this case, the field determines 608 * whether and how to adjust the instant. 609 * <p> 610 * This instance is immutable and unaffected by this method call. 611 * 612 * @param field the field to set in the result, not null 613 * @param newValue the new value of the field in the result 614 * @return a {@code Year} based on {@code this} with the specified field set, not null 615 * @throws DateTimeException if the field cannot be set 616 * @throws UnsupportedTemporalTypeException if the field is not supported 617 * @throws ArithmeticException if numeric overflow occurs 618 */ 619 @Override with(TemporalField field, long newValue)620 public Year with(TemporalField field, long newValue) { 621 if (field instanceof ChronoField) { 622 ChronoField f = (ChronoField) field; 623 f.checkValidValue(newValue); 624 switch (f) { 625 case YEAR_OF_ERA: return Year.of((int) (year < 1 ? 1 - newValue : newValue)); 626 case YEAR: return Year.of((int) newValue); 627 case ERA: return (getLong(ERA) == newValue ? this : Year.of(1 - year)); 628 } 629 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 630 } 631 return field.adjustInto(this, newValue); 632 } 633 634 //----------------------------------------------------------------------- 635 /** 636 * Returns a copy of this year with the specified amount added. 637 * <p> 638 * This returns a {@code Year}, based on this one, with the specified amount added. 639 * The amount is typically {@link Period} but may be any other type implementing 640 * the {@link TemporalAmount} interface. 641 * <p> 642 * The calculation is delegated to the amount object by calling 643 * {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free 644 * to implement the addition in any way it wishes, however it typically 645 * calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation 646 * of the amount implementation to determine if it can be successfully added. 647 * <p> 648 * This instance is immutable and unaffected by this method call. 649 * 650 * @param amountToAdd the amount to add, not null 651 * @return a {@code Year} based on this year with the addition made, not null 652 * @throws DateTimeException if the addition cannot be made 653 * @throws ArithmeticException if numeric overflow occurs 654 */ 655 @Override plus(TemporalAmount amountToAdd)656 public Year plus(TemporalAmount amountToAdd) { 657 return (Year) amountToAdd.addTo(this); 658 } 659 660 /** 661 * Returns a copy of this year with the specified amount added. 662 * <p> 663 * This returns a {@code Year}, based on this one, with the amount 664 * in terms of the unit added. If it is not possible to add the amount, because the 665 * unit is not supported or for some other reason, an exception is thrown. 666 * <p> 667 * If the field is a {@link ChronoUnit} then the addition is implemented here. 668 * The supported fields behave as follows: 669 * <ul> 670 * <li>{@code YEARS} - 671 * Returns a {@code Year} with the specified number of years added. 672 * This is equivalent to {@link #plusYears(long)}. 673 * <li>{@code DECADES} - 674 * Returns a {@code Year} with the specified number of decades added. 675 * This is equivalent to calling {@link #plusYears(long)} with the amount 676 * multiplied by 10. 677 * <li>{@code CENTURIES} - 678 * Returns a {@code Year} with the specified number of centuries added. 679 * This is equivalent to calling {@link #plusYears(long)} with the amount 680 * multiplied by 100. 681 * <li>{@code MILLENNIA} - 682 * Returns a {@code Year} with the specified number of millennia added. 683 * This is equivalent to calling {@link #plusYears(long)} with the amount 684 * multiplied by 1,000. 685 * <li>{@code ERAS} - 686 * Returns a {@code Year} with the specified number of eras added. 687 * Only two eras are supported so the amount must be one, zero or minus one. 688 * If the amount is non-zero then the year is changed such that the year-of-era 689 * is unchanged. 690 * </ul> 691 * <p> 692 * All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}. 693 * <p> 694 * If the field is not a {@code ChronoUnit}, then the result of this method 695 * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)} 696 * passing {@code this} as the argument. In this case, the unit determines 697 * whether and how to perform the addition. 698 * <p> 699 * This instance is immutable and unaffected by this method call. 700 * 701 * @param amountToAdd the amount of the unit to add to the result, may be negative 702 * @param unit the unit of the amount to add, not null 703 * @return a {@code Year} based on this year with the specified amount added, not null 704 * @throws DateTimeException if the addition cannot be made 705 * @throws UnsupportedTemporalTypeException if the unit is not supported 706 * @throws ArithmeticException if numeric overflow occurs 707 */ 708 @Override plus(long amountToAdd, TemporalUnit unit)709 public Year plus(long amountToAdd, TemporalUnit unit) { 710 if (unit instanceof ChronoUnit) { 711 switch ((ChronoUnit) unit) { 712 case YEARS: return plusYears(amountToAdd); 713 case DECADES: return plusYears(Math.multiplyExact(amountToAdd, 10)); 714 case CENTURIES: return plusYears(Math.multiplyExact(amountToAdd, 100)); 715 case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000)); 716 case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd)); 717 } 718 throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit); 719 } 720 return unit.addTo(this, amountToAdd); 721 } 722 723 /** 724 * Returns a copy of this {@code Year} with the specified number of years added. 725 * <p> 726 * This instance is immutable and unaffected by this method call. 727 * 728 * @param yearsToAdd the years to add, may be negative 729 * @return a {@code Year} based on this year with the years added, not null 730 * @throws DateTimeException if the result exceeds the supported range 731 */ plusYears(long yearsToAdd)732 public Year plusYears(long yearsToAdd) { 733 if (yearsToAdd == 0) { 734 return this; 735 } 736 return of(YEAR.checkValidIntValue(year + yearsToAdd)); // overflow safe 737 } 738 739 //----------------------------------------------------------------------- 740 /** 741 * Returns a copy of this year with the specified amount subtracted. 742 * <p> 743 * This returns a {@code Year}, based on this one, with the specified amount subtracted. 744 * The amount is typically {@link Period} but may be any other type implementing 745 * the {@link TemporalAmount} interface. 746 * <p> 747 * The calculation is delegated to the amount object by calling 748 * {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free 749 * to implement the subtraction in any way it wishes, however it typically 750 * calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation 751 * of the amount implementation to determine if it can be successfully subtracted. 752 * <p> 753 * This instance is immutable and unaffected by this method call. 754 * 755 * @param amountToSubtract the amount to subtract, not null 756 * @return a {@code Year} based on this year with the subtraction made, not null 757 * @throws DateTimeException if the subtraction cannot be made 758 * @throws ArithmeticException if numeric overflow occurs 759 */ 760 @Override minus(TemporalAmount amountToSubtract)761 public Year minus(TemporalAmount amountToSubtract) { 762 return (Year) amountToSubtract.subtractFrom(this); 763 } 764 765 /** 766 * Returns a copy of this year with the specified amount subtracted. 767 * <p> 768 * This returns a {@code Year}, based on this one, with the amount 769 * in terms of the unit subtracted. If it is not possible to subtract the amount, 770 * because the unit is not supported or for some other reason, an exception is thrown. 771 * <p> 772 * This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated. 773 * See that method for a full description of how addition, and thus subtraction, works. 774 * <p> 775 * This instance is immutable and unaffected by this method call. 776 * 777 * @param amountToSubtract the amount of the unit to subtract from the result, may be negative 778 * @param unit the unit of the amount to subtract, not null 779 * @return a {@code Year} based on this year with the specified amount subtracted, not null 780 * @throws DateTimeException if the subtraction cannot be made 781 * @throws UnsupportedTemporalTypeException if the unit is not supported 782 * @throws ArithmeticException if numeric overflow occurs 783 */ 784 @Override minus(long amountToSubtract, TemporalUnit unit)785 public Year minus(long amountToSubtract, TemporalUnit unit) { 786 return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); 787 } 788 789 /** 790 * Returns a copy of this {@code Year} with the specified number of years subtracted. 791 * <p> 792 * This instance is immutable and unaffected by this method call. 793 * 794 * @param yearsToSubtract the years to subtract, may be negative 795 * @return a {@code Year} based on this year with the year subtracted, not null 796 * @throws DateTimeException if the result exceeds the supported range 797 */ minusYears(long yearsToSubtract)798 public Year minusYears(long yearsToSubtract) { 799 return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract)); 800 } 801 802 //----------------------------------------------------------------------- 803 /** 804 * Queries this year using the specified query. 805 * <p> 806 * This queries this year using the specified query strategy object. 807 * The {@code TemporalQuery} object defines the logic to be used to 808 * obtain the result. Read the documentation of the query to understand 809 * what the result of this method will be. 810 * <p> 811 * The result of this method is obtained by invoking the 812 * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the 813 * specified query passing {@code this} as the argument. 814 * 815 * @param <R> the type of the result 816 * @param query the query to invoke, not null 817 * @return the query result, null may be returned (defined by the query) 818 * @throws DateTimeException if unable to query (defined by the query) 819 * @throws ArithmeticException if numeric overflow occurs (defined by the query) 820 */ 821 @SuppressWarnings("unchecked") 822 @Override query(TemporalQuery<R> query)823 public <R> R query(TemporalQuery<R> query) { 824 if (query == TemporalQueries.chronology()) { 825 return (R) IsoChronology.INSTANCE; 826 } else if (query == TemporalQueries.precision()) { 827 return (R) YEARS; 828 } 829 return Temporal.super.query(query); 830 } 831 832 /** 833 * Adjusts the specified temporal object to have this year. 834 * <p> 835 * This returns a temporal object of the same observable type as the input 836 * with the year changed to be the same as this. 837 * <p> 838 * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)} 839 * passing {@link ChronoField#YEAR} as the field. 840 * If the specified temporal object does not use the ISO calendar system then 841 * a {@code DateTimeException} is thrown. 842 * <p> 843 * In most cases, it is clearer to reverse the calling pattern by using 844 * {@link Temporal#with(TemporalAdjuster)}: 845 * <pre> 846 * // these two lines are equivalent, but the second approach is recommended 847 * temporal = thisYear.adjustInto(temporal); 848 * temporal = temporal.with(thisYear); 849 * </pre> 850 * <p> 851 * This instance is immutable and unaffected by this method call. 852 * 853 * @param temporal the target object to be adjusted, not null 854 * @return the adjusted object, not null 855 * @throws DateTimeException if unable to make the adjustment 856 * @throws ArithmeticException if numeric overflow occurs 857 */ 858 @Override adjustInto(Temporal temporal)859 public Temporal adjustInto(Temporal temporal) { 860 if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) { 861 throw new DateTimeException("Adjustment only supported on ISO date-time"); 862 } 863 return temporal.with(YEAR, year); 864 } 865 866 /** 867 * Calculates the amount of time until another year in terms of the specified unit. 868 * <p> 869 * This calculates the amount of time between two {@code Year} 870 * objects in terms of a single {@code TemporalUnit}. 871 * The start and end points are {@code this} and the specified year. 872 * The result will be negative if the end is before the start. 873 * The {@code Temporal} passed to this method is converted to a 874 * {@code Year} using {@link #from(TemporalAccessor)}. 875 * For example, the amount in decades between two year can be calculated 876 * using {@code startYear.until(endYear, DECADES)}. 877 * <p> 878 * The calculation returns a whole number, representing the number of 879 * complete units between the two years. 880 * For example, the amount in decades between 2012 and 2031 881 * will only be one decade as it is one year short of two decades. 882 * <p> 883 * There are two equivalent ways of using this method. 884 * The first is to invoke this method. 885 * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}: 886 * <pre> 887 * // these two lines are equivalent 888 * amount = start.until(end, YEARS); 889 * amount = YEARS.between(start, end); 890 * </pre> 891 * The choice should be made based on which makes the code more readable. 892 * <p> 893 * The calculation is implemented in this method for {@link ChronoUnit}. 894 * The units {@code YEARS}, {@code DECADES}, {@code CENTURIES}, 895 * {@code MILLENNIA} and {@code ERAS} are supported. 896 * Other {@code ChronoUnit} values will throw an exception. 897 * <p> 898 * If the unit is not a {@code ChronoUnit}, then the result of this method 899 * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)} 900 * passing {@code this} as the first argument and the converted input temporal 901 * as the second argument. 902 * <p> 903 * This instance is immutable and unaffected by this method call. 904 * 905 * @param endExclusive the end date, exclusive, which is converted to a {@code Year}, not null 906 * @param unit the unit to measure the amount in, not null 907 * @return the amount of time between this year and the end year 908 * @throws DateTimeException if the amount cannot be calculated, or the end 909 * temporal cannot be converted to a {@code Year} 910 * @throws UnsupportedTemporalTypeException if the unit is not supported 911 * @throws ArithmeticException if numeric overflow occurs 912 */ 913 @Override until(Temporal endExclusive, TemporalUnit unit)914 public long until(Temporal endExclusive, TemporalUnit unit) { 915 Year end = Year.from(endExclusive); 916 if (unit instanceof ChronoUnit) { 917 long yearsUntil = ((long) end.year) - year; // no overflow 918 switch ((ChronoUnit) unit) { 919 case YEARS: return yearsUntil; 920 case DECADES: return yearsUntil / 10; 921 case CENTURIES: return yearsUntil / 100; 922 case MILLENNIA: return yearsUntil / 1000; 923 case ERAS: return end.getLong(ERA) - getLong(ERA); 924 } 925 throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit); 926 } 927 return unit.between(this, end); 928 } 929 930 /** 931 * Formats this year using the specified formatter. 932 * <p> 933 * This year will be passed to the formatter to produce a string. 934 * 935 * @param formatter the formatter to use, not null 936 * @return the formatted year string, not null 937 * @throws DateTimeException if an error occurs during printing 938 */ format(DateTimeFormatter formatter)939 public String format(DateTimeFormatter formatter) { 940 Objects.requireNonNull(formatter, "formatter"); 941 return formatter.format(this); 942 } 943 944 //----------------------------------------------------------------------- 945 /** 946 * Combines this year with a day-of-year to create a {@code LocalDate}. 947 * <p> 948 * This returns a {@code LocalDate} formed from this year and the specified day-of-year. 949 * <p> 950 * The day-of-year value 366 is only valid in a leap year. 951 * 952 * @param dayOfYear the day-of-year to use, from 1 to 365-366 953 * @return the local date formed from this year and the specified date of year, not null 954 * @throws DateTimeException if the day of year is zero or less, 366 or greater or equal 955 * to 366 and this is not a leap year 956 */ atDay(int dayOfYear)957 public LocalDate atDay(int dayOfYear) { 958 return LocalDate.ofYearDay(year, dayOfYear); 959 } 960 961 /** 962 * Combines this year with a month to create a {@code YearMonth}. 963 * <p> 964 * This returns a {@code YearMonth} formed from this year and the specified month. 965 * All possible combinations of year and month are valid. 966 * <p> 967 * This method can be used as part of a chain to produce a date: 968 * <pre> 969 * LocalDate date = year.atMonth(month).atDay(day); 970 * </pre> 971 * 972 * @param month the month-of-year to use, not null 973 * @return the year-month formed from this year and the specified month, not null 974 */ atMonth(Month month)975 public YearMonth atMonth(Month month) { 976 return YearMonth.of(year, month); 977 } 978 979 /** 980 * Combines this year with a month to create a {@code YearMonth}. 981 * <p> 982 * This returns a {@code YearMonth} formed from this year and the specified month. 983 * All possible combinations of year and month are valid. 984 * <p> 985 * This method can be used as part of a chain to produce a date: 986 * <pre> 987 * LocalDate date = year.atMonth(month).atDay(day); 988 * </pre> 989 * 990 * @param month the month-of-year to use, from 1 (January) to 12 (December) 991 * @return the year-month formed from this year and the specified month, not null 992 * @throws DateTimeException if the month is invalid 993 */ atMonth(int month)994 public YearMonth atMonth(int month) { 995 return YearMonth.of(year, month); 996 } 997 998 /** 999 * Combines this year with a month-day to create a {@code LocalDate}. 1000 * <p> 1001 * This returns a {@code LocalDate} formed from this year and the specified month-day. 1002 * <p> 1003 * A month-day of February 29th will be adjusted to February 28th in the resulting 1004 * date if the year is not a leap year. 1005 * 1006 * @param monthDay the month-day to use, not null 1007 * @return the local date formed from this year and the specified month-day, not null 1008 */ atMonthDay(MonthDay monthDay)1009 public LocalDate atMonthDay(MonthDay monthDay) { 1010 return monthDay.atYear(year); 1011 } 1012 1013 //----------------------------------------------------------------------- 1014 /** 1015 * Compares this year to another year. 1016 * <p> 1017 * The comparison is based on the value of the year. 1018 * It is "consistent with equals", as defined by {@link Comparable}. 1019 * 1020 * @param other the other year to compare to, not null 1021 * @return the comparator value, negative if less, positive if greater 1022 */ 1023 @Override compareTo(Year other)1024 public int compareTo(Year other) { 1025 return year - other.year; 1026 } 1027 1028 /** 1029 * Checks if this year is after the specified year. 1030 * 1031 * @param other the other year to compare to, not null 1032 * @return true if this is after the specified year 1033 */ isAfter(Year other)1034 public boolean isAfter(Year other) { 1035 return year > other.year; 1036 } 1037 1038 /** 1039 * Checks if this year is before the specified year. 1040 * 1041 * @param other the other year to compare to, not null 1042 * @return true if this point is before the specified year 1043 */ isBefore(Year other)1044 public boolean isBefore(Year other) { 1045 return year < other.year; 1046 } 1047 1048 //----------------------------------------------------------------------- 1049 /** 1050 * Checks if this year is equal to another year. 1051 * <p> 1052 * The comparison is based on the time-line position of the years. 1053 * 1054 * @param obj the object to check, null returns false 1055 * @return true if this is equal to the other year 1056 */ 1057 @Override equals(Object obj)1058 public boolean equals(Object obj) { 1059 if (this == obj) { 1060 return true; 1061 } 1062 if (obj instanceof Year) { 1063 return year == ((Year) obj).year; 1064 } 1065 return false; 1066 } 1067 1068 /** 1069 * A hash code for this year. 1070 * 1071 * @return a suitable hash code 1072 */ 1073 @Override hashCode()1074 public int hashCode() { 1075 return year; 1076 } 1077 1078 //----------------------------------------------------------------------- 1079 /** 1080 * Outputs this year as a {@code String}. 1081 * 1082 * @return a string representation of this year, not null 1083 */ 1084 @Override toString()1085 public String toString() { 1086 return Integer.toString(year); 1087 } 1088 1089 //----------------------------------------------------------------------- 1090 /** 1091 * Writes the object using a 1092 * <a href="{@docRoot}/serialized-form.html#java.time.Ser">dedicated serialized form</a>. 1093 * @serialData 1094 * <pre> 1095 * out.writeByte(11); // identifies a Year 1096 * out.writeInt(year); 1097 * </pre> 1098 * 1099 * @return the instance of {@code Ser}, not null 1100 */ 1101 @java.io.Serial writeReplace()1102 private Object writeReplace() { 1103 return new Ser(Ser.YEAR_TYPE, this); 1104 } 1105 1106 /** 1107 * Defend against malicious streams. 1108 * 1109 * @param s the stream to read 1110 * @throws InvalidObjectException always 1111 */ 1112 @java.io.Serial readObject(ObjectInputStream s)1113 private void readObject(ObjectInputStream s) throws InvalidObjectException { 1114 throw new InvalidObjectException("Deserialization via serialization delegate"); 1115 } 1116 writeExternal(DataOutput out)1117 void writeExternal(DataOutput out) throws IOException { 1118 out.writeInt(year); 1119 } 1120 readExternal(DataInput in)1121 static Year readExternal(DataInput in) throws IOException { 1122 return Year.of(in.readInt()); 1123 } 1124 1125 } 1126