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