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.temporal;
033
034import java.io.Serializable;
035import java.util.Arrays;
036import java.util.List;
037import java.util.Locale;
038import java.util.Objects;
039
040import org.threeten.bp.Clock;
041import org.threeten.bp.DateTimeException;
042import org.threeten.bp.LocalDate;
043import org.threeten.bp.LocalDateTime;
044import org.threeten.bp.ZoneId;
045import org.threeten.bp.ZonedDateTime;
046
047/**
048 * The ISO calendar system.
049 * <p>
050 * This chronology defines the rules of the ISO calendar system.
051 * This calendar system is based on the ISO-8601 standard, which is the
052 * <i>de facto</i> world calendar.
053 * <p>
054 * The fields are defined as follows:
055 * <p><ul>
056 * <li>era - There are two eras, 'Current Era' (CE) and 'Before Current Era' (BCE).
057 * <li>year-of-era - The year-of-era is the same as the proleptic-year for the current CE era.
058 *  For the BCE era before the ISO epoch the year increases from 1 upwards as time goes backwards.
059 * <li>proleptic-year - The proleptic year is the same as the year-of-era for the
060 *  current era. For the previous era, years have zero, then negative values.
061 * <li>month-of-year - There are 12 months in an ISO year, numbered from 1 to 12.
062 * <li>day-of-month - There are between 28 and 31 days in each of the ISO month, numbered from 1 to 31.
063 *  Months 4, 6, 9 and 11 have 30 days, Months 1, 3, 5, 7, 8, 10 and 12 have 31 days.
064 *  Month 2 has 28 days, or 29 in a leap year.
065 * <li>day-of-year - There are 365 days in a standard ISO year and 366 in a leap year.
066 *  The days are numbered from 1 to 365 or 1 to 366.
067 * <li>leap-year - Leap years occur every 4 years, except where the year is divisble by 100 and not divisble by 400.
068 * </ul><p>
069 *
070 * <h3>Specification for implementors</h3>
071 * This class is immutable and thread-safe.
072 */
073public final class ISOChrono extends Chrono<ISOChrono> implements Serializable {
074
075    /**
076     * Singleton instance of the ISO chronology.
077     */
078    public static final ISOChrono INSTANCE = new ISOChrono();
079    /**
080     * The singleton instance for the era BCE - 'Before Current Era'.
081     * The 'ISO' part of the name emphasizes that this differs from the BCE
082     * era in the Gregorian calendar system.
083     * This has the numeric value of {@code 0}.
084     */
085    public static final Era<ISOChrono> ERA_BCE = ISOEra.BCE;
086    /**
087     * The singleton instance for the era CE - 'Current Era'.
088     * The 'ISO' part of the name emphasizes that this differs from the CE
089     * era in the Gregorian calendar system.
090     * This has the numeric value of {@code 1}.
091     */
092    public static final Era<ISOChrono> ERA_CE = ISOEra.CE;
093
094    /**
095     * Serialization version.
096     */
097    private static final long serialVersionUID = -1440403870442975015L;
098
099    /**
100     * Restricted constructor.
101     */
102    private ISOChrono() {
103    }
104
105    /**
106     * Resolve singleton.
107     *
108     * @return the singleton instance, not null
109     */
110    private Object readResolve() {
111        return INSTANCE;
112    }
113
114    //-----------------------------------------------------------------------
115    /**
116     * Gets the ID of the chronology - 'ISO'.
117     * <p>
118     * The ID uniquely identifies the {@code Chrono}.
119     * It can be used to lookup the {@code Chrono} using {@link #of(String)}.
120     *
121     * @return the chronology ID - 'ISO'
122     * @see #getCalendarType()
123     */
124    @Override
125    public String getId() {
126        return "ISO";
127    }
128
129    /**
130     * Gets the calendar type of the underlying calendar system - 'iso8601'.
131     * <p>
132     * The calendar type is an identifier defined by the
133     * <em>Unicode Locale Data Markup Language (LDML)</em> specification.
134     * It can be used to lookup the {@code Chrono} using {@link #of(String)}.
135     * It can also be used as part of a locale, accessible via
136     * {@link Locale#getUnicodeLocaleType(String)} with the key 'ca'.
137     *
138     * @return the calendar system type - 'iso8601'
139     * @see #getId()
140     */
141    @Override
142    public String getCalendarType() {
143        return "iso8601";
144    }
145
146    //-----------------------------------------------------------------------
147    /**
148     * Obtains an ISO local date from the era, year-of-era, month-of-year
149     * and day-of-month fields.
150     *
151     * @param era  the ISO era, not null
152     * @param yearOfEra  the ISO year-of-era
153     * @param month  the ISO month-of-year
154     * @param dayOfMonth  the ISO day-of-month
155     * @return the ISO local date, not null
156     * @throws DateTimeException if unable to create the date
157     */
158    @Override  // override with covariant return type
159    public LocalDate date(Era<ISOChrono> era, int yearOfEra, int month, int dayOfMonth) {
160        return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
161    }
162
163    /**
164     * Obtains an ISO local date from the proleptic-year, month-of-year
165     * and day-of-month fields.
166     * <p>
167     * This is equivalent to {@link LocalDate#of(int, int, int)}.
168     *
169     * @param prolepticYear  the ISO proleptic-year
170     * @param month  the ISO month-of-year
171     * @param dayOfMonth  the ISO day-of-month
172     * @return the ISO local date, not null
173     * @throws DateTimeException if unable to create the date
174     */
175    @Override  // override with covariant return type
176    public LocalDate date(int prolepticYear, int month, int dayOfMonth) {
177        return LocalDate.of(prolepticYear, month, dayOfMonth);
178    }
179
180    /**
181     * Obtains an ISO local date from the era, year-of-era and day-of-year fields.
182     *
183     * @param era  the ISO era, not null
184     * @param yearOfEra  the ISO year-of-era
185     * @param dayOfYear  the ISO day-of-year
186     * @return the ISO local date, not null
187     * @throws DateTimeException if unable to create the date
188     */
189    @Override  // override with covariant return type
190    public LocalDate dateYearDay(Era<ISOChrono> era, int yearOfEra, int dayOfYear) {
191        return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
192    }
193
194    /**
195     * Obtains an ISO local date from the proleptic-year and day-of-year fields.
196     * <p>
197     * This is equivalent to {@link LocalDate#ofYearDay(int, int)}.
198     *
199     * @param prolepticYear  the ISO proleptic-year
200     * @param dayOfYear  the ISO day-of-year
201     * @return the ISO local date, not null
202     * @throws DateTimeException if unable to create the date
203     */
204    @Override  // override with covariant return type
205    public LocalDate dateYearDay(int prolepticYear, int dayOfYear) {
206        return LocalDate.ofYearDay(prolepticYear, dayOfYear);
207    }
208
209    //-----------------------------------------------------------------------
210    /**
211     * Obtains an ISO local date from another date-time object.
212     * <p>
213     * This is equivalent to {@link LocalDate#from(TemporalAccessor)}.
214     *
215     * @param temporal  the date-time object to convert, not null
216     * @return the ISO local date, not null
217     * @throws DateTimeException if unable to create the date
218     */
219    @Override  // override with covariant return type
220    public LocalDate date(TemporalAccessor temporal) {
221        return LocalDate.from(temporal);
222    }
223
224    /**
225     * Obtains an ISO local date-time from another date-time object.
226     * <p>
227     * This is equivalent to {@link LocalDateTime#from(TemporalAccessor)}.
228     *
229     * @param temporal  the date-time object to convert, not null
230     * @return the ISO local date-time, not null
231     * @throws DateTimeException if unable to create the date-time
232     */
233    @Override  // override with covariant return type
234    public LocalDateTime localDateTime(TemporalAccessor temporal) {
235        return LocalDateTime.from(temporal);
236    }
237
238    /**
239     * Obtains an ISO zoned date-time from another date-time object.
240     * <p>
241     * This is equivalent to {@link ZonedDateTime#from(TemporalAccessor)}.
242     *
243     * @param temporal  the date-time object to convert, not null
244     * @return the ISO zoned date-time, not null
245     * @throws DateTimeException if unable to create the date-time
246     */
247    @Override  // override with covariant return type
248    public ZonedDateTime zonedDateTime(TemporalAccessor temporal) {
249        return ZonedDateTime.from(temporal);
250    }
251
252    //-----------------------------------------------------------------------
253    /**
254     * Obtains the current ISO local date from the system clock in the default time-zone.
255     * <p>
256     * This will query the {@link Clock#systemDefaultZone() system clock} in the default
257     * time-zone to obtain the current date.
258     * <p>
259     * Using this method will prevent the ability to use an alternate clock for testing
260     * because the clock is hard-coded.
261     *
262     * @return the current ISO local date using the system clock and default time-zone, not null
263     * @throws DateTimeException if unable to create the date
264     */
265    @Override  // override with covariant return type
266    public LocalDate dateNow() {
267        return dateNow(Clock.systemDefaultZone());
268    }
269
270    /**
271     * Obtains the current ISO local date from the system clock in the specified time-zone.
272     * <p>
273     * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date.
274     * Specifying the time-zone avoids dependence on the default time-zone.
275     * <p>
276     * Using this method will prevent the ability to use an alternate clock for testing
277     * because the clock is hard-coded.
278     *
279     * @return the current ISO local date using the system clock, not null
280     * @throws DateTimeException if unable to create the date
281     */
282    @Override  // override with covariant return type
283    public LocalDate dateNow(ZoneId zone) {
284        return dateNow(Clock.system(zone));
285    }
286
287    /**
288     * Obtains the current ISO local date from the specified clock.
289     * <p>
290     * This will query the specified clock to obtain the current date - today.
291     * Using this method allows the use of an alternate clock for testing.
292     * The alternate clock may be introduced using {@link Clock dependency injection}.
293     *
294     * @param clock  the clock to use, not null
295     * @return the current ISO local date, not null
296     * @throws DateTimeException if unable to create the date
297     */
298    @Override  // override with covariant return type
299    public LocalDate dateNow(Clock clock) {
300        Objects.requireNonNull(clock, "clock");
301        return date(LocalDate.now(clock));
302    }
303
304    //-----------------------------------------------------------------------
305    /**
306     * Checks if the year is a leap year, according to the ISO proleptic
307     * calendar system rules.
308     * <p>
309     * This method applies the current rules for leap years across the whole time-line.
310     * In general, a year is a leap year if it is divisible by four without
311     * remainder. However, years divisible by 100, are not leap years, with
312     * the exception of years divisible by 400 which are.
313     * <p>
314     * For example, 1904 is a leap year it is divisible by 4.
315     * 1900 was not a leap year as it is divisible by 100, however 2000 was a
316     * leap year as it is divisible by 400.
317     * <p>
318     * The calculation is proleptic - applying the same rules into the far future and far past.
319     * This is historically inaccurate, but is correct for the ISO-8601 standard.
320     *
321     * @param prolepticYear  the ISO proleptic year to check
322     * @return true if the year is leap, false otherwise
323     */
324    @Override
325    public boolean isLeapYear(long prolepticYear) {
326        return ((prolepticYear & 3) == 0) && ((prolepticYear % 100) != 0 || (prolepticYear % 400) == 0);
327    }
328
329    @Override
330    public int prolepticYear(Era<ISOChrono> era, int yearOfEra) {
331        if (era instanceof ISOEra == false) {
332            throw new DateTimeException("Era must be ISOEra");
333        }
334        return (era == ISOEra.CE ? yearOfEra : 1 - yearOfEra);
335    }
336
337    @Override
338    public Era<ISOChrono> eraOf(int eraValue) {
339        return ISOEra.of(eraValue);
340    }
341
342    @Override
343    public List<Era<ISOChrono>> eras() {
344        return Arrays.<Era<ISOChrono>>asList(ISOEra.values());
345    }
346
347    //-----------------------------------------------------------------------
348    @Override
349    public ValueRange range(ChronoField field) {
350        return field.range();
351    }
352
353}