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