1 /* 2 * Copyright (c) 2012, 2023, 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 /** 95 * A date in the Japanese Imperial calendar system. 96 * <p> 97 * This date operates using the {@linkplain JapaneseChronology Japanese Imperial calendar}. 98 * This calendar system is primarily used in Japan. 99 * <p> 100 * The Japanese Imperial calendar system is the same as the ISO calendar system 101 * apart from the era-based year numbering. The proleptic-year is defined to be 102 * equal to the ISO proleptic-year. 103 * <p> 104 * Japan introduced the Gregorian calendar starting with Meiji 6. 105 * Only Meiji and later eras are supported; 106 * dates before Meiji 6, January 1 are not supported. 107 * <p> 108 * For example, the Japanese year "Heisei 24" corresponds to ISO year "2012".<br> 109 * Calling {@code japaneseDate.get(YEAR_OF_ERA)} will return 24.<br> 110 * Calling {@code japaneseDate.get(YEAR)} will return 2012.<br> 111 * Calling {@code japaneseDate.get(ERA)} will return 2, corresponding to 112 * {@code JapaneseChronology.ERA_HEISEI}.<br> 113 * <p> 114 * This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a> 115 * class; programmers should treat instances that are 116 * {@linkplain #equals(Object) equal} as interchangeable and should not 117 * use instances for synchronization, or unpredictable behavior may 118 * occur. For example, in a future release, synchronization may fail. 119 * The {@code equals} method should be used for comparisons. 120 * 121 * @implSpec 122 * This class is immutable and thread-safe. 123 * 124 * @since 1.8 125 */ 126 @jdk.internal.ValueBased 127 public final class JapaneseDate 128 extends ChronoLocalDateImpl<JapaneseDate> 129 implements ChronoLocalDate, Serializable { 130 131 /** 132 * Serialization version. 133 */ 134 @java.io.Serial 135 private static final long serialVersionUID = -305327627230580483L; 136 137 /** 138 * The underlying ISO local date. 139 */ 140 private final transient LocalDate isoDate; 141 /** 142 * The JapaneseEra of this date. 143 */ 144 private final transient JapaneseEra era; 145 /** 146 * The Japanese imperial calendar year of this date. 147 */ 148 private final transient int yearOfEra; 149 150 /** 151 * The first day supported by the JapaneseChronology is Meiji 6, January 1st. 152 */ 153 static final LocalDate MEIJI_6_ISODATE = LocalDate.of(1873, 1, 1); 154 155 //----------------------------------------------------------------------- 156 /** 157 * Obtains the current {@code JapaneseDate} from the system clock in the default time-zone. 158 * <p> 159 * This will query the {@link Clock#systemDefaultZone() system clock} in the default 160 * time-zone to obtain the current date. 161 * <p> 162 * Using this method will prevent the ability to use an alternate clock for testing 163 * because the clock is hard-coded. 164 * 165 * @return the current date using the system clock and default time-zone, not null 166 */ 167 public static JapaneseDate now() { 168 return now(Clock.systemDefaultZone()); 169 } 170 171 /** 172 * Obtains the current {@code JapaneseDate} from the system clock in the specified time-zone. 173 * <p> 174 * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date. 175 * Specifying the time-zone avoids dependence on the default time-zone. 176 * <p> 177 * Using this method will prevent the ability to use an alternate clock for testing 178 * because the clock is hard-coded. 179 * 180 * @param zone the zone ID to use, not null 181 * @return the current date using the system clock, not null 182 */ 183 public static JapaneseDate now(ZoneId zone) { 184 return now(Clock.system(zone)); 185 } 186 187 /** 188 * Obtains the current {@code JapaneseDate} from the specified clock. 189 * <p> 190 * This will query the specified clock to obtain the current date - today. 191 * Using this method allows the use of an alternate clock for testing. 192 * The alternate clock may be introduced using {@linkplain Clock dependency injection}. 193 * 194 * @param clock the clock to use, not null 195 * @return the current date, not null 196 * @throws DateTimeException if the current date cannot be obtained 197 */ 198 public static JapaneseDate now(Clock clock) { 199 return new JapaneseDate(LocalDate.now(clock)); 200 } 201 202 /** 203 * Obtains a {@code JapaneseDate} representing a date in the Japanese calendar 204 * system from the era, year-of-era, month-of-year and day-of-month fields. 205 * <p> 206 * This returns a {@code JapaneseDate} with the specified fields. 207 * The day must be valid for the year and month, otherwise an exception will be thrown. 208 * <p> 209 * The Japanese month and day-of-month are the same as those in the 210 * ISO calendar system. They are not reset when the era changes. 211 * For example: 212 * <pre> 213 * 6th Jan Showa 64 = ISO 1989-01-06 214 * 7th Jan Showa 64 = ISO 1989-01-07 215 * 8th Jan Heisei 1 = ISO 1989-01-08 216 * 9th Jan Heisei 1 = ISO 1989-01-09 217 * </pre> 218 * 219 * @param era the Japanese era, not null 220 * @param yearOfEra the Japanese year-of-era 221 * @param month the Japanese month-of-year, from 1 to 12 222 * @param dayOfMonth the Japanese day-of-month, from 1 to 31 223 * @return the date in Japanese calendar system, not null 224 * @throws DateTimeException if the value of any field is out of range, 225 * or if the day-of-month is invalid for the month-year, 226 * or if the date is not a Japanese era 227 */ 228 public static JapaneseDate of(JapaneseEra era, int yearOfEra, int month, int dayOfMonth) { 229 Objects.requireNonNull(era, "era"); 230 LocalGregorianCalendar.Date jdate = JapaneseChronology.JCAL.newCalendarDate(null); 231 jdate.setEra(era.getPrivateEra()).setDate(yearOfEra, month, dayOfMonth); 232 if (!JapaneseChronology.JCAL.validate(jdate)) { 233 throw new DateTimeException("year, month, and day not valid for Era"); 234 } 235 LocalDate date = LocalDate.of(jdate.getNormalizedYear(), month, dayOfMonth); 236 return new JapaneseDate(era, yearOfEra, date); 237 } 238 239 /** 240 * Obtains a {@code JapaneseDate} representing a date in the Japanese calendar 241 * system from the proleptic-year, month-of-year and day-of-month fields. 242 * <p> 243 * This returns a {@code JapaneseDate} with the specified fields. 244 * The day must be valid for the year and month, otherwise an exception will be thrown. 245 * <p> 246 * The Japanese proleptic year, month and day-of-month are the same as those 247 * in the ISO calendar system. They are not reset when the era changes. 248 * 249 * @param prolepticYear the Japanese proleptic-year 250 * @param month the Japanese month-of-year, from 1 to 12 251 * @param dayOfMonth the Japanese day-of-month, from 1 to 31 252 * @return the date in Japanese calendar system, not null 253 * @throws DateTimeException if the value of any field is out of range, 254 * or if the day-of-month is invalid for the month-year 255 */ 256 public static JapaneseDate of(int prolepticYear, int month, int dayOfMonth) { 257 return new JapaneseDate(LocalDate.of(prolepticYear, month, dayOfMonth)); 258 } 259 260 /** 261 * Obtains a {@code JapaneseDate} representing a date in the Japanese calendar 262 * system from the era, year-of-era and day-of-year fields. 263 * <p> 264 * This returns a {@code JapaneseDate} with the specified fields. 265 * The day must be valid for the year, otherwise an exception will be thrown. 266 * <p> 267 * The day-of-year in this factory is expressed relative to the start of the year-of-era. 268 * This definition changes the normal meaning of day-of-year only in those years 269 * where the year-of-era is reset to one due to a change in the era. 270 * For example: 271 * <pre> 272 * 6th Jan Showa 64 = day-of-year 6 273 * 7th Jan Showa 64 = day-of-year 7 274 * 8th Jan Heisei 1 = day-of-year 1 275 * 9th Jan Heisei 1 = day-of-year 2 276 * </pre> 277 * 278 * @param era the Japanese era, not null 279 * @param yearOfEra the Japanese year-of-era 280 * @param dayOfYear the chronology day-of-year, from 1 to 366 281 * @return the date in Japanese calendar system, not null 282 * @throws DateTimeException if the value of any field is out of range, 283 * or if the day-of-year is invalid for the year 284 */ 285 static JapaneseDate ofYearDay(JapaneseEra era, int yearOfEra, int dayOfYear) { 286 Objects.requireNonNull(era, "era"); 287 CalendarDate firstDay = era.getPrivateEra().getSinceDate(); 288 LocalGregorianCalendar.Date jdate = JapaneseChronology.JCAL.newCalendarDate(null); 289 jdate.setEra(era.getPrivateEra()); 290 if (yearOfEra == 1) { 291 jdate.setDate(yearOfEra, firstDay.getMonth(), firstDay.getDayOfMonth() + dayOfYear - 1); 292 } else { 293 jdate.setDate(yearOfEra, 1, dayOfYear); 294 } 295 JapaneseChronology.JCAL.normalize(jdate); 296 if (era.getPrivateEra() != jdate.getEra() || yearOfEra != jdate.getYear()) { 297 throw new DateTimeException("Invalid parameters"); 298 } 299 LocalDate localdate = LocalDate.of(jdate.getNormalizedYear(), 300 jdate.getMonth(), jdate.getDayOfMonth()); 301 return new JapaneseDate(era, yearOfEra, localdate); 302 } 303 304 /** 305 * Obtains a {@code JapaneseDate} from a temporal object. 306 * <p> 307 * This obtains a date in the Japanese calendar system based on the specified temporal. 308 * A {@code TemporalAccessor} represents an arbitrary set of date and time information, 309 * which this factory converts to an instance of {@code JapaneseDate}. 310 * <p> 311 * The conversion typically uses the {@link ChronoField#EPOCH_DAY EPOCH_DAY} 312 * field, which is standardized across calendar systems. 313 * <p> 314 * This method matches the signature of the functional interface {@link TemporalQuery} 315 * allowing it to be used as a query via method reference, {@code JapaneseDate::from}. 316 * 317 * @param temporal the temporal object to convert, not null 318 * @return the date in Japanese calendar system, not null 319 * @throws DateTimeException if unable to convert to a {@code JapaneseDate} 320 */ 321 public static JapaneseDate from(TemporalAccessor temporal) { 322 return JapaneseChronology.INSTANCE.date(temporal); 323 } 324 325 //----------------------------------------------------------------------- 326 /** 327 * Creates an instance from an ISO date. 328 * 329 * @param isoDate the standard local date, validated not null 330 */ 331 JapaneseDate(LocalDate isoDate) { 332 if (isoDate.isBefore(MEIJI_6_ISODATE)) { 333 throw new DateTimeException("JapaneseDate before Meiji 6 is not supported"); 334 } 335 LocalGregorianCalendar.Date jdate = toPrivateJapaneseDate(isoDate); 336 this.era = JapaneseEra.toJapaneseEra(jdate.getEra()); 337 this.yearOfEra = jdate.getYear(); 338 this.isoDate = isoDate; 339 } 340 341 /** 342 * Constructs a {@code JapaneseDate}. This constructor does NOT validate the given parameters, 343 * and {@code era} and {@code year} must agree with {@code isoDate}. 344 * 345 * @param era the era, validated not null 346 * @param year the year-of-era, validated 347 * @param isoDate the standard local date, validated not null 348 */ 349 JapaneseDate(JapaneseEra era, int year, LocalDate isoDate) { 350 if (isoDate.isBefore(MEIJI_6_ISODATE)) { 351 throw new DateTimeException("JapaneseDate before Meiji 6 is not supported"); 352 } 353 this.era = era; 354 this.yearOfEra = year; 355 this.isoDate = isoDate; 356 } 357 358 //----------------------------------------------------------------------- 359 /** 360 * Gets the chronology of this date, which is the Japanese calendar system. 361 * <p> 362 * The {@code Chronology} represents the calendar system in use. 363 * The era and other fields in {@link ChronoField} are defined by the chronology. 364 * 365 * @return the Japanese chronology, not null 366 */ 367 @Override 368 public JapaneseChronology getChronology() { 369 return JapaneseChronology.INSTANCE; 370 } 371 372 /** 373 * Gets the era applicable at this date. 374 * <p> 375 * The Japanese calendar system has multiple eras defined by {@link JapaneseEra}. 376 * 377 * @return the era applicable at this date, not null 378 */ 379 @Override 380 public JapaneseEra getEra() { 381 return era; 382 } 383 384 /** 385 * Returns the length of the month represented by this date. 386 * <p> 387 * This returns the length of the month in days. 388 * Month lengths match those of the ISO calendar system. 389 * 390 * @return the length of the month in days 391 */ 392 @Override 393 public int lengthOfMonth() { 394 return isoDate.lengthOfMonth(); 395 } 396 397 @Override 398 public int lengthOfYear() { 399 Calendar jcal = Calendar.getInstance(JapaneseChronology.LOCALE); 400 jcal.set(Calendar.ERA, era.getValue() + JapaneseEra.ERA_OFFSET); 401 jcal.set(yearOfEra, isoDate.getMonthValue() - 1, isoDate.getDayOfMonth()); 402 return jcal.getActualMaximum(Calendar.DAY_OF_YEAR); 403 } 404 405 //----------------------------------------------------------------------- 406 /** 407 * Checks if the specified field is supported. 408 * <p> 409 * This checks if this date can be queried for the specified field. 410 * If false, then calling the {@link #range(TemporalField) range} and 411 * {@link #get(TemporalField) get} methods will throw an exception. 412 * <p> 413 * If the field is a {@link ChronoField} then the query is implemented here. 414 * The supported fields are: 415 * <ul> 416 * <li>{@code DAY_OF_WEEK} 417 * <li>{@code DAY_OF_MONTH} 418 * <li>{@code DAY_OF_YEAR} 419 * <li>{@code EPOCH_DAY} 420 * <li>{@code MONTH_OF_YEAR} 421 * <li>{@code PROLEPTIC_MONTH} 422 * <li>{@code YEAR_OF_ERA} 423 * <li>{@code YEAR} 424 * <li>{@code ERA} 425 * </ul> 426 * All other {@code ChronoField} instances will return false. 427 * <p> 428 * If the field is not a {@code ChronoField}, then the result of this method 429 * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)} 430 * passing {@code this} as the argument. 431 * Whether the field is supported is determined by the field. 432 * 433 * @param field the field to check, null returns false 434 * @return true if the field is supported on this date, false if not 435 */ 436 @Override 437 public boolean isSupported(TemporalField field) { 438 if (field == ALIGNED_DAY_OF_WEEK_IN_MONTH || field == ALIGNED_DAY_OF_WEEK_IN_YEAR || 439 field == ALIGNED_WEEK_OF_MONTH || field == ALIGNED_WEEK_OF_YEAR) { 440 return false; 441 } 442 return super.isSupported(field); 443 } 444 445 @Override 446 public ValueRange range(TemporalField field) { 447 if (field instanceof ChronoField chronoField) { 448 if (isSupported(field)) { 449 return switch (chronoField) { 450 case DAY_OF_MONTH -> ValueRange.of(1, lengthOfMonth()); 451 case DAY_OF_YEAR -> ValueRange.of(1, lengthOfYear()); 452 case YEAR_OF_ERA -> { 453 Calendar jcal = Calendar.getInstance(JapaneseChronology.LOCALE); 454 jcal.set(Calendar.ERA, era.getValue() + JapaneseEra.ERA_OFFSET); 455 jcal.set(yearOfEra, isoDate.getMonthValue() - 1, isoDate.getDayOfMonth()); 456 yield ValueRange.of(1, jcal.getActualMaximum(Calendar.YEAR)); 457 } 458 default -> getChronology().range(chronoField); 459 }; 460 } 461 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 462 } 463 return field.rangeRefinedBy(this); 464 } 465 466 @Override 467 public long getLong(TemporalField field) { 468 if (field instanceof ChronoField cf) { 469 // same as ISO: 470 // DAY_OF_WEEK, DAY_OF_MONTH, EPOCH_DAY, MONTH_OF_YEAR, PROLEPTIC_MONTH, YEAR 471 // 472 // calendar specific fields 473 // DAY_OF_YEAR, YEAR_OF_ERA, ERA 474 switch (cf) { 475 case ALIGNED_DAY_OF_WEEK_IN_MONTH: 476 case ALIGNED_DAY_OF_WEEK_IN_YEAR: 477 case ALIGNED_WEEK_OF_MONTH: 478 case ALIGNED_WEEK_OF_YEAR: 479 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 480 case YEAR_OF_ERA: 481 return yearOfEra; 482 case ERA: 483 return era.getValue(); 484 case DAY_OF_YEAR: 485 Calendar jcal = Calendar.getInstance(JapaneseChronology.LOCALE); 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 chronoField) { 517 if (getLong(chronoField) == newValue) { // getLong() validates for supported fields 518 return this; 519 } 520 switch (chronoField) { 521 case YEAR_OF_ERA: 522 case YEAR: 523 case ERA: { 524 int nvalue = getChronology().range(chronoField).checkValidIntValue(newValue, chronoField); 525 switch (chronoField) { 526 case YEAR_OF_ERA: 527 return this.withYear(nvalue); 528 case YEAR: 529 return with(isoDate.withYear(nvalue)); 530 case ERA: { 531 return this.withYear(JapaneseEra.of(nvalue), yearOfEra); 532 } 533 } 534 } 535 } 536 // YEAR, PROLEPTIC_MONTH and others are same as ISO 537 return with(isoDate.with(field, newValue)); 538 } 539 return super.with(field, newValue); 540 } 541 542 /** 543 * {@inheritDoc} 544 * @throws DateTimeException {@inheritDoc} 545 * @throws ArithmeticException {@inheritDoc} 546 */ 547 @Override 548 public JapaneseDate with(TemporalAdjuster adjuster) { 549 return super.with(adjuster); 550 } 551 552 /** 553 * {@inheritDoc} 554 * @throws DateTimeException {@inheritDoc} 555 * @throws ArithmeticException {@inheritDoc} 556 */ 557 @Override 558 public JapaneseDate plus(TemporalAmount amount) { 559 return super.plus(amount); 560 } 561 562 /** 563 * {@inheritDoc} 564 * @throws DateTimeException {@inheritDoc} 565 * @throws ArithmeticException {@inheritDoc} 566 */ 567 @Override 568 public JapaneseDate minus(TemporalAmount amount) { 569 return super.minus(amount); 570 } 571 //----------------------------------------------------------------------- 572 /** 573 * Returns a copy of this date with the year altered. 574 * <p> 575 * This method changes the year of the date. 576 * If the month-day is invalid for the year, then the previous valid day 577 * will be selected instead. 578 * <p> 579 * This instance is immutable and unaffected by this method call. 580 * 581 * @param era the era to set in the result, not null 582 * @param yearOfEra the year-of-era to set in the returned date 583 * @return a {@code JapaneseDate} based on this date with the requested year, never null 584 * @throws DateTimeException if {@code year} is invalid 585 */ 586 private JapaneseDate withYear(JapaneseEra era, int yearOfEra) { 587 int year = JapaneseChronology.INSTANCE.prolepticYear(era, yearOfEra); 588 return with(isoDate.withYear(year)); 589 } 590 591 /** 592 * Returns a copy of this date with the year-of-era altered. 593 * <p> 594 * This method changes the year-of-era of the date. 595 * If the month-day is invalid for the year, then the previous valid day 596 * will be selected instead. 597 * <p> 598 * This instance is immutable and unaffected by this method call. 599 * 600 * @param year the year to set in the returned date 601 * @return a {@code JapaneseDate} based on this date with the requested year-of-era, never null 602 * @throws DateTimeException if {@code year} is invalid 603 */ 604 private JapaneseDate withYear(int year) { 605 return withYear(getEra(), year); 606 } 607 608 //----------------------------------------------------------------------- 609 @Override 610 JapaneseDate plusYears(long years) { 611 return with(isoDate.plusYears(years)); 612 } 613 614 @Override 615 JapaneseDate plusMonths(long months) { 616 return with(isoDate.plusMonths(months)); 617 } 618 619 @Override 620 JapaneseDate plusWeeks(long weeksToAdd) { 621 return with(isoDate.plusWeeks(weeksToAdd)); 622 } 623 624 @Override 625 JapaneseDate plusDays(long days) { 626 return with(isoDate.plusDays(days)); 627 } 628 629 @Override 630 public JapaneseDate plus(long amountToAdd, TemporalUnit unit) { 631 return super.plus(amountToAdd, unit); 632 } 633 634 @Override 635 public JapaneseDate minus(long amountToSubtract, TemporalUnit unit) { 636 return super.minus(amountToSubtract, unit); 637 } 638 639 @Override 640 JapaneseDate minusYears(long yearsToSubtract) { 641 return super.minusYears(yearsToSubtract); 642 } 643 644 @Override 645 JapaneseDate minusMonths(long monthsToSubtract) { 646 return super.minusMonths(monthsToSubtract); 647 } 648 649 @Override 650 JapaneseDate minusWeeks(long weeksToSubtract) { 651 return super.minusWeeks(weeksToSubtract); 652 } 653 654 @Override 655 JapaneseDate minusDays(long daysToSubtract) { 656 return super.minusDays(daysToSubtract); 657 } 658 659 private JapaneseDate with(LocalDate newDate) { 660 return (newDate.equals(isoDate) ? this : new JapaneseDate(newDate)); 661 } 662 663 @Override // for javadoc and covariant return type 664 @SuppressWarnings("unchecked") 665 public final ChronoLocalDateTime<JapaneseDate> atTime(LocalTime localTime) { 666 return (ChronoLocalDateTime<JapaneseDate>)super.atTime(localTime); 667 } 668 669 @Override 670 public ChronoPeriod until(ChronoLocalDate endDate) { 671 Period period = isoDate.until(endDate); 672 return getChronology().period(period.getYears(), period.getMonths(), period.getDays()); 673 } 674 675 @Override // override for performance 676 public long toEpochDay() { 677 return isoDate.toEpochDay(); 678 } 679 680 //------------------------------------------------------------------------- 681 /** 682 * Compares this date to another date, including the chronology. 683 * <p> 684 * Compares this {@code JapaneseDate} with another ensuring that the date is the same. 685 * <p> 686 * Only objects of type {@code JapaneseDate} are compared, other types return false. 687 * To compare the dates of two {@code TemporalAccessor} instances, including dates 688 * in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator. 689 * 690 * @param obj the object to check, null returns false 691 * @return true if this is equal to the other date 692 */ 693 @Override // override for performance 694 public boolean equals(Object obj) { 695 if (this == obj) { 696 return true; 697 } 698 return (obj instanceof JapaneseDate otherDate) 699 && this.isoDate.equals(otherDate.isoDate); 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 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 */ 719 @java.io.Serial 720 private void readObject(ObjectInputStream s) throws InvalidObjectException { 721 throw new InvalidObjectException("Deserialization via serialization delegate"); 722 } 723 724 /** 725 * Writes the object using a 726 * <a href="{@docRoot}/serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>. 727 * @serialData 728 * <pre> 729 * out.writeByte(4); // identifies a JapaneseDate 730 * out.writeInt(get(YEAR)); 731 * out.writeByte(get(MONTH_OF_YEAR)); 732 * out.writeByte(get(DAY_OF_MONTH)); 733 * </pre> 734 * 735 * @return the instance of {@code Ser}, not null 736 */ 737 @java.io.Serial 738 private Object writeReplace() { 739 return new Ser(Ser.JAPANESE_DATE_TYPE, this); 740 } 741 742 void writeExternal(DataOutput out) throws IOException { 743 // JapaneseChronology is implicit in the JAPANESE_DATE_TYPE 744 out.writeInt(get(YEAR)); 745 out.writeByte(get(MONTH_OF_YEAR)); 746 out.writeByte(get(DAY_OF_MONTH)); 747 } 748 749 static JapaneseDate readExternal(DataInput in) throws IOException { 750 int year = in.readInt(); 751 int month = in.readByte(); 752 int dayOfMonth = in.readByte(); 753 return JapaneseChronology.INSTANCE.date(year, month, dayOfMonth); 754 } 755 756 }