001/*
002 * Copyright (c) 2007-2013, Stephen Colebourne & Michael Nascimento Santos
003 *
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions are met:
008 *
009 *  * Redistributions of source code must retain the above copyright notice,
010 *    this list of conditions and the following disclaimer.
011 *
012 *  * Redistributions in binary form must reproduce the above copyright notice,
013 *    this list of conditions and the following disclaimer in the documentation
014 *    and/or other materials provided with the distribution.
015 *
016 *  * Neither the name of JSR-310 nor the names of its contributors
017 *    may be used to endorse or promote products derived from this software
018 *    without specific prior written permission.
019 *
020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031 */
032package org.threeten.bp;
033
034import static org.threeten.bp.temporal.ChronoField.MONTH_OF_YEAR;
035import static org.threeten.bp.temporal.ChronoUnit.MONTHS;
036
037import java.util.Locale;
038
039import org.threeten.bp.format.DateTimeFormatterBuilder;
040import org.threeten.bp.format.TextStyle;
041import org.threeten.bp.temporal.Chrono;
042import org.threeten.bp.temporal.ChronoField;
043import org.threeten.bp.temporal.ISOChrono;
044import org.threeten.bp.temporal.Temporal;
045import org.threeten.bp.temporal.TemporalAccessor;
046import org.threeten.bp.temporal.TemporalAdjuster;
047import org.threeten.bp.temporal.TemporalField;
048import org.threeten.bp.temporal.TemporalQueries;
049import org.threeten.bp.temporal.TemporalQuery;
050import org.threeten.bp.temporal.ValueRange;
051
052/**
053 * A month-of-year, such as 'July'.
054 * <p>
055 * {@code Month} is an enum representing the 12 months of the year -
056 * January, February, March, April, May, June, July, August, September, October,
057 * November and December.
058 * <p>
059 * In addition to the textual enum name, each month-of-year has an {@code int} value.
060 * The {@code int} value follows normal usage and the ISO-8601 standard,
061 * from 1 (January) to 12 (December). It is recommended that applications use the enum
062 * rather than the {@code int} value to ensure code clarity.
063 * <p>
064 * <b>Do not use {@code ordinal()} to obtain the numeric representation of {@code Month}.
065 * Use {@code getValue()} instead.</b>
066 * <p>
067 * This enum represents a common concept that is found in many calendar systems.
068 * As such, this enum may be used by any calendar system that has the month-of-year
069 * concept defined exactly equivalent to the ISO-8601 calendar system.
070 *
071 * <h3>Specification for implementors</h3>
072 * This is an immutable and thread-safe enum.
073 */
074public enum Month implements TemporalAccessor, TemporalAdjuster {
075
076    /**
077     * The singleton instance for the month of January with 31 days.
078     * This has the numeric value of {@code 1}.
079     */
080    JANUARY,
081    /**
082     * The singleton instance for the month of February with 28 days, or 29 in a leap year.
083     * This has the numeric value of {@code 2}.
084     */
085    FEBRUARY,
086    /**
087     * The singleton instance for the month of March with 31 days.
088     * This has the numeric value of {@code 3}.
089     */
090    MARCH,
091    /**
092     * The singleton instance for the month of April with 30 days.
093     * This has the numeric value of {@code 4}.
094     */
095    APRIL,
096    /**
097     * The singleton instance for the month of May with 31 days.
098     * This has the numeric value of {@code 5}.
099     */
100    MAY,
101    /**
102     * The singleton instance for the month of June with 30 days.
103     * This has the numeric value of {@code 6}.
104     */
105    JUNE,
106    /**
107     * The singleton instance for the month of July with 31 days.
108     * This has the numeric value of {@code 7}.
109     */
110    JULY,
111    /**
112     * The singleton instance for the month of August with 31 days.
113     * This has the numeric value of {@code 8}.
114     */
115    AUGUST,
116    /**
117     * The singleton instance for the month of September with 30 days.
118     * This has the numeric value of {@code 9}.
119     */
120    SEPTEMBER,
121    /**
122     * The singleton instance for the month of October with 31 days.
123     * This has the numeric value of {@code 10}.
124     */
125    OCTOBER,
126    /**
127     * The singleton instance for the month of November with 30 days.
128     * This has the numeric value of {@code 11}.
129     */
130    NOVEMBER,
131    /**
132     * The singleton instance for the month of December with 31 days.
133     * This has the numeric value of {@code 12}.
134     */
135    DECEMBER;
136    /**
137     * Private cache of all the constants.
138     */
139    private static final Month[] ENUMS = Month.values();
140
141    //-----------------------------------------------------------------------
142    /**
143     * Obtains an instance of {@code Month} from an {@code int} value.
144     * <p>
145     * {@code Month} is an enum representing the 12 months of the year.
146     * This factory allows the enum to be obtained from the {@code int} value.
147     * The {@code int} value follows the ISO-8601 standard, from 1 (January) to 12 (December).
148     *
149     * @param month  the month-of-year to represent, from 1 (January) to 12 (December)
150     * @return the month-of-year, not null
151     * @throws DateTimeException if the month-of-year is invalid
152     */
153    public static Month of(int month) {
154        if (month < 1 || month > 12) {
155            throw new DateTimeException("Invalid value for MonthOfYear: " + month);
156        }
157        return ENUMS[month - 1];
158    }
159
160    //-----------------------------------------------------------------------
161    /**
162     * Obtains an instance of {@code Month} from a temporal object.
163     * <p>
164     * A {@code TemporalAccessor} represents some form of date and time information.
165     * This factory converts the arbitrary temporal object to an instance of {@code Month}.
166     * <p>
167     * The conversion extracts the {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} field.
168     * The extraction is only permitted if the temporal object has an ISO
169     * chronology, or can be converted to a {@code LocalDate}.
170     * <p>
171     * This method matches the signature of the functional interface {@link TemporalQuery}
172     * allowing it to be used in queries via method reference, {@code Month::from}.
173     *
174     * @param temporal  the temporal object to convert, not null
175     * @return the month-of-year, not null
176     * @throws DateTimeException if unable to convert to a {@code Month}
177     */
178    public static Month from(TemporalAccessor temporal) {
179        if (temporal instanceof Month) {
180            return (Month) temporal;
181        }
182        try {
183            if (ISOChrono.INSTANCE.equals(Chrono.from(temporal)) == false) {
184                temporal = LocalDate.from(temporal);
185            }
186            return of(temporal.get(MONTH_OF_YEAR));
187        } catch (DateTimeException ex) {
188            throw new DateTimeException("Unable to obtain Month from TemporalAccessor: " + temporal.getClass(), ex);
189        }
190    }
191
192    //-----------------------------------------------------------------------
193    /**
194     * Gets the month-of-year {@code int} value.
195     * <p>
196     * The values are numbered following the ISO-8601 standard,
197     * from 1 (January) to 12 (December).
198     *
199     * @return the month-of-year, from 1 (January) to 12 (December)
200     */
201    public int getValue() {
202        return ordinal() + 1;
203    }
204
205    //-----------------------------------------------------------------------
206    /**
207     * Gets the textual representation, such as 'Jan' or 'December'.
208     * <p>
209     * This returns the textual name used to identify the month-of-year.
210     * The parameters control the length of the returned text and the locale.
211     * <p>
212     * If no textual mapping is found then the {@link #getValue() numeric value} is returned.
213     *
214     * @param style  the length of the text required, not null
215     * @param locale  the locale to use, not null
216     * @return the text value of the month-of-year, not null
217     */
218    public String getText(TextStyle style, Locale locale) {
219        return new DateTimeFormatterBuilder().appendText(MONTH_OF_YEAR, style).toFormatter(locale).print(this);
220    }
221
222    //-----------------------------------------------------------------------
223    /**
224     * Checks if the specified field is supported.
225     * <p>
226     * This checks if this month-of-year can be queried for the specified field.
227     * If false, then calling the {@link #range(TemporalField) range} and
228     * {@link #get(TemporalField) get} methods will throw an exception.
229     * <p>
230     * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then
231     * this method returns true.
232     * All other {@code ChronoField} instances will return false.
233     * <p>
234     * If the field is not a {@code ChronoField}, then the result of this method
235     * is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
236     * passing {@code this} as the argument.
237     * Whether the field is supported is determined by the field.
238     *
239     * @param field  the field to check, null returns false
240     * @return true if the field is supported on this month-of-year, false if not
241     */
242    @Override
243    public boolean isSupported(TemporalField field) {
244        if (field instanceof ChronoField) {
245            return field == MONTH_OF_YEAR;
246        }
247        return field != null && field.doIsSupported(this);
248    }
249
250    /**
251     * Gets the range of valid values for the specified field.
252     * <p>
253     * The range object expresses the minimum and maximum valid values for a field.
254     * This month is used to enhance the accuracy of the returned range.
255     * If it is not possible to return the range, because the field is not supported
256     * or for some other reason, an exception is thrown.
257     * <p>
258     * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then the
259     * range of the month-of-year, from 1 to 12, will be returned.
260     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
261     * <p>
262     * If the field is not a {@code ChronoField}, then the result of this method
263     * is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
264     * passing {@code this} as the argument.
265     * Whether the range can be obtained is determined by the field.
266     *
267     * @param field  the field to query the range for, not null
268     * @return the range of valid values for the field, not null
269     * @throws DateTimeException if the range for the field cannot be obtained
270     */
271    @Override
272    public ValueRange range(TemporalField field) {
273        if (field == MONTH_OF_YEAR) {
274            return field.range();
275        } else if (field instanceof ChronoField) {
276            throw new DateTimeException("Unsupported field: " + field.getName());
277        }
278        return field.doRange(this);
279    }
280
281    /**
282     * Gets the value of the specified field from this month-of-year as an {@code int}.
283     * <p>
284     * This queries this month for the value for the specified field.
285     * The returned value will always be within the valid range of values for the field.
286     * If it is not possible to return the value, because the field is not supported
287     * or for some other reason, an exception is thrown.
288     * <p>
289     * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then the
290     * value of the month-of-year, from 1 to 12, will be returned.
291     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
292     * <p>
293     * If the field is not a {@code ChronoField}, then the result of this method
294     * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
295     * passing {@code this} as the argument. Whether the value can be obtained,
296     * and what the value represents, is determined by the field.
297     *
298     * @param field  the field to get, not null
299     * @return the value for the field, within the valid range of values
300     * @throws DateTimeException if a value for the field cannot be obtained
301     * @throws DateTimeException if the range of valid values for the field exceeds an {@code int}
302     * @throws DateTimeException if the value is outside the range of valid values for the field
303     * @throws ArithmeticException if numeric overflow occurs
304     */
305    @Override
306    public int get(TemporalField field) {
307        if (field == MONTH_OF_YEAR) {
308            return getValue();
309        }
310        return range(field).checkValidIntValue(getLong(field), field);
311    }
312
313    /**
314     * Gets the value of the specified field from this month-of-year as a {@code long}.
315     * <p>
316     * This queries this month for the value for the specified field.
317     * If it is not possible to return the value, because the field is not supported
318     * or for some other reason, an exception is thrown.
319     * <p>
320     * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then the
321     * value of the month-of-year, from 1 to 12, will be returned.
322     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
323     * <p>
324     * If the field is not a {@code ChronoField}, then the result of this method
325     * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
326     * passing {@code this} as the argument. Whether the value can be obtained,
327     * and what the value represents, is determined by the field.
328     *
329     * @param field  the field to get, not null
330     * @return the value for the field
331     * @throws DateTimeException if a value for the field cannot be obtained
332     * @throws ArithmeticException if numeric overflow occurs
333     */
334    @Override
335    public long getLong(TemporalField field) {
336        if (field == MONTH_OF_YEAR) {
337            return getValue();
338        } else if (field instanceof ChronoField) {
339            throw new DateTimeException("Unsupported field: " + field.getName());
340        }
341        return field.doGet(this);
342    }
343
344    //-----------------------------------------------------------------------
345    /**
346     * Returns the month-of-year that is the specified number of quarters after this one.
347     * <p>
348     * The calculation rolls around the end of the year from December to January.
349     * The specified period may be negative.
350     * <p>
351     * This instance is immutable and unaffected by this method call.
352     *
353     * @param months  the months to add, positive or negative
354     * @return the resulting month, not null
355     */
356    public Month plus(long months) {
357        int amount = (int) (months % 12);
358        return ENUMS[(ordinal() + (amount + 12)) % 12];
359    }
360
361    /**
362     * Returns the month-of-year that is the specified number of months before this one.
363     * <p>
364     * The calculation rolls around the start of the year from January to December.
365     * The specified period may be negative.
366     * <p>
367     * This instance is immutable and unaffected by this method call.
368     *
369     * @param months  the months to subtract, positive or negative
370     * @return the resulting month, not null
371     */
372    public Month minus(long months) {
373        return plus(-(months % 12));
374    }
375
376    //-----------------------------------------------------------------------
377    /**
378     * Gets the length of this month in days.
379     * <p>
380     * This takes a flag to determine whether to return the length for a leap year or not.
381     * <p>
382     * February has 28 days in a standard year and 29 days in a leap year.
383     * April, June, September and November have 30 days.
384     * All other months have 31 days.
385     *
386     * @param leapYear  true if the length is required for a leap year
387     * @return the length of this month in days, from 28 to 31
388     */
389    public int length(boolean leapYear) {
390        switch (this) {
391            case FEBRUARY:
392                return (leapYear ? 29 : 28);
393            case APRIL:
394            case JUNE:
395            case SEPTEMBER:
396            case NOVEMBER:
397                return 30;
398            default:
399                return 31;
400        }
401    }
402
403    /**
404     * Gets the minimum length of this month in days.
405     * <p>
406     * February has a minimum length of 28 days.
407     * April, June, September and November have 30 days.
408     * All other months have 31 days.
409     *
410     * @return the minimum length of this month in days, from 28 to 31
411     */
412    public int minLength() {
413        switch (this) {
414            case FEBRUARY:
415                return 28;
416            case APRIL:
417            case JUNE:
418            case SEPTEMBER:
419            case NOVEMBER:
420                return 30;
421            default:
422                return 31;
423        }
424    }
425
426    /**
427     * Gets the maximum length of this month in days.
428     * <p>
429     * February has a maximum length of 29 days.
430     * April, June, September and November have 30 days.
431     * All other months have 31 days.
432     *
433     * @return the maximum length of this month in days, from 29 to 31
434     */
435    public int maxLength() {
436        switch (this) {
437            case FEBRUARY:
438                return 29;
439            case APRIL:
440            case JUNE:
441            case SEPTEMBER:
442            case NOVEMBER:
443                return 30;
444            default:
445                return 31;
446        }
447    }
448
449    //-----------------------------------------------------------------------
450    /**
451     * Gets the day-of-year corresponding to the first day of this month.
452     * <p>
453     * This returns the day-of-year that this month begins on, using the leap
454     * year flag to determine the length of February.
455     *
456     * @param leapYear  true if the length is required for a leap year
457     * @return the day of year corresponding to the first day of this month, from 1 to 336
458     */
459    public int firstDayOfYear(boolean leapYear) {
460        int leap = leapYear ? 1 : 0;
461        switch (this) {
462            case JANUARY:
463                return 1;
464            case FEBRUARY:
465                return 32;
466            case MARCH:
467                return 60 + leap;
468            case APRIL:
469                return 91 + leap;
470            case MAY:
471                return 121 + leap;
472            case JUNE:
473                return 152 + leap;
474            case JULY:
475                return 182 + leap;
476            case AUGUST:
477                return 213 + leap;
478            case SEPTEMBER:
479                return 244 + leap;
480            case OCTOBER:
481                return 274 + leap;
482            case NOVEMBER:
483                return 305 + leap;
484            case DECEMBER:
485            default:
486                return 335 + leap;
487        }
488    }
489
490    /**
491     * Gets the month corresponding to the first month of this quarter.
492     * <p>
493     * The year can be divided into four quarters.
494     * This method returns the first month of the quarter for the base month.
495     * January, February and March return January.
496     * April, May and June return April.
497     * July, August and September return July.
498     * October, November and December return October.
499     *
500     * @return the first month of the quarter corresponding to this month, not null
501     */
502    public Month firstMonthOfQuarter() {
503        return ENUMS[(ordinal() / 3) * 3];
504    }
505
506    //-----------------------------------------------------------------------
507    /**
508     * Queries this month-of-year using the specified query.
509     * <p>
510     * This queries this month-of-year using the specified query strategy object.
511     * The {@code TemporalQuery} object defines the logic to be used to
512     * obtain the result. Read the documentation of the query to understand
513     * what the result of this method will be.
514     * <p>
515     * The result of this method is obtained by invoking the
516     * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the
517     * specified query passing {@code this} as the argument.
518     *
519     * @param <R> the type of the result
520     * @param query  the query to invoke, not null
521     * @return the query result, null may be returned (defined by the query)
522     * @throws DateTimeException if unable to query (defined by the query)
523     * @throws ArithmeticException if numeric overflow occurs (defined by the query)
524     */
525    @SuppressWarnings("unchecked")
526    @Override
527    public <R> R query(TemporalQuery<R> query) {
528        if (query == TemporalQueries.chrono()) {
529            return (R) ISOChrono.INSTANCE;
530        } else if (query == TemporalQueries.precision()) {
531            return (R) MONTHS;
532        } else if (query == TemporalQueries.zoneId()) {
533            return null;
534        }
535        return query.queryFrom(this);
536    }
537
538    /**
539     * Adjusts the specified temporal object to have this month-of-year.
540     * <p>
541     * This returns a temporal object of the same observable type as the input
542     * with the month-of-year changed to be the same as this.
543     * <p>
544     * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
545     * passing {@link ChronoField#MONTH_OF_YEAR} as the field.
546     * If the specified temporal object does not use the ISO calendar system then
547     * a {@code DateTimeException} is thrown.
548     * <p>
549     * In most cases, it is clearer to reverse the calling pattern by using
550     * {@link Temporal#with(TemporalAdjuster)}:
551     * <pre>
552     *   // these two lines are equivalent, but the second approach is recommended
553     *   temporal = thisMonth.adjustInto(temporal);
554     *   temporal = temporal.with(thisMonth);
555     * </pre>
556     * <p>
557     * For example, given a date in May, the following are output:
558     * <pre>
559     *   dateInMay.with(JANUARY);    // four months earlier
560     *   dateInMay.with(APRIL);      // one months earlier
561     *   dateInMay.with(MAY);        // same date
562     *   dateInMay.with(JUNE);       // one month later
563     *   dateInMay.with(DECEMBER);   // seven months later
564     * </pre>
565     * <p>
566     * This instance is immutable and unaffected by this method call.
567     *
568     * @param temporal  the target object to be adjusted, not null
569     * @return the adjusted object, not null
570     * @throws DateTimeException if unable to make the adjustment
571     * @throws ArithmeticException if numeric overflow occurs
572     */
573    @Override
574    public Temporal adjustInto(Temporal temporal) {
575        if (Chrono.from(temporal).equals(ISOChrono.INSTANCE) == false) {
576            throw new DateTimeException("Adjustment only supported on ISO date-time");
577        }
578        return temporal.with(MONTH_OF_YEAR, getValue());
579    }
580
581}