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