1 /* 2 * Copyright (c) 2012, 2018, 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 */ now()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 */ now(ZoneId zone)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 */ now(Clock clock)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 */ of(JapaneseEra era, int yearOfEra, int month, int dayOfMonth)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 */ of(int prolepticYear, int month, int dayOfMonth)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 */ ofYearDay(JapaneseEra era, int yearOfEra, int dayOfYear)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 */ from(TemporalAccessor temporal)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 */ JapaneseDate(LocalDate isoDate)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 */ JapaneseDate(JapaneseEra era, int year, LocalDate isoDate)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 getChronology()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 getEra()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 lengthOfMonth()385 public int lengthOfMonth() { 386 return isoDate.lengthOfMonth(); 387 } 388 389 @Override lengthOfYear()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 isSupported(TemporalField field)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 return super.isSupported(field); 436 } 437 438 @Override range(TemporalField field)439 public ValueRange range(TemporalField field) { 440 if (field instanceof ChronoField) { 441 if (isSupported(field)) { 442 ChronoField f = (ChronoField) field; 443 switch (f) { 444 case DAY_OF_MONTH: return ValueRange.of(1, lengthOfMonth()); 445 case DAY_OF_YEAR: return ValueRange.of(1, lengthOfYear()); 446 case YEAR_OF_ERA: { 447 // Android-changed: use #createCalendar() to create calendar. 448 Calendar jcal = JapaneseChronology.createCalendar(); 449 jcal.set(Calendar.ERA, era.getValue() + JapaneseEra.ERA_OFFSET); 450 jcal.set(yearOfEra, isoDate.getMonthValue() - 1, isoDate.getDayOfMonth()); 451 return ValueRange.of(1, jcal.getActualMaximum(Calendar.YEAR)); 452 } 453 } 454 return getChronology().range(f); 455 } 456 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 457 } 458 return field.rangeRefinedBy(this); 459 } 460 461 @Override getLong(TemporalField field)462 public long getLong(TemporalField field) { 463 if (field instanceof ChronoField) { 464 // same as ISO: 465 // DAY_OF_WEEK, DAY_OF_MONTH, EPOCH_DAY, MONTH_OF_YEAR, PROLEPTIC_MONTH, YEAR 466 // 467 // calendar specific fields 468 // DAY_OF_YEAR, YEAR_OF_ERA, ERA 469 switch ((ChronoField) field) { 470 case ALIGNED_DAY_OF_WEEK_IN_MONTH: 471 case ALIGNED_DAY_OF_WEEK_IN_YEAR: 472 case ALIGNED_WEEK_OF_MONTH: 473 case ALIGNED_WEEK_OF_YEAR: 474 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 475 case YEAR_OF_ERA: 476 return yearOfEra; 477 case ERA: 478 return era.getValue(); 479 case DAY_OF_YEAR: 480 // Android-changed: use #createCalendar() to create calendar. 481 Calendar jcal = JapaneseChronology.createCalendar(); 482 jcal.set(Calendar.ERA, era.getValue() + JapaneseEra.ERA_OFFSET); 483 jcal.set(yearOfEra, isoDate.getMonthValue() - 1, isoDate.getDayOfMonth()); 484 return jcal.get(Calendar.DAY_OF_YEAR); 485 } 486 return isoDate.getLong(field); 487 } 488 return field.getFrom(this); 489 } 490 491 /** 492 * Returns a {@code LocalGregorianCalendar.Date} converted from the given {@code isoDate}. 493 * 494 * @param isoDate the local date, not null 495 * @return a {@code LocalGregorianCalendar.Date}, not null 496 */ toPrivateJapaneseDate(LocalDate isoDate)497 private static LocalGregorianCalendar.Date toPrivateJapaneseDate(LocalDate isoDate) { 498 LocalGregorianCalendar.Date jdate = JapaneseChronology.JCAL.newCalendarDate(null); 499 sun.util.calendar.Era sunEra = JapaneseEra.privateEraFrom(isoDate); 500 int year = isoDate.getYear(); 501 if (sunEra != null) { 502 year -= sunEra.getSinceDate().getYear() - 1; 503 } 504 jdate.setEra(sunEra).setYear(year).setMonth(isoDate.getMonthValue()).setDayOfMonth(isoDate.getDayOfMonth()); 505 JapaneseChronology.JCAL.normalize(jdate); 506 return jdate; 507 } 508 509 //----------------------------------------------------------------------- 510 @Override with(TemporalField field, long newValue)511 public JapaneseDate with(TemporalField field, long newValue) { 512 if (field instanceof ChronoField) { 513 ChronoField f = (ChronoField) field; 514 if (getLong(f) == newValue) { // getLong() validates for supported fields 515 return this; 516 } 517 switch (f) { 518 case YEAR_OF_ERA: 519 case YEAR: 520 case ERA: { 521 int nvalue = getChronology().range(f).checkValidIntValue(newValue, f); 522 switch (f) { 523 case YEAR_OF_ERA: 524 return this.withYear(nvalue); 525 case YEAR: 526 return with(isoDate.withYear(nvalue)); 527 case ERA: { 528 return this.withYear(JapaneseEra.of(nvalue), yearOfEra); 529 } 530 } 531 } 532 } 533 // YEAR, PROLEPTIC_MONTH and others are same as ISO 534 return with(isoDate.with(field, newValue)); 535 } 536 return super.with(field, newValue); 537 } 538 539 /** 540 * {@inheritDoc} 541 * @throws DateTimeException {@inheritDoc} 542 * @throws ArithmeticException {@inheritDoc} 543 */ 544 @Override with(TemporalAdjuster adjuster)545 public JapaneseDate with(TemporalAdjuster adjuster) { 546 return super.with(adjuster); 547 } 548 549 /** 550 * {@inheritDoc} 551 * @throws DateTimeException {@inheritDoc} 552 * @throws ArithmeticException {@inheritDoc} 553 */ 554 @Override plus(TemporalAmount amount)555 public JapaneseDate plus(TemporalAmount amount) { 556 return super.plus(amount); 557 } 558 559 /** 560 * {@inheritDoc} 561 * @throws DateTimeException {@inheritDoc} 562 * @throws ArithmeticException {@inheritDoc} 563 */ 564 @Override minus(TemporalAmount amount)565 public JapaneseDate minus(TemporalAmount amount) { 566 return super.minus(amount); 567 } 568 //----------------------------------------------------------------------- 569 /** 570 * Returns a copy of this date with the year altered. 571 * <p> 572 * This method changes the year of the date. 573 * If the month-day is invalid for the year, then the previous valid day 574 * will be selected instead. 575 * <p> 576 * This instance is immutable and unaffected by this method call. 577 * 578 * @param era the era to set in the result, not null 579 * @param yearOfEra the year-of-era to set in the returned date 580 * @return a {@code JapaneseDate} based on this date with the requested year, never null 581 * @throws DateTimeException if {@code year} is invalid 582 */ withYear(JapaneseEra era, int yearOfEra)583 private JapaneseDate withYear(JapaneseEra era, int yearOfEra) { 584 int year = JapaneseChronology.INSTANCE.prolepticYear(era, yearOfEra); 585 return with(isoDate.withYear(year)); 586 } 587 588 /** 589 * Returns a copy of this date with the year-of-era altered. 590 * <p> 591 * This method changes the year-of-era of the date. 592 * If the month-day is invalid for the year, then the previous valid day 593 * will be selected instead. 594 * <p> 595 * This instance is immutable and unaffected by this method call. 596 * 597 * @param year the year to set in the returned date 598 * @return a {@code JapaneseDate} based on this date with the requested year-of-era, never null 599 * @throws DateTimeException if {@code year} is invalid 600 */ withYear(int year)601 private JapaneseDate withYear(int year) { 602 return withYear(getEra(), year); 603 } 604 605 //----------------------------------------------------------------------- 606 @Override plusYears(long years)607 JapaneseDate plusYears(long years) { 608 return with(isoDate.plusYears(years)); 609 } 610 611 @Override plusMonths(long months)612 JapaneseDate plusMonths(long months) { 613 return with(isoDate.plusMonths(months)); 614 } 615 616 @Override plusWeeks(long weeksToAdd)617 JapaneseDate plusWeeks(long weeksToAdd) { 618 return with(isoDate.plusWeeks(weeksToAdd)); 619 } 620 621 @Override plusDays(long days)622 JapaneseDate plusDays(long days) { 623 return with(isoDate.plusDays(days)); 624 } 625 626 @Override plus(long amountToAdd, TemporalUnit unit)627 public JapaneseDate plus(long amountToAdd, TemporalUnit unit) { 628 return super.plus(amountToAdd, unit); 629 } 630 631 @Override minus(long amountToAdd, TemporalUnit unit)632 public JapaneseDate minus(long amountToAdd, TemporalUnit unit) { 633 return super.minus(amountToAdd, unit); 634 } 635 636 @Override minusYears(long yearsToSubtract)637 JapaneseDate minusYears(long yearsToSubtract) { 638 return super.minusYears(yearsToSubtract); 639 } 640 641 @Override minusMonths(long monthsToSubtract)642 JapaneseDate minusMonths(long monthsToSubtract) { 643 return super.minusMonths(monthsToSubtract); 644 } 645 646 @Override minusWeeks(long weeksToSubtract)647 JapaneseDate minusWeeks(long weeksToSubtract) { 648 return super.minusWeeks(weeksToSubtract); 649 } 650 651 @Override minusDays(long daysToSubtract)652 JapaneseDate minusDays(long daysToSubtract) { 653 return super.minusDays(daysToSubtract); 654 } 655 with(LocalDate newDate)656 private JapaneseDate with(LocalDate newDate) { 657 return (newDate.equals(isoDate) ? this : new JapaneseDate(newDate)); 658 } 659 660 @Override // for javadoc and covariant return type 661 @SuppressWarnings("unchecked") atTime(LocalTime localTime)662 public final ChronoLocalDateTime<JapaneseDate> atTime(LocalTime localTime) { 663 return (ChronoLocalDateTime<JapaneseDate>)super.atTime(localTime); 664 } 665 666 @Override until(ChronoLocalDate endDate)667 public ChronoPeriod until(ChronoLocalDate endDate) { 668 Period period = isoDate.until(endDate); 669 return getChronology().period(period.getYears(), period.getMonths(), period.getDays()); 670 } 671 672 @Override // override for performance toEpochDay()673 public long toEpochDay() { 674 return isoDate.toEpochDay(); 675 } 676 677 //------------------------------------------------------------------------- 678 /** 679 * Compares this date to another date, including the chronology. 680 * <p> 681 * Compares this {@code JapaneseDate} with another ensuring that the date is the same. 682 * <p> 683 * Only objects of type {@code JapaneseDate} are compared, other types return false. 684 * To compare the dates of two {@code TemporalAccessor} instances, including dates 685 * in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator. 686 * 687 * @param obj the object to check, null returns false 688 * @return true if this is equal to the other date 689 */ 690 @Override // override for performance equals(Object obj)691 public boolean equals(Object obj) { 692 if (this == obj) { 693 return true; 694 } 695 if (obj instanceof JapaneseDate) { 696 JapaneseDate otherDate = (JapaneseDate) obj; 697 return this.isoDate.equals(otherDate.isoDate); 698 } 699 return false; 700 } 701 702 /** 703 * A hash code for this date. 704 * 705 * @return a suitable hash code based only on the Chronology and the date 706 */ 707 @Override // override for performance hashCode()708 public int hashCode() { 709 return getChronology().getId().hashCode() ^ isoDate.hashCode(); 710 } 711 712 //----------------------------------------------------------------------- 713 /** 714 * Defend against malicious streams. 715 * 716 * @param s the stream to read 717 * @throws InvalidObjectException always 718 */ readObject(ObjectInputStream s)719 private void readObject(ObjectInputStream s) throws InvalidObjectException { 720 throw new InvalidObjectException("Deserialization via serialization delegate"); 721 } 722 723 /** 724 * Writes the object using a 725 * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>. 726 * @serialData 727 * <pre> 728 * out.writeByte(4); // identifies a JapaneseDate 729 * out.writeInt(get(YEAR)); 730 * out.writeByte(get(MONTH_OF_YEAR)); 731 * out.writeByte(get(DAY_OF_MONTH)); 732 * </pre> 733 * 734 * @return the instance of {@code Ser}, not null 735 */ writeReplace()736 private Object writeReplace() { 737 return new Ser(Ser.JAPANESE_DATE_TYPE, this); 738 } 739 writeExternal(DataOutput out)740 void writeExternal(DataOutput out) throws IOException { 741 // JapaneseChronology is implicit in the JAPANESE_DATE_TYPE 742 out.writeInt(get(YEAR)); 743 out.writeByte(get(MONTH_OF_YEAR)); 744 out.writeByte(get(DAY_OF_MONTH)); 745 } 746 readExternal(DataInput in)747 static JapaneseDate readExternal(DataInput in) throws IOException { 748 int year = in.readInt(); 749 int month = in.readByte(); 750 int dayOfMonth = in.readByte(); 751 return JapaneseChronology.INSTANCE.date(year, month, dayOfMonth); 752 } 753 754 } 755