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