Home | History | Annotate | Download | only in chrono
      1 /*
      2  * Copyright (c) 2012, 2016, 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  * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
     28  *
     29  * All rights reserved.
     30  *
     31  * Redistribution and use in source and binary forms, with or without
     32  * modification, are permitted provided that the following conditions are met:
     33  *
     34  *  * Redistributions of source code must retain the above copyright notice,
     35  *    this list of conditions and the following disclaimer.
     36  *
     37  *  * Redistributions in binary form must reproduce the above copyright notice,
     38  *    this list of conditions and the following disclaimer in the documentation
     39  *    and/or other materials provided with the distribution.
     40  *
     41  *  * Neither the name of JSR-310 nor the names of its contributors
     42  *    may be used to endorse or promote products derived from this software
     43  *    without specific prior written permission.
     44  *
     45  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     46  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     47  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     48  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     49  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     50  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     51  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     52  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     53  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     54  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     55  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     56  */
     57 package java.time.chrono;
     58 
     59 import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
     60 import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
     61 import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;
     62 import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;
     63 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
     64 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
     65 import static java.time.temporal.ChronoField.YEAR;
     66 
     67 import java.io.DataInput;
     68 import java.io.DataOutput;
     69 import java.io.IOException;
     70 import java.io.InvalidObjectException;
     71 import java.io.ObjectInputStream;
     72 import java.io.Serializable;
     73 import java.time.Clock;
     74 import java.time.DateTimeException;
     75 import java.time.LocalDate;
     76 import java.time.LocalTime;
     77 import java.time.Period;
     78 import java.time.ZoneId;
     79 import java.time.temporal.ChronoField;
     80 import java.time.temporal.TemporalAccessor;
     81 import java.time.temporal.TemporalAdjuster;
     82 import java.time.temporal.TemporalAmount;
     83 import java.time.temporal.TemporalField;
     84 import java.time.temporal.TemporalQuery;
     85 import java.time.temporal.TemporalUnit;
     86 import java.time.temporal.UnsupportedTemporalTypeException;
     87 import java.time.temporal.ValueRange;
     88 import java.util.Calendar;
     89 import java.util.Objects;
     90 
     91 import sun.util.calendar.CalendarDate;
     92 import sun.util.calendar.LocalGregorianCalendar;
     93 
     94 // Android-changed: removed ValueBased paragraph.
     95 /**
     96  * A date in the Japanese Imperial calendar system.
     97  * <p>
     98  * This date operates using the {@linkplain JapaneseChronology Japanese Imperial calendar}.
     99  * This calendar system is primarily used in Japan.
    100  * <p>
    101  * The Japanese Imperial calendar system is the same as the ISO calendar system
    102  * apart from the era-based year numbering. The proleptic-year is defined to be
    103  * equal to the ISO proleptic-year.
    104  * <p>
    105  * Japan introduced the Gregorian calendar starting with Meiji 6.
    106  * Only Meiji and later eras are supported;
    107  * dates before Meiji 6, January 1 are not supported.
    108  * <p>
    109  * For example, the Japanese year "Heisei 24" corresponds to ISO year "2012".<br>
    110  * Calling {@code japaneseDate.get(YEAR_OF_ERA)} will return 24.<br>
    111  * Calling {@code japaneseDate.get(YEAR)} will return 2012.<br>
    112  * Calling {@code japaneseDate.get(ERA)} will return 2, corresponding to
    113  * {@code JapaneseChronology.ERA_HEISEI}.<br>
    114  *
    115  * @implSpec
    116  * This class is immutable and thread-safe.
    117  *
    118  * @since 1.8
    119  */
    120 public final class JapaneseDate
    121         extends ChronoLocalDateImpl<JapaneseDate>
    122         implements ChronoLocalDate, Serializable {
    123 
    124     /**
    125      * Serialization version.
    126      */
    127     private static final long serialVersionUID = -305327627230580483L;
    128 
    129     /**
    130      * The underlying ISO local date.
    131      */
    132     private final transient LocalDate isoDate;
    133     /**
    134      * The JapaneseEra of this date.
    135      */
    136     private transient JapaneseEra era;
    137     /**
    138      * The Japanese imperial calendar year of this date.
    139      */
    140     private transient int yearOfEra;
    141 
    142     /**
    143      * The first day supported by the JapaneseChronology is Meiji 6, January 1st.
    144      */
    145     static final LocalDate MEIJI_6_ISODATE = LocalDate.of(1873, 1, 1);
    146 
    147     //-----------------------------------------------------------------------
    148     /**
    149      * Obtains the current {@code JapaneseDate} from the system clock in the default time-zone.
    150      * <p>
    151      * This will query the {@link Clock#systemDefaultZone() system clock} in the default
    152      * time-zone to obtain the current date.
    153      * <p>
    154      * Using this method will prevent the ability to use an alternate clock for testing
    155      * because the clock is hard-coded.
    156      *
    157      * @return the current date using the system clock and default time-zone, not null
    158      */
    159     public static JapaneseDate now() {
    160         return now(Clock.systemDefaultZone());
    161     }
    162 
    163     /**
    164      * Obtains the current {@code JapaneseDate} from the system clock in the specified time-zone.
    165      * <p>
    166      * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date.
    167      * Specifying the time-zone avoids dependence on the default time-zone.
    168      * <p>
    169      * Using this method will prevent the ability to use an alternate clock for testing
    170      * because the clock is hard-coded.
    171      *
    172      * @param zone  the zone ID to use, not null
    173      * @return the current date using the system clock, not null
    174      */
    175     public static JapaneseDate now(ZoneId zone) {
    176         return now(Clock.system(zone));
    177     }
    178 
    179     /**
    180      * Obtains the current {@code JapaneseDate} from the specified clock.
    181      * <p>
    182      * This will query the specified clock to obtain the current date - today.
    183      * Using this method allows the use of an alternate clock for testing.
    184      * The alternate clock may be introduced using {@linkplain Clock dependency injection}.
    185      *
    186      * @param clock  the clock to use, not null
    187      * @return the current date, not null
    188      * @throws DateTimeException if the current date cannot be obtained
    189      */
    190     public static JapaneseDate now(Clock clock) {
    191         return new JapaneseDate(LocalDate.now(clock));
    192     }
    193 
    194     /**
    195      * Obtains a {@code JapaneseDate} representing a date in the Japanese calendar
    196      * system from the era, year-of-era, month-of-year and day-of-month fields.
    197      * <p>
    198      * This returns a {@code JapaneseDate} with the specified fields.
    199      * The day must be valid for the year and month, otherwise an exception will be thrown.
    200      * <p>
    201      * The Japanese month and day-of-month are the same as those in the
    202      * ISO calendar system. They are not reset when the era changes.
    203      * For example:
    204      * <pre>
    205      *  6th Jan Showa 64 = ISO 1989-01-06
    206      *  7th Jan Showa 64 = ISO 1989-01-07
    207      *  8th Jan Heisei 1 = ISO 1989-01-08
    208      *  9th Jan Heisei 1 = ISO 1989-01-09
    209      * </pre>
    210      *
    211      * @param era  the Japanese era, not null
    212      * @param yearOfEra  the Japanese year-of-era
    213      * @param month  the Japanese month-of-year, from 1 to 12
    214      * @param dayOfMonth  the Japanese day-of-month, from 1 to 31
    215      * @return the date in Japanese calendar system, not null
    216      * @throws DateTimeException if the value of any field is out of range,
    217      *  or if the day-of-month is invalid for the month-year,
    218      *  or if the date is not a Japanese era
    219      */
    220     public static JapaneseDate of(JapaneseEra era, int yearOfEra, int month, int dayOfMonth) {
    221         Objects.requireNonNull(era, "era");
    222         LocalGregorianCalendar.Date jdate = JapaneseChronology.JCAL.newCalendarDate(null);
    223         jdate.setEra(era.getPrivateEra()).setDate(yearOfEra, month, dayOfMonth);
    224         if (!JapaneseChronology.JCAL.validate(jdate)) {
    225             throw new DateTimeException("year, month, and day not valid for Era");
    226         }
    227         LocalDate date = LocalDate.of(jdate.getNormalizedYear(), month, dayOfMonth);
    228         return new JapaneseDate(era, yearOfEra, date);
    229     }
    230 
    231     /**
    232      * Obtains a {@code JapaneseDate} representing a date in the Japanese calendar
    233      * system from the proleptic-year, month-of-year and day-of-month fields.
    234      * <p>
    235      * This returns a {@code JapaneseDate} with the specified fields.
    236      * The day must be valid for the year and month, otherwise an exception will be thrown.
    237      * <p>
    238      * The Japanese proleptic year, month and day-of-month are the same as those
    239      * in the ISO calendar system. They are not reset when the era changes.
    240      *
    241      * @param prolepticYear  the Japanese proleptic-year
    242      * @param month  the Japanese month-of-year, from 1 to 12
    243      * @param dayOfMonth  the Japanese day-of-month, from 1 to 31
    244      * @return the date in Japanese calendar system, not null
    245      * @throws DateTimeException if the value of any field is out of range,
    246      *  or if the day-of-month is invalid for the month-year
    247      */
    248     public static JapaneseDate of(int prolepticYear, int month, int dayOfMonth) {
    249         return new JapaneseDate(LocalDate.of(prolepticYear, month, dayOfMonth));
    250     }
    251 
    252     /**
    253      * Obtains a {@code JapaneseDate} representing a date in the Japanese calendar
    254      * system from the era, year-of-era and day-of-year fields.
    255      * <p>
    256      * This returns a {@code JapaneseDate} with the specified fields.
    257      * The day must be valid for the year, otherwise an exception will be thrown.
    258      * <p>
    259      * The day-of-year in this factory is expressed relative to the start of the year-of-era.
    260      * This definition changes the normal meaning of day-of-year only in those years
    261      * where the year-of-era is reset to one due to a change in the era.
    262      * For example:
    263      * <pre>
    264      *  6th Jan Showa 64 = day-of-year 6
    265      *  7th Jan Showa 64 = day-of-year 7
    266      *  8th Jan Heisei 1 = day-of-year 1
    267      *  9th Jan Heisei 1 = day-of-year 2
    268      * </pre>
    269      *
    270      * @param era  the Japanese era, not null
    271      * @param yearOfEra  the Japanese year-of-era
    272      * @param dayOfYear  the chronology day-of-year, from 1 to 366
    273      * @return the date in Japanese calendar system, not null
    274      * @throws DateTimeException if the value of any field is out of range,
    275      *  or if the day-of-year is invalid for the year
    276      */
    277     static JapaneseDate ofYearDay(JapaneseEra era, int yearOfEra, int dayOfYear) {
    278         Objects.requireNonNull(era, "era");
    279         CalendarDate firstDay = era.getPrivateEra().getSinceDate();
    280         LocalGregorianCalendar.Date jdate = JapaneseChronology.JCAL.newCalendarDate(null);
    281         jdate.setEra(era.getPrivateEra());
    282         if (yearOfEra == 1) {
    283             jdate.setDate(yearOfEra, firstDay.getMonth(), firstDay.getDayOfMonth() + dayOfYear - 1);
    284         } else {
    285             jdate.setDate(yearOfEra, 1, dayOfYear);
    286         }
    287         JapaneseChronology.JCAL.normalize(jdate);
    288         if (era.getPrivateEra() != jdate.getEra() || yearOfEra != jdate.getYear()) {
    289             throw new DateTimeException("Invalid parameters");
    290         }
    291         LocalDate localdate = LocalDate.of(jdate.getNormalizedYear(),
    292                                       jdate.getMonth(), jdate.getDayOfMonth());
    293         return new JapaneseDate(era, yearOfEra, localdate);
    294     }
    295 
    296     /**
    297      * Obtains a {@code JapaneseDate} from a temporal object.
    298      * <p>
    299      * This obtains a date in the Japanese calendar system based on the specified temporal.
    300      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
    301      * which this factory converts to an instance of {@code JapaneseDate}.
    302      * <p>
    303      * The conversion typically uses the {@link ChronoField#EPOCH_DAY EPOCH_DAY}
    304      * field, which is standardized across calendar systems.
    305      * <p>
    306      * This method matches the signature of the functional interface {@link TemporalQuery}
    307      * allowing it to be used as a query via method reference, {@code JapaneseDate::from}.
    308      *
    309      * @param temporal  the temporal object to convert, not null
    310      * @return the date in Japanese calendar system, not null
    311      * @throws DateTimeException if unable to convert to a {@code JapaneseDate}
    312      */
    313     public static JapaneseDate from(TemporalAccessor temporal) {
    314         return JapaneseChronology.INSTANCE.date(temporal);
    315     }
    316 
    317     //-----------------------------------------------------------------------
    318     /**
    319      * Creates an instance from an ISO date.
    320      *
    321      * @param isoDate  the standard local date, validated not null
    322      */
    323     JapaneseDate(LocalDate isoDate) {
    324         if (isoDate.isBefore(MEIJI_6_ISODATE)) {
    325             throw new DateTimeException("JapaneseDate before Meiji 6 is not supported");
    326         }
    327         LocalGregorianCalendar.Date jdate = toPrivateJapaneseDate(isoDate);
    328         this.era = JapaneseEra.toJapaneseEra(jdate.getEra());
    329         this.yearOfEra = jdate.getYear();
    330         this.isoDate = isoDate;
    331     }
    332 
    333     /**
    334      * Constructs a {@code JapaneseDate}. This constructor does NOT validate the given parameters,
    335      * and {@code era} and {@code year} must agree with {@code isoDate}.
    336      *
    337      * @param era  the era, validated not null
    338      * @param year  the year-of-era, validated
    339      * @param isoDate  the standard local date, validated not null
    340      */
    341     JapaneseDate(JapaneseEra era, int year, LocalDate isoDate) {
    342         if (isoDate.isBefore(MEIJI_6_ISODATE)) {
    343             throw new DateTimeException("JapaneseDate before Meiji 6 is not supported");
    344         }
    345         this.era = era;
    346         this.yearOfEra = year;
    347         this.isoDate = isoDate;
    348     }
    349 
    350     //-----------------------------------------------------------------------
    351     /**
    352      * Gets the chronology of this date, which is the Japanese calendar system.
    353      * <p>
    354      * The {@code Chronology} represents the calendar system in use.
    355      * The era and other fields in {@link ChronoField} are defined by the chronology.
    356      *
    357      * @return the Japanese chronology, not null
    358      */
    359     @Override
    360     public JapaneseChronology getChronology() {
    361         return JapaneseChronology.INSTANCE;
    362     }
    363 
    364     /**
    365      * Gets the era applicable at this date.
    366      * <p>
    367      * The Japanese calendar system has multiple eras defined by {@link JapaneseEra}.
    368      *
    369      * @return the era applicable at this date, not null
    370      */
    371     @Override
    372     public JapaneseEra getEra() {
    373         return era;
    374     }
    375 
    376     /**
    377      * Returns the length of the month represented by this date.
    378      * <p>
    379      * This returns the length of the month in days.
    380      * Month lengths match those of the ISO calendar system.
    381      *
    382      * @return the length of the month in days
    383      */
    384     @Override
    385     public int lengthOfMonth() {
    386         return isoDate.lengthOfMonth();
    387     }
    388 
    389     @Override
    390     public int lengthOfYear() {
    391         // Android-changed: use #createCalendar() to create calendar.
    392         Calendar jcal = JapaneseChronology.createCalendar();
    393         jcal.set(Calendar.ERA, era.getValue() + JapaneseEra.ERA_OFFSET);
    394         jcal.set(yearOfEra, isoDate.getMonthValue() - 1, isoDate.getDayOfMonth());
    395         return  jcal.getActualMaximum(Calendar.DAY_OF_YEAR);
    396     }
    397 
    398     //-----------------------------------------------------------------------
    399     /**
    400      * Checks if the specified field is supported.
    401      * <p>
    402      * This checks if this date can be queried for the specified field.
    403      * If false, then calling the {@link #range(TemporalField) range} and
    404      * {@link #get(TemporalField) get} methods will throw an exception.
    405      * <p>
    406      * If the field is a {@link ChronoField} then the query is implemented here.
    407      * The supported fields are:
    408      * <ul>
    409      * <li>{@code DAY_OF_WEEK}
    410      * <li>{@code DAY_OF_MONTH}
    411      * <li>{@code DAY_OF_YEAR}
    412      * <li>{@code EPOCH_DAY}
    413      * <li>{@code MONTH_OF_YEAR}
    414      * <li>{@code PROLEPTIC_MONTH}
    415      * <li>{@code YEAR_OF_ERA}
    416      * <li>{@code YEAR}
    417      * <li>{@code ERA}
    418      * </ul>
    419      * All other {@code ChronoField} instances will return false.
    420      * <p>
    421      * If the field is not a {@code ChronoField}, then the result of this method
    422      * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
    423      * passing {@code this} as the argument.
    424      * Whether the field is supported is determined by the field.
    425      *
    426      * @param field  the field to check, null returns false
    427      * @return true if the field is supported on this date, false if not
    428      */
    429     @Override
    430     public boolean isSupported(TemporalField field) {
    431         if (field == ALIGNED_DAY_OF_WEEK_IN_MONTH || field == ALIGNED_DAY_OF_WEEK_IN_YEAR ||
    432                 field == ALIGNED_WEEK_OF_MONTH || field == ALIGNED_WEEK_OF_YEAR) {
    433             return false;
    434         }
    435         // Android-changed: Apply upstream OpenJDK 9 compilation fix.
    436         // Applied OpenJDK 9 change from http://hg.openjdk.java.net/jdk9/dev/jdk/rev/2b7b09c81bf1
    437         // On OpenJDK 8, either version is supported and has the same behavior.
    438         // return ChronoLocalDate.super.isSupported(field);
    439         return super.isSupported(field);
    440     }
    441 
    442     @Override
    443     public ValueRange range(TemporalField field) {
    444         if (field instanceof ChronoField) {
    445             if (isSupported(field)) {
    446                 ChronoField f = (ChronoField) field;
    447                 switch (f) {
    448                     case DAY_OF_MONTH: return ValueRange.of(1, lengthOfMonth());
    449                     case DAY_OF_YEAR: return ValueRange.of(1, lengthOfYear());
    450                     case YEAR_OF_ERA: {
    451                         // Android-changed: use #createCalendar() to create calendar.
    452                         Calendar jcal = JapaneseChronology.createCalendar();
    453                         jcal.set(Calendar.ERA, era.getValue() + JapaneseEra.ERA_OFFSET);
    454                         jcal.set(yearOfEra, isoDate.getMonthValue() - 1, isoDate.getDayOfMonth());
    455                         return ValueRange.of(1, jcal.getActualMaximum(Calendar.YEAR));
    456                     }
    457                 }
    458                 return getChronology().range(f);
    459             }
    460             throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
    461         }
    462         return field.rangeRefinedBy(this);
    463     }
    464 
    465     @Override
    466     public long getLong(TemporalField field) {
    467         if (field instanceof ChronoField) {
    468             // same as ISO:
    469             // DAY_OF_WEEK, DAY_OF_MONTH, EPOCH_DAY, MONTH_OF_YEAR, PROLEPTIC_MONTH, YEAR
    470             //
    471             // calendar specific fields
    472             // DAY_OF_YEAR, YEAR_OF_ERA, ERA
    473             switch ((ChronoField) field) {
    474                 case ALIGNED_DAY_OF_WEEK_IN_MONTH:
    475                 case ALIGNED_DAY_OF_WEEK_IN_YEAR:
    476                 case ALIGNED_WEEK_OF_MONTH:
    477                 case ALIGNED_WEEK_OF_YEAR:
    478                     throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
    479                 case YEAR_OF_ERA:
    480                     return yearOfEra;
    481                 case ERA:
    482                     return era.getValue();
    483                 case DAY_OF_YEAR:
    484                     // Android-changed: use #createCalendar() to create calendar.
    485                     Calendar jcal = JapaneseChronology.createCalendar();
    486                     jcal.set(Calendar.ERA, era.getValue() + JapaneseEra.ERA_OFFSET);
    487                     jcal.set(yearOfEra, isoDate.getMonthValue() - 1, isoDate.getDayOfMonth());
    488                     return jcal.get(Calendar.DAY_OF_YEAR);
    489             }
    490             return isoDate.getLong(field);
    491         }
    492         return field.getFrom(this);
    493     }
    494 
    495     /**
    496      * Returns a {@code LocalGregorianCalendar.Date} converted from the given {@code isoDate}.
    497      *
    498      * @param isoDate  the local date, not null
    499      * @return a {@code LocalGregorianCalendar.Date}, not null
    500      */
    501     private static LocalGregorianCalendar.Date toPrivateJapaneseDate(LocalDate isoDate) {
    502         LocalGregorianCalendar.Date jdate = JapaneseChronology.JCAL.newCalendarDate(null);
    503         sun.util.calendar.Era sunEra = JapaneseEra.privateEraFrom(isoDate);
    504         int year = isoDate.getYear();
    505         if (sunEra != null) {
    506             year -= sunEra.getSinceDate().getYear() - 1;
    507         }
    508         jdate.setEra(sunEra).setYear(year).setMonth(isoDate.getMonthValue()).setDayOfMonth(isoDate.getDayOfMonth());
    509         JapaneseChronology.JCAL.normalize(jdate);
    510         return jdate;
    511     }
    512 
    513     //-----------------------------------------------------------------------
    514     @Override
    515     public JapaneseDate with(TemporalField field, long newValue) {
    516         if (field instanceof ChronoField) {
    517             ChronoField f = (ChronoField) field;
    518             if (getLong(f) == newValue) {  // getLong() validates for supported fields
    519                 return this;
    520             }
    521             switch (f) {
    522                 case YEAR_OF_ERA:
    523                 case YEAR:
    524                 case ERA: {
    525                     int nvalue = getChronology().range(f).checkValidIntValue(newValue, f);
    526                     switch (f) {
    527                         case YEAR_OF_ERA:
    528                             return this.withYear(nvalue);
    529                         case YEAR:
    530                             return with(isoDate.withYear(nvalue));
    531                         case ERA: {
    532                             return this.withYear(JapaneseEra.of(nvalue), yearOfEra);
    533                         }
    534                     }
    535                 }
    536             }
    537             // YEAR, PROLEPTIC_MONTH and others are same as ISO
    538             return with(isoDate.with(field, newValue));
    539         }
    540         return super.with(field, newValue);
    541     }
    542 
    543     /**
    544      * {@inheritDoc}
    545      * @throws DateTimeException {@inheritDoc}
    546      * @throws ArithmeticException {@inheritDoc}
    547      */
    548     @Override
    549     public  JapaneseDate with(TemporalAdjuster adjuster) {
    550         return super.with(adjuster);
    551     }
    552 
    553     /**
    554      * {@inheritDoc}
    555      * @throws DateTimeException {@inheritDoc}
    556      * @throws ArithmeticException {@inheritDoc}
    557      */
    558     @Override
    559     public JapaneseDate plus(TemporalAmount amount) {
    560         return super.plus(amount);
    561     }
    562 
    563     /**
    564      * {@inheritDoc}
    565      * @throws DateTimeException {@inheritDoc}
    566      * @throws ArithmeticException {@inheritDoc}
    567      */
    568     @Override
    569     public JapaneseDate minus(TemporalAmount amount) {
    570         return super.minus(amount);
    571     }
    572     //-----------------------------------------------------------------------
    573     /**
    574      * Returns a copy of this date with the year altered.
    575      * <p>
    576      * This method changes the year of the date.
    577      * If the month-day is invalid for the year, then the previous valid day
    578      * will be selected instead.
    579      * <p>
    580      * This instance is immutable and unaffected by this method call.
    581      *
    582      * @param era  the era to set in the result, not null
    583      * @param yearOfEra  the year-of-era to set in the returned date
    584      * @return a {@code JapaneseDate} based on this date with the requested year, never null
    585      * @throws DateTimeException if {@code year} is invalid
    586      */
    587     private JapaneseDate withYear(JapaneseEra era, int yearOfEra) {
    588         int year = JapaneseChronology.INSTANCE.prolepticYear(era, yearOfEra);
    589         return with(isoDate.withYear(year));
    590     }
    591 
    592     /**
    593      * Returns a copy of this date with the year-of-era altered.
    594      * <p>
    595      * This method changes the year-of-era of the date.
    596      * If the month-day is invalid for the year, then the previous valid day
    597      * will be selected instead.
    598      * <p>
    599      * This instance is immutable and unaffected by this method call.
    600      *
    601      * @param year  the year to set in the returned date
    602      * @return a {@code JapaneseDate} based on this date with the requested year-of-era, never null
    603      * @throws DateTimeException if {@code year} is invalid
    604      */
    605     private JapaneseDate withYear(int year) {
    606         return withYear(getEra(), year);
    607     }
    608 
    609     //-----------------------------------------------------------------------
    610     @Override
    611     JapaneseDate plusYears(long years) {
    612         return with(isoDate.plusYears(years));
    613     }
    614 
    615     @Override
    616     JapaneseDate plusMonths(long months) {
    617         return with(isoDate.plusMonths(months));
    618     }
    619 
    620     @Override
    621     JapaneseDate plusWeeks(long weeksToAdd) {
    622         return with(isoDate.plusWeeks(weeksToAdd));
    623     }
    624 
    625     @Override
    626     JapaneseDate plusDays(long days) {
    627         return with(isoDate.plusDays(days));
    628     }
    629 
    630     @Override
    631     public JapaneseDate plus(long amountToAdd, TemporalUnit unit) {
    632         return super.plus(amountToAdd, unit);
    633     }
    634 
    635     @Override
    636     public JapaneseDate minus(long amountToAdd, TemporalUnit unit) {
    637         return super.minus(amountToAdd, unit);
    638     }
    639 
    640     @Override
    641     JapaneseDate minusYears(long yearsToSubtract) {
    642         return super.minusYears(yearsToSubtract);
    643     }
    644 
    645     @Override
    646     JapaneseDate minusMonths(long monthsToSubtract) {
    647         return super.minusMonths(monthsToSubtract);
    648     }
    649 
    650     @Override
    651     JapaneseDate minusWeeks(long weeksToSubtract) {
    652         return super.minusWeeks(weeksToSubtract);
    653     }
    654 
    655     @Override
    656     JapaneseDate minusDays(long daysToSubtract) {
    657         return super.minusDays(daysToSubtract);
    658     }
    659 
    660     private JapaneseDate with(LocalDate newDate) {
    661         return (newDate.equals(isoDate) ? this : new JapaneseDate(newDate));
    662     }
    663 
    664     @Override        // for javadoc and covariant return type
    665     @SuppressWarnings("unchecked")
    666     public final ChronoLocalDateTime<JapaneseDate> atTime(LocalTime localTime) {
    667         return (ChronoLocalDateTime<JapaneseDate>)super.atTime(localTime);
    668     }
    669 
    670     @Override
    671     public ChronoPeriod until(ChronoLocalDate endDate) {
    672         Period period = isoDate.until(endDate);
    673         return getChronology().period(period.getYears(), period.getMonths(), period.getDays());
    674     }
    675 
    676     @Override  // override for performance
    677     public long toEpochDay() {
    678         return isoDate.toEpochDay();
    679     }
    680 
    681     //-------------------------------------------------------------------------
    682     /**
    683      * Compares this date to another date, including the chronology.
    684      * <p>
    685      * Compares this {@code JapaneseDate} with another ensuring that the date is the same.
    686      * <p>
    687      * Only objects of type {@code JapaneseDate} are compared, other types return false.
    688      * To compare the dates of two {@code TemporalAccessor} instances, including dates
    689      * in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator.
    690      *
    691      * @param obj  the object to check, null returns false
    692      * @return true if this is equal to the other date
    693      */
    694     @Override  // override for performance
    695     public boolean equals(Object obj) {
    696         if (this == obj) {
    697             return true;
    698         }
    699         if (obj instanceof JapaneseDate) {
    700             JapaneseDate otherDate = (JapaneseDate) obj;
    701             return this.isoDate.equals(otherDate.isoDate);
    702         }
    703         return false;
    704     }
    705 
    706     /**
    707      * A hash code for this date.
    708      *
    709      * @return a suitable hash code based only on the Chronology and the date
    710      */
    711     @Override  // override for performance
    712     public int hashCode() {
    713         return getChronology().getId().hashCode() ^ isoDate.hashCode();
    714     }
    715 
    716     //-----------------------------------------------------------------------
    717     /**
    718      * Defend against malicious streams.
    719      *
    720      * @param s the stream to read
    721      * @throws InvalidObjectException always
    722      */
    723     private void readObject(ObjectInputStream s) throws InvalidObjectException {
    724         throw new InvalidObjectException("Deserialization via serialization delegate");
    725     }
    726 
    727     /**
    728      * Writes the object using a
    729      * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
    730      * @serialData
    731      * <pre>
    732      *  out.writeByte(4);                 // identifies a JapaneseDate
    733      *  out.writeInt(get(YEAR));
    734      *  out.writeByte(get(MONTH_OF_YEAR));
    735      *  out.writeByte(get(DAY_OF_MONTH));
    736      * </pre>
    737      *
    738      * @return the instance of {@code Ser}, not null
    739      */
    740     private Object writeReplace() {
    741         return new Ser(Ser.JAPANESE_DATE_TYPE, this);
    742     }
    743 
    744     void writeExternal(DataOutput out) throws IOException {
    745         // JapaneseChronology is implicit in the JAPANESE_DATE_TYPE
    746         out.writeInt(get(YEAR));
    747         out.writeByte(get(MONTH_OF_YEAR));
    748         out.writeByte(get(DAY_OF_MONTH));
    749     }
    750 
    751     static JapaneseDate readExternal(DataInput in) throws IOException {
    752         int year = in.readInt();
    753         int month = in.readByte();
    754         int dayOfMonth = in.readByte();
    755         return JapaneseChronology.INSTANCE.date(year, month, dayOfMonth);
    756     }
    757 
    758 }
    759