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  * 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.DAY_OF_MONTH;
  60 import static java.time.temporal.ChronoField.DAY_OF_YEAR;
  61 import static java.time.temporal.ChronoField.ERA;
  62 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
  63 import static java.time.temporal.ChronoField.YEAR;
  64 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
  65 import static java.time.temporal.ChronoUnit.DAYS;
  66 import static java.time.temporal.ChronoUnit.MONTHS;
  67 
  68 import java.io.InvalidObjectException;
  69 import java.io.ObjectInputStream;
  70 import java.io.Serializable;
  71 import java.time.Clock;
  72 import java.time.DateTimeException;
  73 import java.time.Instant;
  74 import java.time.LocalDate;
  75 import java.time.Year;
  76 import java.time.ZoneId;
  77 import java.time.format.ResolverStyle;
  78 import java.time.temporal.ChronoField;
  79 import java.time.temporal.TemporalAccessor;
  80 import java.time.temporal.TemporalAdjusters;
  81 import java.time.temporal.TemporalField;
  82 import java.time.temporal.UnsupportedTemporalTypeException;
  83 import java.time.temporal.ValueRange;
  84 import java.util.Arrays;
  85 import java.util.Calendar;
  86 import java.util.List;
  87 import java.util.Locale;
  88 import java.util.Map;
  89 
  90 import sun.util.calendar.CalendarSystem;
  91 import sun.util.calendar.LocalGregorianCalendar;
  92 
  93 /**
  94  * The Japanese Imperial calendar system.
  95  * <p>
  96  * This chronology defines the rules of the Japanese Imperial calendar system.
  97  * This calendar system is primarily used in Japan.
  98  * The Japanese Imperial calendar system is the same as the ISO calendar system
  99  * apart from the era-based year numbering.
 100  * <p>
 101  * Japan introduced the Gregorian calendar starting with Meiji 6.
 102  * Only Meiji and later eras are supported;
 103  * dates before Meiji 6, January 1 are not supported.
 104  * <p>
 105  * The supported {@code ChronoField} instances are:
 106  * <ul>
 107  * <li>{@code DAY_OF_WEEK}
 108  * <li>{@code DAY_OF_MONTH}
 109  * <li>{@code DAY_OF_YEAR}
 110  * <li>{@code EPOCH_DAY}
 111  * <li>{@code MONTH_OF_YEAR}
 112  * <li>{@code PROLEPTIC_MONTH}
 113  * <li>{@code YEAR_OF_ERA}
 114  * <li>{@code YEAR}
 115  * <li>{@code ERA}
 116  * </ul>
 117  *
 118  * @implSpec
 119  * This class is immutable and thread-safe.
 120  *
 121  * @since 1.8
 122  */
 123 public final class JapaneseChronology extends AbstractChronology implements Serializable {
 124 
 125     static final LocalGregorianCalendar JCAL =
 126         (LocalGregorianCalendar) CalendarSystem.forName("japanese");
 127 
 128     // Locale for creating a JapaneseImpericalCalendar.
 129     static final Locale LOCALE = Locale.forLanguageTag("ja-JP-u-ca-japanese");
 130 
 131     /**
 132      * Singleton instance for Japanese chronology.
 133      */
 134     public static final JapaneseChronology INSTANCE = new JapaneseChronology();
 135 
 136     /**
 137      * Serialization version.
 138      */
 139     private static final long serialVersionUID = 459996390165777884L;
 140 
 141     //-----------------------------------------------------------------------
 142     /**
 143      * Restricted constructor.
 144      */
 145     private JapaneseChronology() {
 146     }
 147 
 148     //-----------------------------------------------------------------------
 149     /**
 150      * Gets the ID of the chronology - 'Japanese'.
 151      * <p>
 152      * The ID uniquely identifies the {@code Chronology}.
 153      * It can be used to lookup the {@code Chronology} using {@link Chronology#of(String)}.
 154      *
 155      * @return the chronology ID - 'Japanese'
 156      * @see #getCalendarType()
 157      */
 158     @Override
 159     public String getId() {
 160         return "Japanese";
 161     }
 162 
 163     /**
 164      * Gets the calendar type of the underlying calendar system - 'japanese'.
 165      * <p>
 166      * The calendar type is an identifier defined by the
 167      * <em>Unicode Locale Data Markup Language (LDML)</em> specification.
 168      * It can be used to lookup the {@code Chronology} using {@link Chronology#of(String)}.
 169      * It can also be used as part of a locale, accessible via
 170      * {@link Locale#getUnicodeLocaleType(String)} with the key 'ca'.
 171      *
 172      * @return the calendar system type - 'japanese'
 173      * @see #getId()
 174      */
 175     @Override
 176     public String getCalendarType() {
 177         return "japanese";
 178     }
 179 
 180     //-----------------------------------------------------------------------
 181     /**
 182      * Obtains a local date in Japanese calendar system from the
 183      * era, year-of-era, month-of-year and day-of-month fields.
 184      * <p>
 185      * The Japanese month and day-of-month are the same as those in the
 186      * ISO calendar system. They are not reset when the era changes.
 187      * For example:
 188      * <pre>
 189      *  6th Jan Showa 64 = ISO 1989-01-06
 190      *  7th Jan Showa 64 = ISO 1989-01-07
 191      *  8th Jan Heisei 1 = ISO 1989-01-08
 192      *  9th Jan Heisei 1 = ISO 1989-01-09
 193      * </pre>
 194      *
 195      * @param era  the Japanese era, not null
 196      * @param yearOfEra  the year-of-era
 197      * @param month  the month-of-year
 198      * @param dayOfMonth  the day-of-month
 199      * @return the Japanese local date, not null
 200      * @throws DateTimeException if unable to create the date
 201      * @throws ClassCastException if the {@code era} is not a {@code JapaneseEra}
 202      */
 203     @Override
 204     public JapaneseDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
 205         if (era instanceof JapaneseEra == false) {
 206             throw new ClassCastException("Era must be JapaneseEra");
 207         }
 208         return JapaneseDate.of((JapaneseEra) era, yearOfEra, month, dayOfMonth);
 209     }
 210 
 211     /**
 212      * Obtains a local date in Japanese calendar system from the
 213      * proleptic-year, month-of-year and day-of-month fields.
 214      * <p>
 215      * The Japanese proleptic year, month and day-of-month are the same as those
 216      * in the ISO calendar system. They are not reset when the era changes.
 217      *
 218      * @param prolepticYear  the proleptic-year
 219      * @param month  the month-of-year
 220      * @param dayOfMonth  the day-of-month
 221      * @return the Japanese local date, not null
 222      * @throws DateTimeException if unable to create the date
 223      */
 224     @Override
 225     public JapaneseDate date(int prolepticYear, int month, int dayOfMonth) {
 226         return new JapaneseDate(LocalDate.of(prolepticYear, month, dayOfMonth));
 227     }
 228 
 229     /**
 230      * Obtains a local date in Japanese calendar system from the
 231      * era, year-of-era and day-of-year fields.
 232      * <p>
 233      * The day-of-year in this factory is expressed relative to the start of the year-of-era.
 234      * This definition changes the normal meaning of day-of-year only in those years
 235      * where the year-of-era is reset to one due to a change in the era.
 236      * For example:
 237      * <pre>
 238      *  6th Jan Showa 64 = day-of-year 6
 239      *  7th Jan Showa 64 = day-of-year 7
 240      *  8th Jan Heisei 1 = day-of-year 1
 241      *  9th Jan Heisei 1 = day-of-year 2
 242      * </pre>
 243      *
 244      * @param era  the Japanese era, not null
 245      * @param yearOfEra  the year-of-era
 246      * @param dayOfYear  the day-of-year
 247      * @return the Japanese local date, not null
 248      * @throws DateTimeException if unable to create the date
 249      * @throws ClassCastException if the {@code era} is not a {@code JapaneseEra}
 250      */
 251     @Override
 252     public JapaneseDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
 253         return JapaneseDate.ofYearDay((JapaneseEra) era, yearOfEra, dayOfYear);
 254     }
 255 
 256     /**
 257      * Obtains a local date in Japanese calendar system from the
 258      * proleptic-year and day-of-year fields.
 259      * <p>
 260      * The day-of-year in this factory is expressed relative to the start of the proleptic year.
 261      * The Japanese proleptic year and day-of-year are the same as those in the ISO calendar system.
 262      * They are not reset when the era changes.
 263      *
 264      * @param prolepticYear  the proleptic-year
 265      * @param dayOfYear  the day-of-year
 266      * @return the Japanese local date, not null
 267      * @throws DateTimeException if unable to create the date
 268      */
 269     @Override
 270     public JapaneseDate dateYearDay(int prolepticYear, int dayOfYear) {
 271         return new JapaneseDate(LocalDate.ofYearDay(prolepticYear, dayOfYear));
 272     }
 273 
 274     /**
 275      * Obtains a local date in the Japanese calendar system from the epoch-day.
 276      *
 277      * @param epochDay  the epoch day
 278      * @return the Japanese local date, not null
 279      * @throws DateTimeException if unable to create the date
 280      */
 281     @Override  // override with covariant return type
 282     public JapaneseDate dateEpochDay(long epochDay) {
 283         return new JapaneseDate(LocalDate.ofEpochDay(epochDay));
 284     }
 285 
 286     @Override
 287     public JapaneseDate dateNow() {
 288         return dateNow(Clock.systemDefaultZone());
 289     }
 290 
 291     @Override
 292     public JapaneseDate dateNow(ZoneId zone) {
 293         return dateNow(Clock.system(zone));
 294     }
 295 
 296     @Override
 297     public JapaneseDate dateNow(Clock clock) {
 298         return date(LocalDate.now(clock));
 299     }
 300 
 301     @Override
 302     public JapaneseDate date(TemporalAccessor temporal) {
 303         if (temporal instanceof JapaneseDate) {
 304             return (JapaneseDate) temporal;
 305         }
 306         return new JapaneseDate(LocalDate.from(temporal));
 307     }
 308 
 309     @Override
 310     @SuppressWarnings("unchecked")
 311     public ChronoLocalDateTime<JapaneseDate> localDateTime(TemporalAccessor temporal) {
 312         return (ChronoLocalDateTime<JapaneseDate>)super.localDateTime(temporal);
 313     }
 314 
 315     @Override
 316     @SuppressWarnings("unchecked")
 317     public ChronoZonedDateTime<JapaneseDate> zonedDateTime(TemporalAccessor temporal) {
 318         return (ChronoZonedDateTime<JapaneseDate>)super.zonedDateTime(temporal);
 319     }
 320 
 321     @Override
 322     @SuppressWarnings("unchecked")
 323     public ChronoZonedDateTime<JapaneseDate> zonedDateTime(Instant instant, ZoneId zone) {
 324         return (ChronoZonedDateTime<JapaneseDate>)super.zonedDateTime(instant, zone);
 325     }
 326 
 327     //-----------------------------------------------------------------------
 328     /**
 329      * Checks if the specified year is a leap year.
 330      * <p>
 331      * Japanese calendar leap years occur exactly in line with ISO leap years.
 332      * This method does not validate the year passed in, and only has a
 333      * well-defined result for years in the supported range.
 334      *
 335      * @param prolepticYear  the proleptic-year to check, not validated for range
 336      * @return true if the year is a leap year
 337      */
 338     @Override
 339     public boolean isLeapYear(long prolepticYear) {
 340         return IsoChronology.INSTANCE.isLeapYear(prolepticYear);
 341     }
 342 
 343     @Override
 344     public int prolepticYear(Era era, int yearOfEra) {
 345         if (era instanceof JapaneseEra == false) {
 346             throw new ClassCastException("Era must be JapaneseEra");
 347         }
 348 
 349         JapaneseEra jera = (JapaneseEra) era;
 350         int gregorianYear = jera.getPrivateEra().getSinceDate().getYear() + yearOfEra - 1;
 351         if (yearOfEra == 1) {
 352             return gregorianYear;
 353         }
 354         if (gregorianYear >= Year.MIN_VALUE && gregorianYear <= Year.MAX_VALUE) {
 355             LocalGregorianCalendar.Date jdate = JCAL.newCalendarDate(null);
 356             jdate.setEra(jera.getPrivateEra()).setDate(yearOfEra, 1, 1);
 357             if (JapaneseChronology.JCAL.validate(jdate)) {
 358                 return gregorianYear;
 359             }
 360         }
 361         throw new DateTimeException("Invalid yearOfEra value");
 362     }
 363 
 364     /**
 365      * Returns the calendar system era object from the given numeric value.
 366      *
 367      * See the description of each Era for the numeric values of:
 368      * {@link JapaneseEra#HEISEI}, {@link JapaneseEra#SHOWA},{@link JapaneseEra#TAISHO},
 369      * {@link JapaneseEra#MEIJI}), only Meiji and later eras are supported.
 370      *
 371      * @param eraValue  the era value
 372      * @return the Japanese {@code Era} for the given numeric era value
 373      * @throws DateTimeException if {@code eraValue} is invalid
 374      */
 375     @Override
 376     public JapaneseEra eraOf(int eraValue) {
 377         return JapaneseEra.of(eraValue);
 378     }
 379 
 380     @Override
 381     public List<Era> eras() {
 382         return Arrays.<Era>asList(JapaneseEra.values());
 383     }
 384 
 385     JapaneseEra getCurrentEra() {
 386         // Assume that the last JapaneseEra is the current one.
 387         JapaneseEra[] eras = JapaneseEra.values();
 388         return eras[eras.length - 1];
 389     }
 390 
 391     //-----------------------------------------------------------------------
 392     @Override
 393     public ValueRange range(ChronoField field) {
 394         switch (field) {
 395             case ALIGNED_DAY_OF_WEEK_IN_MONTH:
 396             case ALIGNED_DAY_OF_WEEK_IN_YEAR:
 397             case ALIGNED_WEEK_OF_MONTH:
 398             case ALIGNED_WEEK_OF_YEAR:
 399                 throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
 400             case YEAR_OF_ERA: {
 401                 Calendar jcal = Calendar.getInstance(LOCALE);
 402                 int startYear = getCurrentEra().getPrivateEra().getSinceDate().getYear();
 403                 return ValueRange.of(1, jcal.getGreatestMinimum(Calendar.YEAR),
 404                         jcal.getLeastMaximum(Calendar.YEAR) + 1, // +1 due to the different definitions
 405                         Year.MAX_VALUE - startYear);
 406             }
 407             case DAY_OF_YEAR: {
 408                 Calendar jcal = Calendar.getInstance(LOCALE);
 409                 int fieldIndex = Calendar.DAY_OF_YEAR;
 410                 return ValueRange.of(jcal.getMinimum(fieldIndex), jcal.getGreatestMinimum(fieldIndex),
 411                         jcal.getLeastMaximum(fieldIndex), jcal.getMaximum(fieldIndex));
 412             }
 413             case YEAR:
 414                 return ValueRange.of(JapaneseDate.MEIJI_6_ISODATE.getYear(), Year.MAX_VALUE);
 415             case ERA:
 416                 return ValueRange.of(JapaneseEra.MEIJI.getValue(), getCurrentEra().getValue());
 417             default:
 418                 return field.range();
 419         }
 420     }
 421 
 422     //-----------------------------------------------------------------------
 423     @Override  // override for return type
 424     public JapaneseDate resolveDate(Map <TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
 425         return (JapaneseDate) super.resolveDate(fieldValues, resolverStyle);
 426     }
 427 
 428     @Override  // override for special Japanese behavior
 429     ChronoLocalDate resolveYearOfEra(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
 430         // validate era and year-of-era
 431         Long eraLong = fieldValues.get(ERA);
 432         JapaneseEra era = null;
 433         if (eraLong != null) {
 434             era = eraOf(range(ERA).checkValidIntValue(eraLong, ERA));  // always validated
 435         }
 436         Long yoeLong = fieldValues.get(YEAR_OF_ERA);
 437         int yoe = 0;
 438         if (yoeLong != null) {
 439             yoe = range(YEAR_OF_ERA).checkValidIntValue(yoeLong, YEAR_OF_ERA);  // always validated
 440         }
 441         // if only year-of-era and no year then invent era unless strict
 442         if (era == null && yoeLong != null && fieldValues.containsKey(YEAR) == false && resolverStyle != ResolverStyle.STRICT) {
 443             era = JapaneseEra.values()[JapaneseEra.values().length - 1];
 444         }
 445         // if both present, then try to create date
 446         if (yoeLong != null && era != null) {
 447             if (fieldValues.containsKey(MONTH_OF_YEAR)) {
 448                 if (fieldValues.containsKey(DAY_OF_MONTH)) {
 449                     return resolveYMD(era, yoe, fieldValues, resolverStyle);
 450                 }
 451             }
 452             if (fieldValues.containsKey(DAY_OF_YEAR)) {
 453                 return resolveYD(era, yoe, fieldValues, resolverStyle);
 454             }
 455         }
 456         return null;
 457     }
 458 
 459     private int prolepticYearLenient(JapaneseEra era, int yearOfEra) {
 460         return era.getPrivateEra().getSinceDate().getYear() + yearOfEra - 1;
 461     }
 462 
 463      private ChronoLocalDate resolveYMD(JapaneseEra era, int yoe, Map<TemporalField,Long> fieldValues, ResolverStyle resolverStyle) {
 464          fieldValues.remove(ERA);
 465          fieldValues.remove(YEAR_OF_ERA);
 466          if (resolverStyle == ResolverStyle.LENIENT) {
 467              int y = prolepticYearLenient(era, yoe);
 468              long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
 469              long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
 470              return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
 471          }
 472          int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
 473          int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
 474          if (resolverStyle == ResolverStyle.SMART) {  // previous valid
 475              if (yoe < 1) {
 476                  throw new DateTimeException("Invalid YearOfEra: " + yoe);
 477              }
 478              int y = prolepticYearLenient(era, yoe);
 479              JapaneseDate result;
 480              try {
 481                  result = date(y, moy, dom);
 482              } catch (DateTimeException ex) {
 483                  result = date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
 484              }
 485              // handle the era being changed
 486              // only allow if the new date is in the same Jan-Dec as the era change
 487              // determine by ensuring either original yoe or result yoe is 1
 488              if (result.getEra() != era && result.get(YEAR_OF_ERA) > 1 && yoe > 1) {
 489                  throw new DateTimeException("Invalid YearOfEra for Era: " + era + " " + yoe);
 490              }
 491              return result;
 492          }
 493          return date(era, yoe, moy, dom);
 494      }
 495 
 496     private ChronoLocalDate resolveYD(JapaneseEra era, int yoe, Map <TemporalField,Long> fieldValues, ResolverStyle resolverStyle) {
 497         fieldValues.remove(ERA);
 498         fieldValues.remove(YEAR_OF_ERA);
 499         if (resolverStyle == ResolverStyle.LENIENT) {
 500             int y = prolepticYearLenient(era, yoe);
 501             long days = Math.subtractExact(fieldValues.remove(DAY_OF_YEAR), 1);
 502             return dateYearDay(y, 1).plus(days, DAYS);
 503         }
 504         int doy = range(DAY_OF_YEAR).checkValidIntValue(fieldValues.remove(DAY_OF_YEAR), DAY_OF_YEAR);
 505         return dateYearDay(era, yoe, doy);  // smart is same as strict
 506     }
 507 
 508     //-----------------------------------------------------------------------
 509     /**
 510      * Writes the Chronology using a
 511      * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
 512      * @serialData
 513      * <pre>
 514      *  out.writeByte(1);     // identifies a Chronology
 515      *  out.writeUTF(getId());
 516      * </pre>
 517      *
 518      * @return the instance of {@code Ser}, not null
 519      */
 520     @Override
 521     Object writeReplace() {
 522         return super.writeReplace();
 523     }
 524 
 525     /**
 526      * Defend against malicious streams.
 527      *
 528      * @param s the stream to read
 529      * @throws InvalidObjectException always
 530      */
 531     private void readObject(ObjectInputStream s) throws InvalidObjectException {
 532         throw new InvalidObjectException("Deserialization via serialization delegate");
 533     }
 534 }