Home | History | Annotate | Download | only in chrono
      1 /*
      2  * Copyright (c) 2012, 2015, 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) 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.chrono;
     63 
     64 import java.io.InvalidObjectException;
     65 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
     66 import static java.time.temporal.ChronoField.ERA;
     67 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
     68 import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
     69 import static java.time.temporal.ChronoField.YEAR;
     70 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
     71 
     72 import java.io.ObjectInputStream;
     73 import java.io.Serializable;
     74 import java.time.Clock;
     75 import java.time.DateTimeException;
     76 import java.time.Instant;
     77 import java.time.LocalDate;
     78 import java.time.LocalDateTime;
     79 import java.time.Month;
     80 import java.time.Period;
     81 import java.time.Year;
     82 import java.time.ZoneId;
     83 import java.time.ZonedDateTime;
     84 import java.time.format.ResolverStyle;
     85 import java.time.temporal.ChronoField;
     86 import java.time.temporal.TemporalAccessor;
     87 import java.time.temporal.TemporalField;
     88 import java.time.temporal.ValueRange;
     89 import java.util.Arrays;
     90 import java.util.List;
     91 import java.util.Locale;
     92 import java.util.Map;
     93 import java.util.Objects;
     94 
     95 /**
     96  * The ISO calendar system.
     97  * <p>
     98  * This chronology defines the rules of the ISO calendar system.
     99  * This calendar system is based on the ISO-8601 standard, which is the
    100  * <i>de facto</i> world calendar.
    101  * <p>
    102  * The fields are defined as follows:
    103  * <ul>
    104  * <li>era - There are two eras, 'Current Era' (CE) and 'Before Current Era' (BCE).
    105  * <li>year-of-era - The year-of-era is the same as the proleptic-year for the current CE era.
    106  *  For the BCE era before the ISO epoch the year increases from 1 upwards as time goes backwards.
    107  * <li>proleptic-year - The proleptic year is the same as the year-of-era for the
    108  *  current era. For the previous era, years have zero, then negative values.
    109  * <li>month-of-year - There are 12 months in an ISO year, numbered from 1 to 12.
    110  * <li>day-of-month - There are between 28 and 31 days in each of the ISO month, numbered from 1 to 31.
    111  *  Months 4, 6, 9 and 11 have 30 days, Months 1, 3, 5, 7, 8, 10 and 12 have 31 days.
    112  *  Month 2 has 28 days, or 29 in a leap year.
    113  * <li>day-of-year - There are 365 days in a standard ISO year and 366 in a leap year.
    114  *  The days are numbered from 1 to 365 or 1 to 366.
    115  * <li>leap-year - Leap years occur every 4 years, except where the year is divisble by 100 and not divisble by 400.
    116  * </ul>
    117  *
    118  * @implSpec
    119  * This class is immutable and thread-safe.
    120  *
    121  * @since 1.8
    122  */
    123 public final class IsoChronology extends AbstractChronology implements Serializable {
    124 
    125     /**
    126      * Singleton instance of the ISO chronology.
    127      */
    128     public static final IsoChronology INSTANCE = new IsoChronology();
    129 
    130     /**
    131      * Serialization version.
    132      */
    133     private static final long serialVersionUID = -1440403870442975015L;
    134 
    135     /**
    136      * Restricted constructor.
    137      */
    138     private IsoChronology() {
    139     }
    140 
    141     //-----------------------------------------------------------------------
    142     /**
    143      * Gets the ID of the chronology - 'ISO'.
    144      * <p>
    145      * The ID uniquely identifies the {@code Chronology}.
    146      * It can be used to lookup the {@code Chronology} using {@link Chronology#of(String)}.
    147      *
    148      * @return the chronology ID - 'ISO'
    149      * @see #getCalendarType()
    150      */
    151     @Override
    152     public String getId() {
    153         return "ISO";
    154     }
    155 
    156     /**
    157      * Gets the calendar type of the underlying calendar system - 'iso8601'.
    158      * <p>
    159      * The calendar type is an identifier defined by the
    160      * <em>Unicode Locale Data Markup Language (LDML)</em> specification.
    161      * It can be used to lookup the {@code Chronology} using {@link Chronology#of(String)}.
    162      * It can also be used as part of a locale, accessible via
    163      * {@link Locale#getUnicodeLocaleType(String)} with the key 'ca'.
    164      *
    165      * @return the calendar system type - 'iso8601'
    166      * @see #getId()
    167      */
    168     @Override
    169     public String getCalendarType() {
    170         return "iso8601";
    171     }
    172 
    173     //-----------------------------------------------------------------------
    174     /**
    175      * Obtains an ISO local date from the era, year-of-era, month-of-year
    176      * and day-of-month fields.
    177      *
    178      * @param era  the ISO era, not null
    179      * @param yearOfEra  the ISO year-of-era
    180      * @param month  the ISO month-of-year
    181      * @param dayOfMonth  the ISO day-of-month
    182      * @return the ISO local date, not null
    183      * @throws DateTimeException if unable to create the date
    184      * @throws ClassCastException if the type of {@code era} is not {@code IsoEra}
    185      */
    186     @Override  // override with covariant return type
    187     public LocalDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
    188         return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
    189     }
    190 
    191     /**
    192      * Obtains an ISO local date from the proleptic-year, month-of-year
    193      * and day-of-month fields.
    194      * <p>
    195      * This is equivalent to {@link LocalDate#of(int, int, int)}.
    196      *
    197      * @param prolepticYear  the ISO proleptic-year
    198      * @param month  the ISO month-of-year
    199      * @param dayOfMonth  the ISO day-of-month
    200      * @return the ISO local date, not null
    201      * @throws DateTimeException if unable to create the date
    202      */
    203     @Override  // override with covariant return type
    204     public LocalDate date(int prolepticYear, int month, int dayOfMonth) {
    205         return LocalDate.of(prolepticYear, month, dayOfMonth);
    206     }
    207 
    208     /**
    209      * Obtains an ISO local date from the era, year-of-era and day-of-year fields.
    210      *
    211      * @param era  the ISO era, not null
    212      * @param yearOfEra  the ISO year-of-era
    213      * @param dayOfYear  the ISO day-of-year
    214      * @return the ISO local date, not null
    215      * @throws DateTimeException if unable to create the date
    216      */
    217     @Override  // override with covariant return type
    218     public LocalDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
    219         return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
    220     }
    221 
    222     /**
    223      * Obtains an ISO local date from the proleptic-year and day-of-year fields.
    224      * <p>
    225      * This is equivalent to {@link LocalDate#ofYearDay(int, int)}.
    226      *
    227      * @param prolepticYear  the ISO proleptic-year
    228      * @param dayOfYear  the ISO day-of-year
    229      * @return the ISO local date, not null
    230      * @throws DateTimeException if unable to create the date
    231      */
    232     @Override  // override with covariant return type
    233     public LocalDate dateYearDay(int prolepticYear, int dayOfYear) {
    234         return LocalDate.ofYearDay(prolepticYear, dayOfYear);
    235     }
    236 
    237     /**
    238      * Obtains an ISO local date from the epoch-day.
    239      * <p>
    240      * This is equivalent to {@link LocalDate#ofEpochDay(long)}.
    241      *
    242      * @param epochDay  the epoch day
    243      * @return the ISO local date, not null
    244      * @throws DateTimeException if unable to create the date
    245      */
    246     @Override  // override with covariant return type
    247     public LocalDate dateEpochDay(long epochDay) {
    248         return LocalDate.ofEpochDay(epochDay);
    249     }
    250 
    251     //-----------------------------------------------------------------------
    252     /**
    253      * Obtains an ISO local date from another date-time object.
    254      * <p>
    255      * This is equivalent to {@link LocalDate#from(TemporalAccessor)}.
    256      *
    257      * @param temporal  the date-time object to convert, not null
    258      * @return the ISO local date, not null
    259      * @throws DateTimeException if unable to create the date
    260      */
    261     @Override  // override with covariant return type
    262     public LocalDate date(TemporalAccessor temporal) {
    263         return LocalDate.from(temporal);
    264     }
    265 
    266     /**
    267      * Obtains an ISO local date-time from another date-time object.
    268      * <p>
    269      * This is equivalent to {@link LocalDateTime#from(TemporalAccessor)}.
    270      *
    271      * @param temporal  the date-time object to convert, not null
    272      * @return the ISO local date-time, not null
    273      * @throws DateTimeException if unable to create the date-time
    274      */
    275     @Override  // override with covariant return type
    276     public LocalDateTime localDateTime(TemporalAccessor temporal) {
    277         return LocalDateTime.from(temporal);
    278     }
    279 
    280     /**
    281      * Obtains an ISO zoned date-time from another date-time object.
    282      * <p>
    283      * This is equivalent to {@link ZonedDateTime#from(TemporalAccessor)}.
    284      *
    285      * @param temporal  the date-time object to convert, not null
    286      * @return the ISO zoned date-time, not null
    287      * @throws DateTimeException if unable to create the date-time
    288      */
    289     @Override  // override with covariant return type
    290     public ZonedDateTime zonedDateTime(TemporalAccessor temporal) {
    291         return ZonedDateTime.from(temporal);
    292     }
    293 
    294     /**
    295      * Obtains an ISO zoned date-time in this chronology from an {@code Instant}.
    296      * <p>
    297      * This is equivalent to {@link ZonedDateTime#ofInstant(Instant, ZoneId)}.
    298      *
    299      * @param instant  the instant to create the date-time from, not null
    300      * @param zone  the time-zone, not null
    301      * @return the zoned date-time, not null
    302      * @throws DateTimeException if the result exceeds the supported range
    303      */
    304     @Override
    305     public ZonedDateTime zonedDateTime(Instant instant, ZoneId zone) {
    306         return ZonedDateTime.ofInstant(instant, zone);
    307     }
    308 
    309     //-----------------------------------------------------------------------
    310     /**
    311      * Obtains the current ISO local date from the system clock in the default time-zone.
    312      * <p>
    313      * This will query the {@link Clock#systemDefaultZone() system clock} in the default
    314      * time-zone to obtain the current date.
    315      * <p>
    316      * Using this method will prevent the ability to use an alternate clock for testing
    317      * because the clock is hard-coded.
    318      *
    319      * @return the current ISO local date using the system clock and default time-zone, not null
    320      * @throws DateTimeException if unable to create the date
    321      */
    322     @Override  // override with covariant return type
    323     public LocalDate dateNow() {
    324         return dateNow(Clock.systemDefaultZone());
    325     }
    326 
    327     /**
    328      * Obtains the current ISO local date from the system clock in the specified time-zone.
    329      * <p>
    330      * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date.
    331      * Specifying the time-zone avoids dependence on the default time-zone.
    332      * <p>
    333      * Using this method will prevent the ability to use an alternate clock for testing
    334      * because the clock is hard-coded.
    335      *
    336      * @return the current ISO local date using the system clock, not null
    337      * @throws DateTimeException if unable to create the date
    338      */
    339     @Override  // override with covariant return type
    340     public LocalDate dateNow(ZoneId zone) {
    341         return dateNow(Clock.system(zone));
    342     }
    343 
    344     /**
    345      * Obtains the current ISO local date from the specified clock.
    346      * <p>
    347      * This will query the specified clock to obtain the current date - today.
    348      * Using this method allows the use of an alternate clock for testing.
    349      * The alternate clock may be introduced using {@link Clock dependency injection}.
    350      *
    351      * @param clock  the clock to use, not null
    352      * @return the current ISO local date, not null
    353      * @throws DateTimeException if unable to create the date
    354      */
    355     @Override  // override with covariant return type
    356     public LocalDate dateNow(Clock clock) {
    357         Objects.requireNonNull(clock, "clock");
    358         return date(LocalDate.now(clock));
    359     }
    360 
    361     //-----------------------------------------------------------------------
    362     /**
    363      * Checks if the year is a leap year, according to the ISO proleptic
    364      * calendar system rules.
    365      * <p>
    366      * This method applies the current rules for leap years across the whole time-line.
    367      * In general, a year is a leap year if it is divisible by four without
    368      * remainder. However, years divisible by 100, are not leap years, with
    369      * the exception of years divisible by 400 which are.
    370      * <p>
    371      * For example, 1904 is a leap year it is divisible by 4.
    372      * 1900 was not a leap year as it is divisible by 100, however 2000 was a
    373      * leap year as it is divisible by 400.
    374      * <p>
    375      * The calculation is proleptic - applying the same rules into the far future and far past.
    376      * This is historically inaccurate, but is correct for the ISO-8601 standard.
    377      *
    378      * @param prolepticYear  the ISO proleptic year to check
    379      * @return true if the year is leap, false otherwise
    380      */
    381     @Override
    382     public boolean isLeapYear(long prolepticYear) {
    383         return ((prolepticYear & 3) == 0) && ((prolepticYear % 100) != 0 || (prolepticYear % 400) == 0);
    384     }
    385 
    386     @Override
    387     public int prolepticYear(Era era, int yearOfEra) {
    388         if (era instanceof IsoEra == false) {
    389             throw new ClassCastException("Era must be IsoEra");
    390         }
    391         return (era == IsoEra.CE ? yearOfEra : 1 - yearOfEra);
    392     }
    393 
    394     @Override
    395     public IsoEra eraOf(int eraValue) {
    396         return IsoEra.of(eraValue);
    397     }
    398 
    399     @Override
    400     public List<Era> eras() {
    401         return Arrays.<Era>asList(IsoEra.values());
    402     }
    403 
    404     //-----------------------------------------------------------------------
    405     /**
    406      * Resolves parsed {@code ChronoField} values into a date during parsing.
    407      * <p>
    408      * Most {@code TemporalField} implementations are resolved using the
    409      * resolve method on the field. By contrast, the {@code ChronoField} class
    410      * defines fields that only have meaning relative to the chronology.
    411      * As such, {@code ChronoField} date fields are resolved here in the
    412      * context of a specific chronology.
    413      * <p>
    414      * {@code ChronoField} instances on the ISO calendar system are resolved
    415      * as follows.
    416      * <ul>
    417      * <li>{@code EPOCH_DAY} - If present, this is converted to a {@code LocalDate}
    418      *  and all other date fields are then cross-checked against the date.
    419      * <li>{@code PROLEPTIC_MONTH} - If present, then it is split into the
    420      *  {@code YEAR} and {@code MONTH_OF_YEAR}. If the mode is strict or smart
    421      *  then the field is validated.
    422      * <li>{@code YEAR_OF_ERA} and {@code ERA} - If both are present, then they
    423      *  are combined to form a {@code YEAR}. In lenient mode, the {@code YEAR_OF_ERA}
    424      *  range is not validated, in smart and strict mode it is. The {@code ERA} is
    425      *  validated for range in all three modes. If only the {@code YEAR_OF_ERA} is
    426      *  present, and the mode is smart or lenient, then the current era (CE/AD)
    427      *  is assumed. In strict mode, no era is assumed and the {@code YEAR_OF_ERA} is
    428      *  left untouched. If only the {@code ERA} is present, then it is left untouched.
    429      * <li>{@code YEAR}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} -
    430      *  If all three are present, then they are combined to form a {@code LocalDate}.
    431      *  In all three modes, the {@code YEAR} is validated. If the mode is smart or strict,
    432      *  then the month and day are validated, with the day validated from 1 to 31.
    433      *  If the mode is lenient, then the date is combined in a manner equivalent to
    434      *  creating a date on the first of January in the requested year, then adding
    435      *  the difference in months, then the difference in days.
    436      *  If the mode is smart, and the day-of-month is greater than the maximum for
    437      *  the year-month, then the day-of-month is adjusted to the last day-of-month.
    438      *  If the mode is strict, then the three fields must form a valid date.
    439      * <li>{@code YEAR} and {@code DAY_OF_YEAR} -
    440      *  If both are present, then they are combined to form a {@code LocalDate}.
    441      *  In all three modes, the {@code YEAR} is validated.
    442      *  If the mode is lenient, then the date is combined in a manner equivalent to
    443      *  creating a date on the first of January in the requested year, then adding
    444      *  the difference in days.
    445      *  If the mode is smart or strict, then the two fields must form a valid date.
    446      * <li>{@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and
    447      *  {@code ALIGNED_DAY_OF_WEEK_IN_MONTH} -
    448      *  If all four are present, then they are combined to form a {@code LocalDate}.
    449      *  In all three modes, the {@code YEAR} is validated.
    450      *  If the mode is lenient, then the date is combined in a manner equivalent to
    451      *  creating a date on the first of January in the requested year, then adding
    452      *  the difference in months, then the difference in weeks, then in days.
    453      *  If the mode is smart or strict, then the all four fields are validated to
    454      *  their outer ranges. The date is then combined in a manner equivalent to
    455      *  creating a date on the first day of the requested year and month, then adding
    456      *  the amount in weeks and days to reach their values. If the mode is strict,
    457      *  the date is additionally validated to check that the day and week adjustment
    458      *  did not change the month.
    459      * <li>{@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and
    460      *  {@code DAY_OF_WEEK} - If all four are present, then they are combined to
    461      *  form a {@code LocalDate}. The approach is the same as described above for
    462      *  years, months and weeks in {@code ALIGNED_DAY_OF_WEEK_IN_MONTH}.
    463      *  The day-of-week is adjusted as the next or same matching day-of-week once
    464      *  the years, months and weeks have been handled.
    465      * <li>{@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code ALIGNED_DAY_OF_WEEK_IN_YEAR} -
    466      *  If all three are present, then they are combined to form a {@code LocalDate}.
    467      *  In all three modes, the {@code YEAR} is validated.
    468      *  If the mode is lenient, then the date is combined in a manner equivalent to
    469      *  creating a date on the first of January in the requested year, then adding
    470      *  the difference in weeks, then in days.
    471      *  If the mode is smart or strict, then the all three fields are validated to
    472      *  their outer ranges. The date is then combined in a manner equivalent to
    473      *  creating a date on the first day of the requested year, then adding
    474      *  the amount in weeks and days to reach their values. If the mode is strict,
    475      *  the date is additionally validated to check that the day and week adjustment
    476      *  did not change the year.
    477      * <li>{@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code DAY_OF_WEEK} -
    478      *  If all three are present, then they are combined to form a {@code LocalDate}.
    479      *  The approach is the same as described above for years and weeks in
    480      *  {@code ALIGNED_DAY_OF_WEEK_IN_YEAR}. The day-of-week is adjusted as the
    481      *  next or same matching day-of-week once the years and weeks have been handled.
    482      * </ul>
    483      *
    484      * @param fieldValues  the map of fields to values, which can be updated, not null
    485      * @param resolverStyle  the requested type of resolve, not null
    486      * @return the resolved date, null if insufficient information to create a date
    487      * @throws DateTimeException if the date cannot be resolved, typically
    488      *  because of a conflict in the input data
    489      */
    490     @Override  // override for performance
    491     public LocalDate resolveDate(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
    492         return (LocalDate) super.resolveDate(fieldValues, resolverStyle);
    493     }
    494 
    495     @Override  // override for better proleptic algorithm
    496     void resolveProlepticMonth(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
    497         Long pMonth = fieldValues.remove(PROLEPTIC_MONTH);
    498         if (pMonth != null) {
    499             if (resolverStyle != ResolverStyle.LENIENT) {
    500                 PROLEPTIC_MONTH.checkValidValue(pMonth);
    501             }
    502             addFieldValue(fieldValues, MONTH_OF_YEAR, Math.floorMod(pMonth, 12) + 1);
    503             addFieldValue(fieldValues, YEAR, Math.floorDiv(pMonth, 12));
    504         }
    505     }
    506 
    507     @Override  // override for enhanced behaviour
    508     LocalDate resolveYearOfEra(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
    509         Long yoeLong = fieldValues.remove(YEAR_OF_ERA);
    510         if (yoeLong != null) {
    511             if (resolverStyle != ResolverStyle.LENIENT) {
    512                 YEAR_OF_ERA.checkValidValue(yoeLong);
    513             }
    514             Long era = fieldValues.remove(ERA);
    515             if (era == null) {
    516                 Long year = fieldValues.get(YEAR);
    517                 if (resolverStyle == ResolverStyle.STRICT) {
    518                     // do not invent era if strict, but do cross-check with year
    519                     if (year != null) {
    520                         addFieldValue(fieldValues, YEAR, (year > 0 ? yoeLong: Math.subtractExact(1, yoeLong)));
    521                     } else {
    522                         // reinstate the field removed earlier, no cross-check issues
    523                         fieldValues.put(YEAR_OF_ERA, yoeLong);
    524                     }
    525                 } else {
    526                     // invent era
    527                     addFieldValue(fieldValues, YEAR, (year == null || year > 0 ? yoeLong: Math.subtractExact(1, yoeLong)));
    528                 }
    529             } else if (era.longValue() == 1L) {
    530                 addFieldValue(fieldValues, YEAR, yoeLong);
    531             } else if (era.longValue() == 0L) {
    532                 addFieldValue(fieldValues, YEAR, Math.subtractExact(1, yoeLong));
    533             } else {
    534                 throw new DateTimeException("Invalid value for era: " + era);
    535             }
    536         } else if (fieldValues.containsKey(ERA)) {
    537             ERA.checkValidValue(fieldValues.get(ERA));  // always validated
    538         }
    539         return null;
    540     }
    541 
    542     @Override  // override for performance
    543     LocalDate resolveYMD(Map <TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
    544         int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR));
    545         if (resolverStyle == ResolverStyle.LENIENT) {
    546             long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
    547             long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
    548             return LocalDate.of(y, 1, 1).plusMonths(months).plusDays(days);
    549         }
    550         int moy = MONTH_OF_YEAR.checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR));
    551         int dom = DAY_OF_MONTH.checkValidIntValue(fieldValues.remove(DAY_OF_MONTH));
    552         if (resolverStyle == ResolverStyle.SMART) {  // previous valid
    553             if (moy == 4 || moy == 6 || moy == 9 || moy == 11) {
    554                 dom = Math.min(dom, 30);
    555             } else if (moy == 2) {
    556                 dom = Math.min(dom, Month.FEBRUARY.length(Year.isLeap(y)));
    557 
    558             }
    559         }
    560         return LocalDate.of(y, moy, dom);
    561     }
    562 
    563     //-----------------------------------------------------------------------
    564     @Override
    565     public ValueRange range(ChronoField field) {
    566         return field.range();
    567     }
    568 
    569     //-----------------------------------------------------------------------
    570     /**
    571      * Obtains a period for this chronology based on years, months and days.
    572      * <p>
    573      * This returns a period tied to the ISO chronology using the specified
    574      * years, months and days. See {@link Period} for further details.
    575      *
    576      * @param years  the number of years, may be negative
    577      * @param months  the number of years, may be negative
    578      * @param days  the number of years, may be negative
    579      * @return the period in terms of this chronology, not null
    580      * @return the ISO period, not null
    581      */
    582     @Override  // override with covariant return type
    583     public Period period(int years, int months, int days) {
    584         return Period.of(years, months, days);
    585     }
    586 
    587     //-----------------------------------------------------------------------
    588     /**
    589      * Writes the Chronology using a
    590      * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
    591      * @serialData
    592      * <pre>
    593      *  out.writeByte(1);     // identifies a Chronology
    594      *  out.writeUTF(getId());
    595      * </pre>
    596      *
    597      * @return the instance of {@code Ser}, not null
    598      */
    599     @Override
    600     Object writeReplace() {
    601         return super.writeReplace();
    602     }
    603 
    604     /**
    605      * Defend against malicious streams.
    606      *
    607      * @param s the stream to read
    608      * @throws InvalidObjectException always
    609      */
    610     private void readObject(ObjectInputStream s) throws InvalidObjectException {
    611         throw new InvalidObjectException("Deserialization via serialization delegate");
    612     }
    613 }
    614