1 /* 2 * Copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * * Neither the name of JSR-310 nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package org.threeten.bp; 33 34 import static org.threeten.bp.temporal.ChronoField.ERA; 35 import static org.threeten.bp.temporal.ChronoField.MONTH_OF_YEAR; 36 import static org.threeten.bp.temporal.ChronoField.PROLEPTIC_MONTH; 37 import static org.threeten.bp.temporal.ChronoField.YEAR; 38 import static org.threeten.bp.temporal.ChronoField.YEAR_OF_ERA; 39 import static org.threeten.bp.temporal.ChronoUnit.CENTURIES; 40 import static org.threeten.bp.temporal.ChronoUnit.DECADES; 41 import static org.threeten.bp.temporal.ChronoUnit.ERAS; 42 import static org.threeten.bp.temporal.ChronoUnit.MILLENNIA; 43 import static org.threeten.bp.temporal.ChronoUnit.MONTHS; 44 import static org.threeten.bp.temporal.ChronoUnit.YEARS; 45 46 import java.io.DataInput; 47 import java.io.DataOutput; 48 import java.io.IOException; 49 import java.io.InvalidObjectException; 50 import java.io.ObjectStreamException; 51 import java.io.Serializable; 52 53 import org.threeten.bp.chrono.Chronology; 54 import org.threeten.bp.chrono.IsoChronology; 55 import org.threeten.bp.format.DateTimeFormatter; 56 import org.threeten.bp.format.DateTimeFormatterBuilder; 57 import org.threeten.bp.format.DateTimeParseException; 58 import org.threeten.bp.format.SignStyle; 59 import org.threeten.bp.jdk8.DefaultInterfaceTemporalAccessor; 60 import org.threeten.bp.jdk8.Jdk8Methods; 61 import org.threeten.bp.temporal.ChronoField; 62 import org.threeten.bp.temporal.ChronoUnit; 63 import org.threeten.bp.temporal.Temporal; 64 import org.threeten.bp.temporal.TemporalAccessor; 65 import org.threeten.bp.temporal.TemporalAdjuster; 66 import org.threeten.bp.temporal.TemporalAmount; 67 import org.threeten.bp.temporal.TemporalField; 68 import org.threeten.bp.temporal.TemporalQueries; 69 import org.threeten.bp.temporal.TemporalQuery; 70 import org.threeten.bp.temporal.TemporalUnit; 71 import org.threeten.bp.temporal.UnsupportedTemporalTypeException; 72 import org.threeten.bp.temporal.ValueRange; 73 74 /** 75 * A year-month in the ISO-8601 calendar system, such as {@code 2007-12}. 76 * <p> 77 * {@code YearMonth} is an immutable date-time object that represents the combination 78 * of a year and month. Any field that can be derived from a year and month, such as 79 * quarter-of-year, can be obtained. 80 * <p> 81 * This class does not store or represent a day, time or time-zone. 82 * For example, the value "October 2007" can be stored in a {@code YearMonth}. 83 * <p> 84 * The ISO-8601 calendar system is the modern civil calendar system used today 85 * in most of the world. It is equivalent to the proleptic Gregorian calendar 86 * system, in which today's rules for leap years are applied for all time. 87 * For most applications written today, the ISO-8601 rules are entirely suitable. 88 * However, any application that makes use of historical dates, and requires them 89 * to be accurate will find the ISO-8601 approach unsuitable. 90 * 91 * <h3>Specification for implementors</h3> 92 * This class is immutable and thread-safe. 93 */ 94 public final class YearMonth 95 extends DefaultInterfaceTemporalAccessor 96 implements Temporal, TemporalAdjuster, Comparable<YearMonth>, Serializable { 97 98 /** 99 * Simulate JDK 8 method reference YearMonth::from. 100 */ 101 public static final TemporalQuery<YearMonth> FROM = new TemporalQuery<YearMonth>() { 102 @Override 103 public YearMonth queryFrom(TemporalAccessor temporal) { 104 return YearMonth.from(temporal); 105 } 106 }; 107 108 /** 109 * Serialization version. 110 */ 111 private static final long serialVersionUID = 4183400860270640070L; 112 /** 113 * Parser. 114 */ 115 private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder() 116 .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD) 117 .appendLiteral('-') 118 .appendValue(MONTH_OF_YEAR, 2) 119 .toFormatter(); 120 121 /** 122 * The year. 123 */ 124 private final int year; 125 /** 126 * The month-of-year, not null. 127 */ 128 private final int month; 129 130 //----------------------------------------------------------------------- 131 /** 132 * Obtains the current year-month from the system clock in the default time-zone. 133 * <p> 134 * This will query the {@link Clock#systemDefaultZone() system clock} in the default 135 * time-zone to obtain the current year-month. 136 * The zone and offset will be set based on the time-zone in the clock. 137 * <p> 138 * Using this method will prevent the ability to use an alternate clock for testing 139 * because the clock is hard-coded. 140 * 141 * @return the current year-month using the system clock and default time-zone, not null 142 */ now()143 public static YearMonth now() { 144 return now(Clock.systemDefaultZone()); 145 } 146 147 /** 148 * Obtains the current year-month from the system clock in the specified time-zone. 149 * <p> 150 * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current year-month. 151 * Specifying the time-zone avoids dependence on the default time-zone. 152 * <p> 153 * Using this method will prevent the ability to use an alternate clock for testing 154 * because the clock is hard-coded. 155 * 156 * @param zone the zone ID to use, not null 157 * @return the current year-month using the system clock, not null 158 */ now(ZoneId zone)159 public static YearMonth now(ZoneId zone) { 160 return now(Clock.system(zone)); 161 } 162 163 /** 164 * Obtains the current year-month from the specified clock. 165 * <p> 166 * This will query the specified clock to obtain the current year-month. 167 * Using this method allows the use of an alternate clock for testing. 168 * The alternate clock may be introduced using {@link Clock dependency injection}. 169 * 170 * @param clock the clock to use, not null 171 * @return the current year-month, not null 172 */ now(Clock clock)173 public static YearMonth now(Clock clock) { 174 final LocalDate now = LocalDate.now(clock); // called once 175 return YearMonth.of(now.getYear(), now.getMonth()); 176 } 177 178 //----------------------------------------------------------------------- 179 /** 180 * Obtains an instance of {@code YearMonth} from a year and month. 181 * 182 * @param year the year to represent, from MIN_YEAR to MAX_YEAR 183 * @param month the month-of-year to represent, not null 184 * @return the year-month, not null 185 * @throws DateTimeException if the year value is invalid 186 */ of(int year, Month month)187 public static YearMonth of(int year, Month month) { 188 Jdk8Methods.requireNonNull(month, "month"); 189 return of(year, month.getValue()); 190 } 191 192 /** 193 * Obtains an instance of {@code YearMonth} from a year and month. 194 * 195 * @param year the year to represent, from MIN_YEAR to MAX_YEAR 196 * @param month the month-of-year to represent, from 1 (January) to 12 (December) 197 * @return the year-month, not null 198 * @throws DateTimeException if either field value is invalid 199 */ of(int year, int month)200 public static YearMonth of(int year, int month) { 201 YEAR.checkValidValue(year); 202 MONTH_OF_YEAR.checkValidValue(month); 203 return new YearMonth(year, month); 204 } 205 206 //----------------------------------------------------------------------- 207 /** 208 * Obtains an instance of {@code YearMonth} from a temporal object. 209 * <p> 210 * A {@code TemporalAccessor} represents some form of date and time information. 211 * This factory converts the arbitrary temporal object to an instance of {@code YearMonth}. 212 * <p> 213 * The conversion extracts the {@link ChronoField#YEAR YEAR} and 214 * {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} fields. 215 * The extraction is only permitted if the temporal object has an ISO 216 * chronology, or can be converted to a {@code LocalDate}. 217 * <p> 218 * This method matches the signature of the functional interface {@link TemporalQuery} 219 * allowing it to be used in queries via method reference, {@code YearMonth::from}. 220 * 221 * @param temporal the temporal object to convert, not null 222 * @return the year-month, not null 223 * @throws DateTimeException if unable to convert to a {@code YearMonth} 224 */ from(TemporalAccessor temporal)225 public static YearMonth from(TemporalAccessor temporal) { 226 if (temporal instanceof YearMonth) { 227 return (YearMonth) temporal; 228 } 229 try { 230 if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) { 231 temporal = LocalDate.from(temporal); 232 } 233 return of(temporal.get(YEAR), temporal.get(MONTH_OF_YEAR)); 234 } catch (DateTimeException ex) { 235 throw new DateTimeException("Unable to obtain YearMonth from TemporalAccessor: " + 236 temporal + ", type " + temporal.getClass().getName()); 237 } 238 } 239 240 //----------------------------------------------------------------------- 241 /** 242 * Obtains an instance of {@code YearMonth} from a text string such as {@code 2007-12}. 243 * <p> 244 * The string must represent a valid year-month. 245 * The format must be {@code yyyy-MM}. 246 * Years outside the range 0000 to 9999 must be prefixed by the plus or minus symbol. 247 * 248 * @param text the text to parse such as "2007-12", not null 249 * @return the parsed year-month, not null 250 * @throws DateTimeParseException if the text cannot be parsed 251 */ parse(CharSequence text)252 public static YearMonth parse(CharSequence text) { 253 return parse(text, PARSER); 254 } 255 256 /** 257 * Obtains an instance of {@code YearMonth} from a text string using a specific formatter. 258 * <p> 259 * The text is parsed using the formatter, returning a year-month. 260 * 261 * @param text the text to parse, not null 262 * @param formatter the formatter to use, not null 263 * @return the parsed year-month, not null 264 * @throws DateTimeParseException if the text cannot be parsed 265 */ parse(CharSequence text, DateTimeFormatter formatter)266 public static YearMonth parse(CharSequence text, DateTimeFormatter formatter) { 267 Jdk8Methods.requireNonNull(formatter, "formatter"); 268 return formatter.parse(text, YearMonth.FROM); 269 } 270 271 //----------------------------------------------------------------------- 272 /** 273 * Constructor. 274 * 275 * @param year the year to represent, validated from MIN_YEAR to MAX_YEAR 276 * @param month the month-of-year to represent, validated from 1 (January) to 12 (December) 277 */ YearMonth(int year, int month)278 private YearMonth(int year, int month) { 279 this.year = year; 280 this.month = month; 281 } 282 283 /** 284 * Returns a copy of this year-month with the new year and month, checking 285 * to see if a new object is in fact required. 286 * 287 * @param newYear the year to represent, validated from MIN_YEAR to MAX_YEAR 288 * @param newMonth the month-of-year to represent, validated not null 289 * @return the year-month, not null 290 */ with(int newYear, int newMonth)291 private YearMonth with(int newYear, int newMonth) { 292 if (year == newYear && month == newMonth) { 293 return this; 294 } 295 return new YearMonth(newYear, newMonth); 296 } 297 298 //----------------------------------------------------------------------- 299 /** 300 * Checks if the specified field is supported. 301 * <p> 302 * This checks if this year-month can be queried for the specified field. 303 * If false, then calling the {@link #range(TemporalField) range} and 304 * {@link #get(TemporalField) get} methods will throw an exception. 305 * <p> 306 * If the field is a {@link ChronoField} then the query is implemented here. 307 * The {@link #isSupported(TemporalField) supported fields} will return valid 308 * values based on this date-time. 309 * The supported fields are: 310 * <ul> 311 * <li>{@code MONTH_OF_YEAR} 312 * <li>{@code EPOCH_MONTH} 313 * <li>{@code YEAR_OF_ERA} 314 * <li>{@code YEAR} 315 * <li>{@code ERA} 316 * </ul> 317 * All other {@code ChronoField} instances will return false. 318 * <p> 319 * If the field is not a {@code ChronoField}, then the result of this method 320 * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)} 321 * passing {@code this} as the argument. 322 * Whether the field is supported is determined by the field. 323 * 324 * @param field the field to check, null returns false 325 * @return true if the field is supported on this year-month, false if not 326 */ 327 @Override isSupported(TemporalField field)328 public boolean isSupported(TemporalField field) { 329 if (field instanceof ChronoField) { 330 return field == YEAR || field == MONTH_OF_YEAR || 331 field == PROLEPTIC_MONTH || field == YEAR_OF_ERA || field == ERA; 332 } 333 return field != null && field.isSupportedBy(this); 334 } 335 336 @Override isSupported(TemporalUnit unit)337 public boolean isSupported(TemporalUnit unit) { 338 if (unit instanceof ChronoUnit) { 339 return unit == MONTHS || unit == YEARS || unit == DECADES || unit == CENTURIES || unit == MILLENNIA || unit == ERAS; 340 } 341 return unit != null && unit.isSupportedBy(this); 342 } 343 344 /** 345 * Gets the range of valid values for the specified field. 346 * <p> 347 * The range object expresses the minimum and maximum valid values for a field. 348 * This year-month is used to enhance the accuracy of the returned range. 349 * If it is not possible to return the range, because the field is not supported 350 * or for some other reason, an exception is thrown. 351 * <p> 352 * If the field is a {@link ChronoField} then the query is implemented here. 353 * The {@link #isSupported(TemporalField) supported fields} will return 354 * appropriate range instances. 355 * All other {@code ChronoField} instances will throw a {@code DateTimeException}. 356 * <p> 357 * If the field is not a {@code ChronoField}, then the result of this method 358 * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)} 359 * passing {@code this} as the argument. 360 * Whether the range can be obtained is determined by the field. 361 * 362 * @param field the field to query the range for, not null 363 * @return the range of valid values for the field, not null 364 * @throws DateTimeException if the range for the field cannot be obtained 365 */ 366 @Override range(TemporalField field)367 public ValueRange range(TemporalField field) { 368 if (field == YEAR_OF_ERA) { 369 return (getYear() <= 0 ? ValueRange.of(1, Year.MAX_VALUE + 1) : ValueRange.of(1, Year.MAX_VALUE)); 370 } 371 return super.range(field); 372 } 373 374 /** 375 * Gets the value of the specified field from this year-month as an {@code int}. 376 * <p> 377 * This queries this year-month for the value for the specified field. 378 * The returned value will always be within the valid range of values for the field. 379 * If it is not possible to return the value, because the field is not supported 380 * or for some other reason, an exception is thrown. 381 * <p> 382 * If the field is a {@link ChronoField} then the query is implemented here. 383 * The {@link #isSupported(TemporalField) supported fields} will return valid 384 * values based on this year-month, except {@code EPOCH_MONTH} which is too 385 * large to fit in an {@code int} and throw a {@code DateTimeException}. 386 * All other {@code ChronoField} instances will throw a {@code DateTimeException}. 387 * <p> 388 * If the field is not a {@code ChronoField}, then the result of this method 389 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} 390 * passing {@code this} as the argument. Whether the value can be obtained, 391 * and what the value represents, is determined by the field. 392 * 393 * @param field the field to get, not null 394 * @return the value for the field 395 * @throws DateTimeException if a value for the field cannot be obtained 396 * @throws ArithmeticException if numeric overflow occurs 397 */ 398 @Override // override for Javadoc get(TemporalField field)399 public int get(TemporalField field) { 400 return range(field).checkValidIntValue(getLong(field), field); 401 } 402 403 /** 404 * Gets the value of the specified field from this year-month as a {@code long}. 405 * <p> 406 * This queries this year-month for the value for the specified field. 407 * If it is not possible to return the value, because the field is not supported 408 * or for some other reason, an exception is thrown. 409 * <p> 410 * If the field is a {@link ChronoField} then the query is implemented here. 411 * The {@link #isSupported(TemporalField) supported fields} will return valid 412 * values based on this year-month. 413 * All other {@code ChronoField} instances will throw a {@code DateTimeException}. 414 * <p> 415 * If the field is not a {@code ChronoField}, then the result of this method 416 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} 417 * passing {@code this} as the argument. Whether the value can be obtained, 418 * and what the value represents, is determined by the field. 419 * 420 * @param field the field to get, not null 421 * @return the value for the field 422 * @throws DateTimeException if a value for the field cannot be obtained 423 * @throws ArithmeticException if numeric overflow occurs 424 */ 425 @Override getLong(TemporalField field)426 public long getLong(TemporalField field) { 427 if (field instanceof ChronoField) { 428 switch ((ChronoField) field) { 429 case MONTH_OF_YEAR: return month; 430 case PROLEPTIC_MONTH: return getProlepticMonth(); 431 case YEAR_OF_ERA: return (year < 1 ? 1 - year : year); 432 case YEAR: return year; 433 case ERA: return (year < 1 ? 0 : 1); 434 } 435 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 436 } 437 return field.getFrom(this); 438 } 439 getProlepticMonth()440 private long getProlepticMonth() { 441 return (year * 12L) + (month - 1); 442 } 443 444 //----------------------------------------------------------------------- 445 /** 446 * Gets the year field. 447 * <p> 448 * This method returns the primitive {@code int} value for the year. 449 * <p> 450 * The year returned by this method is proleptic as per {@code get(YEAR)}. 451 * 452 * @return the year, from MIN_YEAR to MAX_YEAR 453 */ getYear()454 public int getYear() { 455 return year; 456 } 457 458 /** 459 * Gets the month-of-year field from 1 to 12. 460 * <p> 461 * This method returns the month as an {@code int} from 1 to 12. 462 * Application code is frequently clearer if the enum {@link Month} 463 * is used by calling {@link #getMonth()}. 464 * 465 * @return the month-of-year, from 1 to 12 466 * @see #getMonth() 467 */ getMonthValue()468 public int getMonthValue() { 469 return month; 470 } 471 472 /** 473 * Gets the month-of-year field using the {@code Month} enum. 474 * <p> 475 * This method returns the enum {@link Month} for the month. 476 * This avoids confusion as to what {@code int} values mean. 477 * If you need access to the primitive {@code int} value then the enum 478 * provides the {@link Month#getValue() int value}. 479 * 480 * @return the month-of-year, not null 481 */ getMonth()482 public Month getMonth() { 483 return Month.of(month); 484 } 485 486 //----------------------------------------------------------------------- 487 /** 488 * Checks if the year is a leap year, according to the ISO proleptic 489 * calendar system rules. 490 * <p> 491 * This method applies the current rules for leap years across the whole time-line. 492 * In general, a year is a leap year if it is divisible by four without 493 * remainder. However, years divisible by 100, are not leap years, with 494 * the exception of years divisible by 400 which are. 495 * <p> 496 * For example, 1904 is a leap year it is divisible by 4. 497 * 1900 was not a leap year as it is divisible by 100, however 2000 was a 498 * leap year as it is divisible by 400. 499 * <p> 500 * The calculation is proleptic - applying the same rules into the far future and far past. 501 * This is historically inaccurate, but is correct for the ISO-8601 standard. 502 * 503 * @return true if the year is leap, false otherwise 504 */ isLeapYear()505 public boolean isLeapYear() { 506 return IsoChronology.INSTANCE.isLeapYear(year); 507 } 508 509 /** 510 * Checks if the day-of-month is valid for this year-month. 511 * <p> 512 * This method checks whether this year and month and the input day form 513 * a valid date. 514 * 515 * @param dayOfMonth the day-of-month to validate, from 1 to 31, invalid value returns false 516 * @return true if the day is valid for this year-month 517 */ isValidDay(int dayOfMonth)518 public boolean isValidDay(int dayOfMonth) { 519 return dayOfMonth >= 1 && dayOfMonth <= lengthOfMonth(); 520 } 521 522 /** 523 * Returns the length of the month, taking account of the year. 524 * <p> 525 * This returns the length of the month in days. 526 * For example, a date in January would return 31. 527 * 528 * @return the length of the month in days, from 28 to 31 529 */ lengthOfMonth()530 public int lengthOfMonth() { 531 return getMonth().length(isLeapYear()); 532 } 533 534 /** 535 * Returns the length of the year. 536 * <p> 537 * This returns the length of the year in days, either 365 or 366. 538 * 539 * @return 366 if the year is leap, 365 otherwise 540 */ lengthOfYear()541 public int lengthOfYear() { 542 return (isLeapYear() ? 366 : 365); 543 } 544 545 //----------------------------------------------------------------------- 546 /** 547 * Returns an adjusted copy of this year-month. 548 * <p> 549 * This returns a new {@code YearMonth}, based on this one, with the year-month adjusted. 550 * The adjustment takes place using the specified adjuster strategy object. 551 * Read the documentation of the adjuster to understand what adjustment will be made. 552 * <p> 553 * A simple adjuster might simply set the one of the fields, such as the year field. 554 * A more complex adjuster might set the year-month to the next month that 555 * Halley's comet will pass the Earth. 556 * <p> 557 * The result of this method is obtained by invoking the 558 * {@link TemporalAdjuster#adjustInto(Temporal)} method on the 559 * specified adjuster passing {@code this} as the argument. 560 * <p> 561 * This instance is immutable and unaffected by this method call. 562 * 563 * @param adjuster the adjuster to use, not null 564 * @return a {@code YearMonth} based on {@code this} with the adjustment made, not null 565 * @throws DateTimeException if the adjustment cannot be made 566 * @throws ArithmeticException if numeric overflow occurs 567 */ 568 @Override with(TemporalAdjuster adjuster)569 public YearMonth with(TemporalAdjuster adjuster) { 570 return (YearMonth) adjuster.adjustInto(this); 571 } 572 573 /** 574 * Returns a copy of this year-month with the specified field set to a new value. 575 * <p> 576 * This returns a new {@code YearMonth}, based on this one, with the value 577 * for the specified field changed. 578 * This can be used to change any supported field, such as the year or month. 579 * If it is not possible to set the value, because the field is not supported or for 580 * some other reason, an exception is thrown. 581 * <p> 582 * If the field is a {@link ChronoField} then the adjustment is implemented here. 583 * The supported fields behave as follows: 584 * <ul> 585 * <li>{@code MONTH_OF_YEAR} - 586 * Returns a {@code YearMonth} with the specified month-of-year. 587 * The year will be unchanged. 588 * <li>{@code PROLEPTIC_MONTH} - 589 * Returns a {@code YearMonth} with the specified proleptic-month. 590 * This completely replaces the year and month of this object. 591 * <li>{@code YEAR_OF_ERA} - 592 * Returns a {@code YearMonth} with the specified year-of-era 593 * The month and era will be unchanged. 594 * <li>{@code YEAR} - 595 * Returns a {@code YearMonth} with the specified year. 596 * The month will be unchanged. 597 * <li>{@code ERA} - 598 * Returns a {@code YearMonth} with the specified era. 599 * The month and year-of-era will be unchanged. 600 * </ul> 601 * <p> 602 * In all cases, if the new value is outside the valid range of values for the field 603 * then a {@code DateTimeException} will be thrown. 604 * <p> 605 * All other {@code ChronoField} instances will throw a {@code DateTimeException}. 606 * <p> 607 * If the field is not a {@code ChronoField}, then the result of this method 608 * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)} 609 * passing {@code this} as the argument. In this case, the field determines 610 * whether and how to adjust the instant. 611 * <p> 612 * This instance is immutable and unaffected by this method call. 613 * 614 * @param field the field to set in the result, not null 615 * @param newValue the new value of the field in the result 616 * @return a {@code YearMonth} based on {@code this} with the specified field set, not null 617 * @throws DateTimeException if the field cannot be set 618 * @throws ArithmeticException if numeric overflow occurs 619 */ 620 @Override with(TemporalField field, long newValue)621 public YearMonth with(TemporalField field, long newValue) { 622 if (field instanceof ChronoField) { 623 ChronoField f = (ChronoField) field; 624 f.checkValidValue(newValue); 625 switch (f) { 626 case MONTH_OF_YEAR: return withMonth((int) newValue); 627 case PROLEPTIC_MONTH: return plusMonths(newValue - getLong(PROLEPTIC_MONTH)); 628 case YEAR_OF_ERA: return withYear((int) (year < 1 ? 1 - newValue : newValue)); 629 case YEAR: return withYear((int) newValue); 630 case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year)); 631 } 632 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 633 } 634 return field.adjustInto(this, newValue); 635 } 636 637 //----------------------------------------------------------------------- 638 /** 639 * Returns a copy of this {@code YearMonth} with the year altered. 640 * <p> 641 * This instance is immutable and unaffected by this method call. 642 * 643 * @param year the year to set in the returned year-month, from MIN_YEAR to MAX_YEAR 644 * @return a {@code YearMonth} based on this year-month with the requested year, not null 645 * @throws DateTimeException if the year value is invalid 646 */ withYear(int year)647 public YearMonth withYear(int year) { 648 YEAR.checkValidValue(year); 649 return with(year, month); 650 } 651 652 /** 653 * Returns a copy of this {@code YearMonth} with the month-of-year altered. 654 * <p> 655 * This instance is immutable and unaffected by this method call. 656 * 657 * @param month the month-of-year to set in the returned year-month, from 1 (January) to 12 (December) 658 * @return a {@code YearMonth} based on this year-month with the requested month, not null 659 * @throws DateTimeException if the month-of-year value is invalid 660 */ withMonth(int month)661 public YearMonth withMonth(int month) { 662 MONTH_OF_YEAR.checkValidValue(month); 663 return with(year, month); 664 } 665 666 //----------------------------------------------------------------------- 667 /** 668 * Returns a copy of this year-month with the specified period added. 669 * <p> 670 * This method returns a new year-month based on this year-month with the specified period added. 671 * The adder is typically {@link org.threeten.bp.Period Period} but may be any other type implementing 672 * the {@link TemporalAmount} interface. 673 * The calculation is delegated to the specified adjuster, which typically calls 674 * back to {@link #plus(long, TemporalUnit)}. 675 * <p> 676 * This instance is immutable and unaffected by this method call. 677 * 678 * @param amount the amount to add, not null 679 * @return a {@code YearMonth} based on this year-month with the addition made, not null 680 * @throws DateTimeException if the addition cannot be made 681 * @throws ArithmeticException if numeric overflow occurs 682 */ 683 @Override plus(TemporalAmount amount)684 public YearMonth plus(TemporalAmount amount) { 685 return (YearMonth) amount.addTo(this); 686 } 687 688 /** 689 * {@inheritDoc} 690 * @throws DateTimeException {@inheritDoc} 691 * @throws ArithmeticException {@inheritDoc} 692 */ 693 @Override plus(long amountToAdd, TemporalUnit unit)694 public YearMonth plus(long amountToAdd, TemporalUnit unit) { 695 if (unit instanceof ChronoUnit) { 696 switch ((ChronoUnit) unit) { 697 case MONTHS: return plusMonths(amountToAdd); 698 case YEARS: return plusYears(amountToAdd); 699 case DECADES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 10)); 700 case CENTURIES: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 100)); 701 case MILLENNIA: return plusYears(Jdk8Methods.safeMultiply(amountToAdd, 1000)); 702 case ERAS: return with(ERA, Jdk8Methods.safeAdd(getLong(ERA), amountToAdd)); 703 } 704 throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit); 705 } 706 return unit.addTo(this, amountToAdd); 707 } 708 709 /** 710 * Returns a copy of this year-month with the specified period in years added. 711 * <p> 712 * This instance is immutable and unaffected by this method call. 713 * 714 * @param yearsToAdd the years to add, may be negative 715 * @return a {@code YearMonth} based on this year-month with the years added, not null 716 * @throws DateTimeException if the result exceeds the supported range 717 */ plusYears(long yearsToAdd)718 public YearMonth plusYears(long yearsToAdd) { 719 if (yearsToAdd == 0) { 720 return this; 721 } 722 int newYear = YEAR.checkValidIntValue(year + yearsToAdd); // safe overflow 723 return with(newYear, month); 724 } 725 726 /** 727 * Returns a copy of this year-month with the specified period in months added. 728 * <p> 729 * This instance is immutable and unaffected by this method call. 730 * 731 * @param monthsToAdd the months to add, may be negative 732 * @return a {@code YearMonth} based on this year-month with the months added, not null 733 * @throws DateTimeException if the result exceeds the supported range 734 */ plusMonths(long monthsToAdd)735 public YearMonth plusMonths(long monthsToAdd) { 736 if (monthsToAdd == 0) { 737 return this; 738 } 739 long monthCount = year * 12L + (month - 1); 740 long calcMonths = monthCount + monthsToAdd; // safe overflow 741 int newYear = YEAR.checkValidIntValue(Jdk8Methods.floorDiv(calcMonths, 12)); 742 int newMonth = Jdk8Methods.floorMod(calcMonths, 12) + 1; 743 return with(newYear, newMonth); 744 } 745 746 //----------------------------------------------------------------------- 747 /** 748 * Returns a copy of this year-month with the specified period subtracted. 749 * <p> 750 * This method returns a new year-month based on this year-month with the specified period subtracted. 751 * The subtractor is typically {@link org.threeten.bp.Period Period} but may be any other type implementing 752 * the {@link TemporalAmount} interface. 753 * The calculation is delegated to the specified adjuster, which typically calls 754 * back to {@link #minus(long, TemporalUnit)}. 755 * <p> 756 * This instance is immutable and unaffected by this method call. 757 * 758 * @param amount the amount to aubtract, not null 759 * @return a {@code YearMonth} based on this year-month with the subtraction made, not null 760 * @throws DateTimeException if the subtraction cannot be made 761 * @throws ArithmeticException if numeric overflow occurs 762 */ 763 @Override minus(TemporalAmount amount)764 public YearMonth minus(TemporalAmount amount) { 765 return (YearMonth) amount.subtractFrom(this); 766 } 767 768 /** 769 * {@inheritDoc} 770 * @throws DateTimeException {@inheritDoc} 771 * @throws ArithmeticException {@inheritDoc} 772 */ 773 @Override minus(long amountToSubtract, TemporalUnit unit)774 public YearMonth minus(long amountToSubtract, TemporalUnit unit) { 775 return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); 776 } 777 778 /** 779 * Returns a copy of this year-month with the specified period in years subtracted. 780 * <p> 781 * This instance is immutable and unaffected by this method call. 782 * 783 * @param yearsToSubtract the years to subtract, may be negative 784 * @return a {@code YearMonth} based on this year-month with the years subtracted, not null 785 * @throws DateTimeException if the result exceeds the supported range 786 */ minusYears(long yearsToSubtract)787 public YearMonth minusYears(long yearsToSubtract) { 788 return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract)); 789 } 790 791 /** 792 * Returns a copy of this year-month with the specified period in months subtracted. 793 * <p> 794 * This instance is immutable and unaffected by this method call. 795 * 796 * @param monthsToSubtract the months to subtract, may be negative 797 * @return a {@code YearMonth} based on this year-month with the months subtracted, not null 798 * @throws DateTimeException if the result exceeds the supported range 799 */ minusMonths(long monthsToSubtract)800 public YearMonth minusMonths(long monthsToSubtract) { 801 return (monthsToSubtract == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-monthsToSubtract)); 802 } 803 804 //----------------------------------------------------------------------- 805 /** 806 * Queries this year-month using the specified query. 807 * <p> 808 * This queries this year-month using the specified query strategy object. 809 * The {@code TemporalQuery} object defines the logic to be used to 810 * obtain the result. Read the documentation of the query to understand 811 * what the result of this method will be. 812 * <p> 813 * The result of this method is obtained by invoking the 814 * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the 815 * specified query passing {@code this} as the argument. 816 * 817 * @param <R> the type of the result 818 * @param query the query to invoke, not null 819 * @return the query result, null may be returned (defined by the query) 820 * @throws DateTimeException if unable to query (defined by the query) 821 * @throws ArithmeticException if numeric overflow occurs (defined by the query) 822 */ 823 @SuppressWarnings("unchecked") 824 @Override query(TemporalQuery<R> query)825 public <R> R query(TemporalQuery<R> query) { 826 if (query == TemporalQueries.chronology()) { 827 return (R) IsoChronology.INSTANCE; 828 } else if (query == TemporalQueries.precision()) { 829 return (R) MONTHS; 830 } else if (query == TemporalQueries.localDate() || query == TemporalQueries.localTime() || 831 query == TemporalQueries.zone() || query == TemporalQueries.zoneId() || query == TemporalQueries.offset()) { 832 return null; 833 } 834 return super.query(query); 835 } 836 837 /** 838 * Adjusts the specified temporal object to have this year-month. 839 * <p> 840 * This returns a temporal object of the same observable type as the input 841 * with the year and month changed to be the same as this. 842 * <p> 843 * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)} 844 * passing {@link ChronoField#PROLEPTIC_MONTH} as the field. 845 * If the specified temporal object does not use the ISO calendar system then 846 * a {@code DateTimeException} is thrown. 847 * <p> 848 * In most cases, it is clearer to reverse the calling pattern by using 849 * {@link Temporal#with(TemporalAdjuster)}: 850 * <pre> 851 * // these two lines are equivalent, but the second approach is recommended 852 * temporal = thisYearMonth.adjustInto(temporal); 853 * temporal = temporal.with(thisYearMonth); 854 * </pre> 855 * <p> 856 * This instance is immutable and unaffected by this method call. 857 * 858 * @param temporal the target object to be adjusted, not null 859 * @return the adjusted object, not null 860 * @throws DateTimeException if unable to make the adjustment 861 * @throws ArithmeticException if numeric overflow occurs 862 */ 863 @Override adjustInto(Temporal temporal)864 public Temporal adjustInto(Temporal temporal) { 865 if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) { 866 throw new DateTimeException("Adjustment only supported on ISO date-time"); 867 } 868 return temporal.with(PROLEPTIC_MONTH, getProlepticMonth()); 869 } 870 871 /** 872 * Calculates the period between this year-month and another year-month in 873 * terms of the specified unit. 874 * <p> 875 * This calculates the period between two year-months in terms of a single unit. 876 * The start and end points are {@code this} and the specified year-month. 877 * The result will be negative if the end is before the start. 878 * The {@code Temporal} passed to this method must be a {@code YearMonth}. 879 * For example, the period in years between two year-months can be calculated 880 * using {@code startYearMonth.until(endYearMonth, YEARS)}. 881 * <p> 882 * The calculation returns a whole number, representing the number of 883 * complete units between the two year-months. 884 * For example, the period in decades between 2012-06 and 2032-05 885 * will only be one decade as it is one month short of two decades. 886 * <p> 887 * This method operates in association with {@link TemporalUnit#between}. 888 * The result of this method is a {@code long} representing the amount of 889 * the specified unit. By contrast, the result of {@code between} is an 890 * object that can be used directly in addition/subtraction: 891 * <pre> 892 * long period = start.until(end, YEARS); // this method 893 * dateTime.plus(YEARS.between(start, end)); // use in plus/minus 894 * </pre> 895 * <p> 896 * The calculation is implemented in this method for {@link ChronoUnit}. 897 * The units {@code MONTHS}, {@code YEARS}, {@code DECADES}, 898 * {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS} are supported. 899 * Other {@code ChronoUnit} values will throw an exception. 900 * <p> 901 * If the unit is not a {@code ChronoUnit}, then the result of this method 902 * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)} 903 * passing {@code this} as the first argument and the input temporal as 904 * the second argument. 905 * <p> 906 * This instance is immutable and unaffected by this method call. 907 * 908 * @param endExclusive the end year-month, which is converted to a {@code YearMonth}, not null 909 * @param unit the unit to measure the period in, not null 910 * @return the amount of the period between this year-month and the end year-month 911 * @throws DateTimeException if the period cannot be calculated 912 * @throws ArithmeticException if numeric overflow occurs 913 */ 914 @Override until(Temporal endExclusive, TemporalUnit unit)915 public long until(Temporal endExclusive, TemporalUnit unit) { 916 YearMonth end = YearMonth.from(endExclusive); 917 if (unit instanceof ChronoUnit) { 918 long monthsUntil = end.getProlepticMonth() - getProlepticMonth(); // no overflow 919 switch ((ChronoUnit) unit) { 920 case MONTHS: return monthsUntil; 921 case YEARS: return monthsUntil / 12; 922 case DECADES: return monthsUntil / 120; 923 case CENTURIES: return monthsUntil / 1200; 924 case MILLENNIA: return monthsUntil / 12000; 925 case ERAS: return end.getLong(ERA) - getLong(ERA); 926 } 927 throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit); 928 } 929 return unit.between(this, end); 930 } 931 932 //----------------------------------------------------------------------- 933 /** 934 * Combines this year-month with a day-of-month to create a {@code LocalDate}. 935 * <p> 936 * This returns a {@code LocalDate} formed from this year-month and the specified day-of-month. 937 * <p> 938 * The day-of-month value must be valid for the year-month. 939 * <p> 940 * This method can be used as part of a chain to produce a date: 941 * <pre> 942 * LocalDate date = year.atMonth(month).atDay(day); 943 * </pre> 944 * 945 * @param dayOfMonth the day-of-month to use, from 1 to 31 946 * @return the date formed from this year-month and the specified day, not null 947 * @throws DateTimeException if the day is invalid for the year-month 948 * @see #isValidDay(int) 949 */ atDay(int dayOfMonth)950 public LocalDate atDay(int dayOfMonth) { 951 return LocalDate.of(year, month, dayOfMonth); 952 } 953 954 /** 955 * Returns a {@code LocalDate} at the end of the month. 956 * <p> 957 * This returns a {@code LocalDate} based on this year-month. 958 * The day-of-month is set to the last valid day of the month, taking 959 * into account leap years. 960 * <p> 961 * This method can be used as part of a chain to produce a date: 962 * <pre> 963 * LocalDate date = year.atMonth(month).atEndOfMonth(); 964 * </pre> 965 * 966 * @return the last valid date of this year-month, not null 967 */ atEndOfMonth()968 public LocalDate atEndOfMonth() { 969 return LocalDate.of(year, month, lengthOfMonth()); 970 } 971 972 //----------------------------------------------------------------------- 973 /** 974 * Compares this year-month to another year-month. 975 * <p> 976 * The comparison is based first on the value of the year, then on the value of the month. 977 * It is "consistent with equals", as defined by {@link Comparable}. 978 * 979 * @param other the other year-month to compare to, not null 980 * @return the comparator value, negative if less, positive if greater 981 */ 982 @Override compareTo(YearMonth other)983 public int compareTo(YearMonth other) { 984 int cmp = (year - other.year); 985 if (cmp == 0) { 986 cmp = (month - other.month); 987 } 988 return cmp; 989 } 990 991 /** 992 * Is this year-month after the specified year-month. 993 * 994 * @param other the other year-month to compare to, not null 995 * @return true if this is after the specified year-month 996 */ isAfter(YearMonth other)997 public boolean isAfter(YearMonth other) { 998 return compareTo(other) > 0; 999 } 1000 1001 /** 1002 * Is this year-month before the specified year-month. 1003 * 1004 * @param other the other year-month to compare to, not null 1005 * @return true if this point is before the specified year-month 1006 */ isBefore(YearMonth other)1007 public boolean isBefore(YearMonth other) { 1008 return compareTo(other) < 0; 1009 } 1010 1011 //----------------------------------------------------------------------- 1012 /** 1013 * Checks if this year-month is equal to another year-month. 1014 * <p> 1015 * The comparison is based on the time-line position of the year-months. 1016 * 1017 * @param obj the object to check, null returns false 1018 * @return true if this is equal to the other year-month 1019 */ 1020 @Override equals(Object obj)1021 public boolean equals(Object obj) { 1022 if (this == obj) { 1023 return true; 1024 } 1025 if (obj instanceof YearMonth) { 1026 YearMonth other = (YearMonth) obj; 1027 return year == other.year && month == other.month; 1028 } 1029 return false; 1030 } 1031 1032 /** 1033 * A hash code for this year-month. 1034 * 1035 * @return a suitable hash code 1036 */ 1037 @Override hashCode()1038 public int hashCode() { 1039 return year ^ (month << 27); 1040 } 1041 1042 //----------------------------------------------------------------------- 1043 /** 1044 * Outputs this year-month as a {@code String}, such as {@code 2007-12}. 1045 * <p> 1046 * The output will be in the format {@code yyyy-MM}: 1047 * 1048 * @return a string representation of this year-month, not null 1049 */ 1050 @Override toString()1051 public String toString() { 1052 int absYear = Math.abs(year); 1053 StringBuilder buf = new StringBuilder(9); 1054 if (absYear < 1000) { 1055 if (year < 0) { 1056 buf.append(year - 10000).deleteCharAt(1); 1057 } else { 1058 buf.append(year + 10000).deleteCharAt(0); 1059 } 1060 } else { 1061 buf.append(year); 1062 } 1063 return buf.append(month < 10 ? "-0" : "-") 1064 .append(month) 1065 .toString(); 1066 } 1067 1068 /** 1069 * Outputs this year-month as a {@code String} using the formatter. 1070 * <p> 1071 * This year-month will be passed to the formatter 1072 * {@link DateTimeFormatter#format(TemporalAccessor) print method}. 1073 * 1074 * @param formatter the formatter to use, not null 1075 * @return the formatted year-month string, not null 1076 * @throws DateTimeException if an error occurs during printing 1077 */ format(DateTimeFormatter formatter)1078 public String format(DateTimeFormatter formatter) { 1079 Jdk8Methods.requireNonNull(formatter, "formatter"); 1080 return formatter.format(this); 1081 } 1082 1083 //----------------------------------------------------------------------- writeReplace()1084 private Object writeReplace() { 1085 return new Ser(Ser.YEAR_MONTH_TYPE, this); 1086 } 1087 1088 /** 1089 * Defend against malicious streams. 1090 * @return never 1091 * @throws InvalidObjectException always 1092 */ readResolve()1093 private Object readResolve() throws ObjectStreamException { 1094 throw new InvalidObjectException("Deserialization via serialization delegate"); 1095 } 1096 writeExternal(DataOutput out)1097 void writeExternal(DataOutput out) throws IOException { 1098 out.writeInt(year); 1099 out.writeByte(month); 1100 } 1101 readExternal(DataInput in)1102 static YearMonth readExternal(DataInput in) throws IOException { 1103 int year = in.readInt(); 1104 byte month = in.readByte(); 1105 return YearMonth.of(year, month); 1106 } 1107 1108 } 1109