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.MONTH_OF_YEAR; 35 import static org.threeten.bp.temporal.ChronoUnit.MONTHS; 36 37 import java.util.Locale; 38 39 import org.threeten.bp.chrono.Chronology; 40 import org.threeten.bp.chrono.IsoChronology; 41 import org.threeten.bp.format.DateTimeFormatterBuilder; 42 import org.threeten.bp.format.TextStyle; 43 import org.threeten.bp.temporal.ChronoField; 44 import org.threeten.bp.temporal.Temporal; 45 import org.threeten.bp.temporal.TemporalAccessor; 46 import org.threeten.bp.temporal.TemporalAdjuster; 47 import org.threeten.bp.temporal.TemporalField; 48 import org.threeten.bp.temporal.TemporalQueries; 49 import org.threeten.bp.temporal.TemporalQuery; 50 import org.threeten.bp.temporal.UnsupportedTemporalTypeException; 51 import org.threeten.bp.temporal.ValueRange; 52 53 /** 54 * A month-of-year, such as 'July'. 55 * <p> 56 * {@code Month} is an enum representing the 12 months of the year - 57 * January, February, March, April, May, June, July, August, September, October, 58 * November and December. 59 * <p> 60 * In addition to the textual enum name, each month-of-year has an {@code int} value. 61 * The {@code int} value follows normal usage and the ISO-8601 standard, 62 * from 1 (January) to 12 (December). It is recommended that applications use the enum 63 * rather than the {@code int} value to ensure code clarity. 64 * <p> 65 * <b>Do not use {@code ordinal()} to obtain the numeric representation of {@code Month}. 66 * Use {@code getValue()} instead.</b> 67 * <p> 68 * This enum represents a common concept that is found in many calendar systems. 69 * As such, this enum may be used by any calendar system that has the month-of-year 70 * concept defined exactly equivalent to the ISO-8601 calendar system. 71 * 72 * <h3>Specification for implementors</h3> 73 * This is an immutable and thread-safe enum. 74 */ 75 public enum Month implements TemporalAccessor, TemporalAdjuster { 76 77 /** 78 * The singleton instance for the month of January with 31 days. 79 * This has the numeric value of {@code 1}. 80 */ 81 JANUARY, 82 /** 83 * The singleton instance for the month of February with 28 days, or 29 in a leap year. 84 * This has the numeric value of {@code 2}. 85 */ 86 FEBRUARY, 87 /** 88 * The singleton instance for the month of March with 31 days. 89 * This has the numeric value of {@code 3}. 90 */ 91 MARCH, 92 /** 93 * The singleton instance for the month of April with 30 days. 94 * This has the numeric value of {@code 4}. 95 */ 96 APRIL, 97 /** 98 * The singleton instance for the month of May with 31 days. 99 * This has the numeric value of {@code 5}. 100 */ 101 MAY, 102 /** 103 * The singleton instance for the month of June with 30 days. 104 * This has the numeric value of {@code 6}. 105 */ 106 JUNE, 107 /** 108 * The singleton instance for the month of July with 31 days. 109 * This has the numeric value of {@code 7}. 110 */ 111 JULY, 112 /** 113 * The singleton instance for the month of August with 31 days. 114 * This has the numeric value of {@code 8}. 115 */ 116 AUGUST, 117 /** 118 * The singleton instance for the month of September with 30 days. 119 * This has the numeric value of {@code 9}. 120 */ 121 SEPTEMBER, 122 /** 123 * The singleton instance for the month of October with 31 days. 124 * This has the numeric value of {@code 10}. 125 */ 126 OCTOBER, 127 /** 128 * The singleton instance for the month of November with 30 days. 129 * This has the numeric value of {@code 11}. 130 */ 131 NOVEMBER, 132 /** 133 * The singleton instance for the month of December with 31 days. 134 * This has the numeric value of {@code 12}. 135 */ 136 DECEMBER; 137 /** 138 * Simulate JDK 8 method reference Month::from. 139 */ 140 public static final TemporalQuery<Month> FROM = new TemporalQuery<Month>() { 141 @Override 142 public Month queryFrom(TemporalAccessor temporal) { 143 return Month.from(temporal); 144 } 145 }; 146 /** 147 * Private cache of all the constants. 148 */ 149 private static final Month[] ENUMS = Month.values(); 150 151 //----------------------------------------------------------------------- 152 /** 153 * Obtains an instance of {@code Month} from an {@code int} value. 154 * <p> 155 * {@code Month} is an enum representing the 12 months of the year. 156 * This factory allows the enum to be obtained from the {@code int} value. 157 * The {@code int} value follows the ISO-8601 standard, from 1 (January) to 12 (December). 158 * 159 * @param month the month-of-year to represent, from 1 (January) to 12 (December) 160 * @return the month-of-year, not null 161 * @throws DateTimeException if the month-of-year is invalid 162 */ of(int month)163 public static Month of(int month) { 164 if (month < 1 || month > 12) { 165 throw new DateTimeException("Invalid value for MonthOfYear: " + month); 166 } 167 return ENUMS[month - 1]; 168 } 169 170 //----------------------------------------------------------------------- 171 /** 172 * Obtains an instance of {@code Month} from a temporal object. 173 * <p> 174 * A {@code TemporalAccessor} represents some form of date and time information. 175 * This factory converts the arbitrary temporal object to an instance of {@code Month}. 176 * <p> 177 * The conversion extracts the {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} field. 178 * The extraction is only permitted if the temporal object has an ISO 179 * chronology, or can be converted to a {@code LocalDate}. 180 * <p> 181 * This method matches the signature of the functional interface {@link TemporalQuery} 182 * allowing it to be used in queries via method reference, {@code Month::from}. 183 * 184 * @param temporal the temporal object to convert, not null 185 * @return the month-of-year, not null 186 * @throws DateTimeException if unable to convert to a {@code Month} 187 */ from(TemporalAccessor temporal)188 public static Month from(TemporalAccessor temporal) { 189 if (temporal instanceof Month) { 190 return (Month) temporal; 191 } 192 try { 193 if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) { 194 temporal = LocalDate.from(temporal); 195 } 196 return of(temporal.get(MONTH_OF_YEAR)); 197 } catch (DateTimeException ex) { 198 throw new DateTimeException("Unable to obtain Month from TemporalAccessor: " + 199 temporal + ", type " + temporal.getClass().getName(), ex); 200 } 201 } 202 203 //----------------------------------------------------------------------- 204 /** 205 * Gets the month-of-year {@code int} value. 206 * <p> 207 * The values are numbered following the ISO-8601 standard, 208 * from 1 (January) to 12 (December). 209 * 210 * @return the month-of-year, from 1 (January) to 12 (December) 211 */ getValue()212 public int getValue() { 213 return ordinal() + 1; 214 } 215 216 //----------------------------------------------------------------------- 217 /** 218 * Gets the textual representation, such as 'Jan' or 'December'. 219 * <p> 220 * This returns the textual name used to identify the month-of-year. 221 * The parameters control the length of the returned text and the locale. 222 * <p> 223 * If no textual mapping is found then the {@link #getValue() numeric value} is returned. 224 * 225 * @param style the length of the text required, not null 226 * @param locale the locale to use, not null 227 * @return the text value of the month-of-year, not null 228 */ getDisplayName(TextStyle style, Locale locale)229 public String getDisplayName(TextStyle style, Locale locale) { 230 return new DateTimeFormatterBuilder().appendText(MONTH_OF_YEAR, style).toFormatter(locale).format(this); 231 } 232 233 //----------------------------------------------------------------------- 234 /** 235 * Checks if the specified field is supported. 236 * <p> 237 * This checks if this month-of-year can be queried for the specified field. 238 * If false, then calling the {@link #range(TemporalField) range} and 239 * {@link #get(TemporalField) get} methods will throw an exception. 240 * <p> 241 * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then 242 * this method returns true. 243 * All other {@code ChronoField} instances will return false. 244 * <p> 245 * If the field is not a {@code ChronoField}, then the result of this method 246 * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)} 247 * passing {@code this} as the argument. 248 * Whether the field is supported is determined by the field. 249 * 250 * @param field the field to check, null returns false 251 * @return true if the field is supported on this month-of-year, false if not 252 */ 253 @Override isSupported(TemporalField field)254 public boolean isSupported(TemporalField field) { 255 if (field instanceof ChronoField) { 256 return field == MONTH_OF_YEAR; 257 } 258 return field != null && field.isSupportedBy(this); 259 } 260 261 /** 262 * Gets the range of valid values for the specified field. 263 * <p> 264 * The range object expresses the minimum and maximum valid values for a field. 265 * This month is used to enhance the accuracy of the returned range. 266 * If it is not possible to return the range, because the field is not supported 267 * or for some other reason, an exception is thrown. 268 * <p> 269 * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then the 270 * range of the month-of-year, from 1 to 12, will be returned. 271 * All other {@code ChronoField} instances will throw a {@code DateTimeException}. 272 * <p> 273 * If the field is not a {@code ChronoField}, then the result of this method 274 * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)} 275 * passing {@code this} as the argument. 276 * Whether the range can be obtained is determined by the field. 277 * 278 * @param field the field to query the range for, not null 279 * @return the range of valid values for the field, not null 280 * @throws DateTimeException if the range for the field cannot be obtained 281 */ 282 @Override range(TemporalField field)283 public ValueRange range(TemporalField field) { 284 if (field == MONTH_OF_YEAR) { 285 return field.range(); 286 } else if (field instanceof ChronoField) { 287 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 288 } 289 return field.rangeRefinedBy(this); 290 } 291 292 /** 293 * Gets the value of the specified field from this month-of-year as an {@code int}. 294 * <p> 295 * This queries this month for the value for the specified field. 296 * The returned value will always be within the valid range of values for the field. 297 * If it is not possible to return the value, because the field is not supported 298 * or for some other reason, an exception is thrown. 299 * <p> 300 * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then the 301 * value of the month-of-year, from 1 to 12, will be returned. 302 * All other {@code ChronoField} instances will throw a {@code DateTimeException}. 303 * <p> 304 * If the field is not a {@code ChronoField}, then the result of this method 305 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} 306 * passing {@code this} as the argument. Whether the value can be obtained, 307 * and what the value represents, is determined by the field. 308 * 309 * @param field the field to get, not null 310 * @return the value for the field, within the valid range of values 311 * @throws DateTimeException if a value for the field cannot be obtained 312 * @throws DateTimeException if the range of valid values for the field exceeds an {@code int} 313 * @throws DateTimeException if the value is outside the range of valid values for the field 314 * @throws ArithmeticException if numeric overflow occurs 315 */ 316 @Override get(TemporalField field)317 public int get(TemporalField field) { 318 if (field == MONTH_OF_YEAR) { 319 return getValue(); 320 } 321 return range(field).checkValidIntValue(getLong(field), field); 322 } 323 324 /** 325 * Gets the value of the specified field from this month-of-year as a {@code long}. 326 * <p> 327 * This queries this month for the value for the specified field. 328 * If it is not possible to return the value, because the field is not supported 329 * or for some other reason, an exception is thrown. 330 * <p> 331 * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then the 332 * value of the month-of-year, from 1 to 12, will be returned. 333 * All other {@code ChronoField} instances will throw a {@code DateTimeException}. 334 * <p> 335 * If the field is not a {@code ChronoField}, then the result of this method 336 * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} 337 * passing {@code this} as the argument. Whether the value can be obtained, 338 * and what the value represents, is determined by the field. 339 * 340 * @param field the field to get, not null 341 * @return the value for the field 342 * @throws DateTimeException if a value for the field cannot be obtained 343 * @throws ArithmeticException if numeric overflow occurs 344 */ 345 @Override getLong(TemporalField field)346 public long getLong(TemporalField field) { 347 if (field == MONTH_OF_YEAR) { 348 return getValue(); 349 } else if (field instanceof ChronoField) { 350 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 351 } 352 return field.getFrom(this); 353 } 354 355 //----------------------------------------------------------------------- 356 /** 357 * Returns the month-of-year that is the specified number of months after this one. 358 * <p> 359 * The calculation rolls around the end of the year from December to January. 360 * The specified period may be negative. 361 * <p> 362 * This instance is immutable and unaffected by this method call. 363 * 364 * @param months the months to add, positive or negative 365 * @return the resulting month, not null 366 */ plus(long months)367 public Month plus(long months) { 368 int amount = (int) (months % 12); 369 return ENUMS[(ordinal() + (amount + 12)) % 12]; 370 } 371 372 /** 373 * Returns the month-of-year that is the specified number of months before this one. 374 * <p> 375 * The calculation rolls around the start of the year from January to December. 376 * The specified period may be negative. 377 * <p> 378 * This instance is immutable and unaffected by this method call. 379 * 380 * @param months the months to subtract, positive or negative 381 * @return the resulting month, not null 382 */ minus(long months)383 public Month minus(long months) { 384 return plus(-(months % 12)); 385 } 386 387 //----------------------------------------------------------------------- 388 /** 389 * Gets the length of this month in days. 390 * <p> 391 * This takes a flag to determine whether to return the length for a leap year or not. 392 * <p> 393 * February has 28 days in a standard year and 29 days in a leap year. 394 * April, June, September and November have 30 days. 395 * All other months have 31 days. 396 * 397 * @param leapYear true if the length is required for a leap year 398 * @return the length of this month in days, from 28 to 31 399 */ length(boolean leapYear)400 public int length(boolean leapYear) { 401 switch (this) { 402 case FEBRUARY: 403 return (leapYear ? 29 : 28); 404 case APRIL: 405 case JUNE: 406 case SEPTEMBER: 407 case NOVEMBER: 408 return 30; 409 default: 410 return 31; 411 } 412 } 413 414 /** 415 * Gets the minimum length of this month in days. 416 * <p> 417 * February has a minimum length of 28 days. 418 * April, June, September and November have 30 days. 419 * All other months have 31 days. 420 * 421 * @return the minimum length of this month in days, from 28 to 31 422 */ minLength()423 public int minLength() { 424 switch (this) { 425 case FEBRUARY: 426 return 28; 427 case APRIL: 428 case JUNE: 429 case SEPTEMBER: 430 case NOVEMBER: 431 return 30; 432 default: 433 return 31; 434 } 435 } 436 437 /** 438 * Gets the maximum length of this month in days. 439 * <p> 440 * February has a maximum length of 29 days. 441 * April, June, September and November have 30 days. 442 * All other months have 31 days. 443 * 444 * @return the maximum length of this month in days, from 29 to 31 445 */ maxLength()446 public int maxLength() { 447 switch (this) { 448 case FEBRUARY: 449 return 29; 450 case APRIL: 451 case JUNE: 452 case SEPTEMBER: 453 case NOVEMBER: 454 return 30; 455 default: 456 return 31; 457 } 458 } 459 460 //----------------------------------------------------------------------- 461 /** 462 * Gets the day-of-year corresponding to the first day of this month. 463 * <p> 464 * This returns the day-of-year that this month begins on, using the leap 465 * year flag to determine the length of February. 466 * 467 * @param leapYear true if the length is required for a leap year 468 * @return the day of year corresponding to the first day of this month, from 1 to 336 469 */ firstDayOfYear(boolean leapYear)470 public int firstDayOfYear(boolean leapYear) { 471 int leap = leapYear ? 1 : 0; 472 switch (this) { 473 case JANUARY: 474 return 1; 475 case FEBRUARY: 476 return 32; 477 case MARCH: 478 return 60 + leap; 479 case APRIL: 480 return 91 + leap; 481 case MAY: 482 return 121 + leap; 483 case JUNE: 484 return 152 + leap; 485 case JULY: 486 return 182 + leap; 487 case AUGUST: 488 return 213 + leap; 489 case SEPTEMBER: 490 return 244 + leap; 491 case OCTOBER: 492 return 274 + leap; 493 case NOVEMBER: 494 return 305 + leap; 495 case DECEMBER: 496 default: 497 return 335 + leap; 498 } 499 } 500 501 /** 502 * Gets the month corresponding to the first month of this quarter. 503 * <p> 504 * The year can be divided into four quarters. 505 * This method returns the first month of the quarter for the base month. 506 * January, February and March return January. 507 * April, May and June return April. 508 * July, August and September return July. 509 * October, November and December return October. 510 * 511 * @return the first month of the quarter corresponding to this month, not null 512 */ firstMonthOfQuarter()513 public Month firstMonthOfQuarter() { 514 return ENUMS[(ordinal() / 3) * 3]; 515 } 516 517 //----------------------------------------------------------------------- 518 /** 519 * Queries this month-of-year using the specified query. 520 * <p> 521 * This queries this month-of-year using the specified query strategy object. 522 * The {@code TemporalQuery} object defines the logic to be used to 523 * obtain the result. Read the documentation of the query to understand 524 * what the result of this method will be. 525 * <p> 526 * The result of this method is obtained by invoking the 527 * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the 528 * specified query passing {@code this} as the argument. 529 * 530 * @param <R> the type of the result 531 * @param query the query to invoke, not null 532 * @return the query result, null may be returned (defined by the query) 533 * @throws DateTimeException if unable to query (defined by the query) 534 * @throws ArithmeticException if numeric overflow occurs (defined by the query) 535 */ 536 @SuppressWarnings("unchecked") 537 @Override query(TemporalQuery<R> query)538 public <R> R query(TemporalQuery<R> query) { 539 if (query == TemporalQueries.chronology()) { 540 return (R) IsoChronology.INSTANCE; 541 } else if (query == TemporalQueries.precision()) { 542 return (R) MONTHS; 543 } else if (query == TemporalQueries.localDate() || query == TemporalQueries.localTime() || 544 query == TemporalQueries.zone() || query == TemporalQueries.zoneId() || query == TemporalQueries.offset()) { 545 return null; 546 } 547 return query.queryFrom(this); 548 } 549 550 /** 551 * Adjusts the specified temporal object to have this month-of-year. 552 * <p> 553 * This returns a temporal object of the same observable type as the input 554 * with the month-of-year changed to be the same as this. 555 * <p> 556 * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)} 557 * passing {@link ChronoField#MONTH_OF_YEAR} as the field. 558 * If the specified temporal object does not use the ISO calendar system then 559 * a {@code DateTimeException} is thrown. 560 * <p> 561 * In most cases, it is clearer to reverse the calling pattern by using 562 * {@link Temporal#with(TemporalAdjuster)}: 563 * <pre> 564 * // these two lines are equivalent, but the second approach is recommended 565 * temporal = thisMonth.adjustInto(temporal); 566 * temporal = temporal.with(thisMonth); 567 * </pre> 568 * <p> 569 * For example, given a date in May, the following are output: 570 * <pre> 571 * dateInMay.with(JANUARY); // four months earlier 572 * dateInMay.with(APRIL); // one months earlier 573 * dateInMay.with(MAY); // same date 574 * dateInMay.with(JUNE); // one month later 575 * dateInMay.with(DECEMBER); // seven months later 576 * </pre> 577 * <p> 578 * This instance is immutable and unaffected by this method call. 579 * 580 * @param temporal the target object to be adjusted, not null 581 * @return the adjusted object, not null 582 * @throws DateTimeException if unable to make the adjustment 583 * @throws ArithmeticException if numeric overflow occurs 584 */ 585 @Override adjustInto(Temporal temporal)586 public Temporal adjustInto(Temporal temporal) { 587 if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) { 588 throw new DateTimeException("Adjustment only supported on ISO date-time"); 589 } 590 return temporal.with(MONTH_OF_YEAR, getValue()); 591 } 592 593 } 594