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