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.DateTimeException;
035import org.threeten.bp.Duration;
036import org.threeten.bp.Period;
037
038/**
039 * A unit of date-time, such as Days or Hours.
040 * <p>
041 * Measurement of time is built on units, such as years, months, days, hours, minutes and seconds.
042 * Implementations of this interface represent those units.
043 * <p>
044 * An instance of this interface represents the unit itself, rather than an amount of the unit.
045 * See {@link Period} for a class that represents an amount in terms of the common units.
046 * <p>
047 * The most commonly used units are defined in {@link ChronoUnit}.
048 * Further units are supplied in {@link ISOFields}.
049 * Units can also be written by application code by implementing this interface.
050 * <p>
051 * The unit works using double dispatch. Client code calls methods on a date-time like
052 * {@code LocalDateTime} which check if the unit is a {@code ChronoUnit}.
053 * If it is, then the date-time must handle it.
054 * Otherwise, the method call is re-dispatched to the matching method in this interface.
055 *
056 * <h3>Specification for implementors</h3>
057 * This interface must be implemented with care to ensure other classes operate correctly.
058 * All implementations that can be instantiated must be final, immutable and thread-safe.
059 * It is recommended to use an enum where possible.
060 */
061public interface TemporalUnit {
062
063    /**
064     * Gets a descriptive name for the unit.
065     * <p>
066     * This should be in the plural and upper-first camel case, such as 'Days' or 'Minutes'.
067     *
068     * @return the name, not null
069     */
070    String getName();
071
072    /**
073     * Gets the duration of this unit, which may be an estimate.
074     * <p>
075     * All units return a duration measured in standard nanoseconds from this method.
076     * For example, an hour has a duration of {@code 60 * 60 * 1,000,000,000ns}.
077     * <p>
078     * Some units may return an accurate duration while others return an estimate.
079     * For example, days have an estimated duration due to the possibility of
080     * daylight saving time changes.
081     * To determine if the duration is an estimate, use {@link #isDurationEstimated()}.
082     *
083     * @return the duration of this unit, which may be an estimate, not null
084     */
085    Duration getDuration();
086
087    /**
088     * Checks if the duration of the unit is an estimate.
089     * <p>
090     * All units have a duration, however the duration is not always accurate.
091     * For example, days have an estimated duration due to the possibility of
092     * daylight saving time changes.
093     * This method returns true if the duration is an estimate and false if it is
094     * accurate. Note that accurate/estimated ignores leap seconds.
095     *
096     * @return true if the duration is estimated, false if accurate
097     */
098    boolean isDurationEstimated();
099
100    //-----------------------------------------------------------------------
101    /**
102     * Checks if this unit is supported by the specified temporal object.
103     * <p>
104     * This checks that the implementing date-time can add/subtract this unit.
105     * This can be used to avoid throwing an exception.
106     *
107     * @param temporal  the temporal object to check, not null
108     * @return true if the unit is supported
109     */
110    boolean isSupported(Temporal temporal);
111
112    /**
113     * Returns a copy of the specified temporal object with the specified period added.
114     * <p>
115     * The period added is a multiple of this unit. For example, this method
116     * could be used to add "3 days" to a date by calling this method on the
117     * instance representing "days", passing the date and the period "3".
118     * The period to be added may be negative, which is equivalent to subtraction.
119     * <p>
120     * There are two equivalent ways of using this method.
121     * The first is to invoke this method directly.
122     * The second is to use {@link Temporal#plus(long, TemporalUnit)}:
123     * <pre>
124     *   // these two lines are equivalent, but the second approach is recommended
125     *   temporal = thisUnit.doPlus(temporal);
126     *   temporal = temporal.plus(thisUnit);
127     * </pre>
128     * It is recommended to use the second approach, {@code plus(TemporalUnit)},
129     * as it is a lot clearer to read in code.
130     * <p>
131     * Implementations should perform any queries or calculations using the units
132     * available in {@link ChronoUnit} or the fields available in {@link ChronoField}.
133     * If the field is not supported a {@code DateTimeException} must be thrown.
134     * <p>
135     * Implementations must not alter the specified temporal object.
136     * Instead, an adjusted copy of the original must be returned.
137     * This provides equivalent, safe behavior for immutable and mutable implementations.
138     *
139     * @param <R>  the type of the Temporal object
140     * @param dateTime  the temporal object to adjust, not null
141     * @param periodToAdd  the period of this unit to add, positive or negative
142     * @return the adjusted temporal object, not null
143     * @throws DateTimeException if the period cannot be added
144     */
145    <R extends Temporal> R doPlus(R dateTime, long periodToAdd);
146
147    //-----------------------------------------------------------------------
148    /**
149     * Calculates the period in terms of this unit between two temporal objects of the same type.
150     * <p>
151     * The period will be positive if the second date-time is after the first, and
152     * negative if the second date-time is before the first.
153     * Call {@link SimplePeriod#abs() abs()} on the result to ensure that the result
154     * is always positive.
155     * <p>
156     * The result can be queried for the {@link SimplePeriod#getAmount() amount}, the
157     * {@link SimplePeriod#getUnit() unit} and used directly in addition/subtraction:
158     * <pre>
159     *  date = date.minus(MONTHS.between(start, end));
160     * </pre>
161     *
162     * @param <R>  the type of the Temporal object; the two date-times must be of the same type
163     * @param dateTime1  the base temporal object, not null
164     * @param dateTime2  the other temporal object, not null
165     * @return the period between datetime1 and datetime2 in terms of this unit;
166     *      positive if datetime2 is later than datetime1, not null
167     */
168    <R extends Temporal> SimplePeriod between(R dateTime1, R dateTime2);
169
170    //-----------------------------------------------------------------------
171    /**
172     * Outputs this unit as a {@code String} using the name.
173     *
174     * @return the name of this unit, not null
175     */
176    @Override
177    String toString();
178
179}