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 org.threeten.bp.Duration;
035
036/**
037 * A standard set of date periods units.
038 * <p>
039 * This set of units provide unit-based access to manipulate a date, time or date-time.
040 * The standard set of units can be extended by implementing {@link TemporalUnit}.
041 * <p>
042 * These units are intended to be applicable in multiple calendar systems.
043 * For example, most non-ISO calendar systems define units of years, months and days,
044 * just with slightly different rules.
045 * The documentation of each unit explains how it operates.
046 *
047 * <h3>Specification for implementors</h3>
048 * This is a final, immutable and thread-safe enum.
049 */
050public enum ChronoUnit implements TemporalUnit {
051
052    /**
053     * Unit that represents the concept of a nanosecond, the smallest supported unit of time.
054     * For the ISO calendar system, it is equal to the 1,000,000,000th part of the second unit.
055     */
056    NANOS("Nanos", Duration.ofNanos(1)),
057    /**
058     * Unit that represents the concept of a microsecond.
059     * For the ISO calendar system, it is equal to the 1,000,000th part of the second unit.
060     */
061    MICROS("Micros", Duration.ofNanos(1000)),
062    /**
063     * Unit that represents the concept of a millisecond.
064     * For the ISO calendar system, it is equal to the 1000th part of the second unit.
065     */
066    MILLIS("Millis", Duration.ofNanos(1000_000)),
067    /**
068     * Unit that represents the concept of a second.
069     * For the ISO calendar system, it is equal to the second in the SI system
070     * of units, except around a leap-second.
071     */
072    SECONDS("Seconds", Duration.ofSeconds(1)),
073    /**
074     * Unit that represents the concept of a minute.
075     * For the ISO calendar system, it is equal to 60 seconds.
076     */
077    MINUTES("Minutes", Duration.ofSeconds(60)),
078    /**
079     * Unit that represents the concept of an hour.
080     * For the ISO calendar system, it is equal to 60 minutes.
081     */
082    HOURS("Hours", Duration.ofSeconds(3600)),
083    /**
084     * Unit that represents the concept of half a day, as used in AM/PM.
085     * For the ISO calendar system, it is equal to 12 hours.
086     */
087    HALF_DAYS("HalfDays", Duration.ofSeconds(43200)),
088    /**
089     * Unit that represents the concept of a day.
090     * For the ISO calendar system, it is the standard day from midnight to midnight.
091     * The estimated duration of a day is {@code 24 Hours}.
092     * <p>
093     * When used with other calendar systems it must correspond to the day defined by
094     * the rising and setting of the Sun on Earth. It is not required that days begin
095     * at midnight - when converting between calendar systems, the date should be
096     * equivalent at midday.
097     */
098    DAYS("Days", Duration.ofSeconds(86400)),
099    /**
100     * Unit that represents the concept of a week.
101     * For the ISO calendar system, it is equal to 7 days.
102     * <p>
103     * When used with other calendar systems it must correspond to an integral number of days.
104     */
105    WEEKS("Weeks", Duration.ofSeconds(7 * 86400L)),
106    /**
107     * Unit that represents the concept of a month.
108     * For the ISO calendar system, the length of the month varies by month-of-year.
109     * The estimated duration of a month is one twelfth of {@code 365.2425 Days}.
110     * <p>
111     * When used with other calendar systems it must correspond to an integral number of days.
112     */
113    MONTHS("Months", Duration.ofSeconds(31556952L / 12)),
114    /**
115     * Unit that represents the concept of a year.
116     * For the ISO calendar system, it is equal to 12 months.
117     * The estimated duration of a year is {@code 365.2425 Days}.
118     * <p>
119     * When used with other calendar systems it must correspond to an integral number of days
120     * or months roughly equal to a year defined by the passage of the Earth around the Sun.
121     */
122    YEARS("Years", Duration.ofSeconds(31556952L)),
123    /**
124     * Unit that represents the concept of a decade.
125     * For the ISO calendar system, it is equal to 10 years.
126     * <p>
127     * When used with other calendar systems it must correspond to an integral number of days
128     * and is normally an integral number of years.
129     */
130    DECADES("Decades", Duration.ofSeconds(31556952L * 10L)),
131    /**
132     * Unit that represents the concept of a century.
133     * For the ISO calendar system, it is equal to 100 years.
134     * <p>
135     * When used with other calendar systems it must correspond to an integral number of days
136     * and is normally an integral number of years.
137     */
138    CENTURIES("Centuries", Duration.ofSeconds(31556952L * 100L)),
139    /**
140     * Unit that represents the concept of a millennium.
141     * For the ISO calendar system, it is equal to 1000 years.
142     * <p>
143     * When used with other calendar systems it must correspond to an integral number of days
144     * and is normally an integral number of years.
145     */
146    MILLENNIA("Millennia", Duration.ofSeconds(31556952L * 1000L)),
147    /**
148     * Unit that represents the concept of an era.
149     * The ISO calendar system doesn't have eras thus it is impossible to add
150     * an era to a date or date-time.
151     * The estimated duration of the era is artificially defined as {@code 1,000,00,000 Years}.
152     * <p>
153     * When used with other calendar systems there are no restrictions on the unit.
154     */
155    ERAS("Eras", Duration.ofSeconds(31556952L * 1000_000_000L)),
156    /**
157     * Artificial unit that represents the concept of forever.
158     * This is primarily used with {@link TemporalField} to represent unbounded fields
159     * such as the year or era.
160     * The estimated duration of the era is artificially defined as the largest duration
161     * supported by {@code Duration}.
162     */
163    FOREVER("Forever", Duration.ofSeconds(Long.MAX_VALUE, 999_999_999));
164
165    private final String name;
166    private final Duration duration;
167
168    private ChronoUnit(String name, Duration estimatedDuration) {
169        this.name = name;
170        this.duration = estimatedDuration;
171    }
172
173    //-----------------------------------------------------------------------
174    @Override
175    public String getName() {
176        return name;
177    }
178
179    //-----------------------------------------------------------------------
180    /**
181     * Gets the estimated duration of this unit in the ISO calendar system.
182     * <p>
183     * All of the units in this class have an estimated duration.
184     * Days vary due to daylight saving time, while months have different lengths.
185     *
186     * @return the estimated duration of this unit, not null
187     */
188    @Override
189    public Duration getDuration() {
190        return duration;
191    }
192
193    /**
194     * Checks if the duration of the unit is an estimate.
195     * <p>
196     * All time units in this class are considered to be accurate, while all date
197     * units in this class are considered to be estimated.
198     * <p>
199     * This definition ignores leap seconds, but considers that Days vary due to
200     * daylight saving time and months have different lengths.
201     *
202     * @return true if the duration is estimated, false if accurate
203     */
204    @Override
205    public boolean isDurationEstimated() {
206        return isDateUnit();
207    }
208
209    //-----------------------------------------------------------------------
210    /**
211     * Checks if this unit is a date unit.
212     *
213     * @return true if a date unit, false if a time unit
214     */
215    public boolean isDateUnit() {
216        return this.compareTo(DAYS) >= 0;
217    }
218
219    /**
220     * Checks if this unit is a time unit.
221     *
222     * @return true if a time unit, false if a date unit
223     */
224    public boolean isTimeUnit() {
225        return this.compareTo(DAYS) < 0;
226    }
227
228    //-----------------------------------------------------------------------
229    @Override
230    public boolean isSupported(Temporal temporal) {
231        if (this == FOREVER) {
232            return false;
233        }
234        if (temporal instanceof ChronoLocalDate) {
235            return isDateUnit();
236        }
237        if (temporal instanceof ChronoLocalDateTime || temporal instanceof ChronoZonedDateTime) {
238            return true;
239        }
240        try {
241            temporal.plus(1, this);
242            return true;
243        } catch (RuntimeException ex) {
244            try {
245                temporal.plus(-1, this);
246                return true;
247            } catch (RuntimeException ex2) {
248                return false;
249            }
250        }
251    }
252
253    @Override
254    public <R extends Temporal> R doPlus(R dateTime, long periodToAdd) {
255        return (R) dateTime.plus(periodToAdd, this);
256    }
257
258    //-----------------------------------------------------------------------
259    @Override
260    public <R extends Temporal> SimplePeriod between(R dateTime1, R dateTime2) {
261        return new SimplePeriod(dateTime1.periodUntil(dateTime2, this), this);
262    }
263
264    //-----------------------------------------------------------------------
265    @Override
266    public String toString() {
267        return getName();
268    }
269
270}