001/*
002 *  Copyright 2001-2006 Stephen Colebourne
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.joda.time;
017
018import java.io.Serializable;
019
020import org.joda.time.base.AbstractInstant;
021import org.joda.time.chrono.ISOChronology;
022import org.joda.time.convert.ConverterManager;
023import org.joda.time.convert.InstantConverter;
024
025/**
026 * Instant is the standard implementation of a fully immutable instant in time.
027 * <p>
028 * <code>Instant</code> is an implementation of {@link ReadableInstant}.
029 * As with all instants, it represents an exact point on the time-line,
030 * but limited to the precision of milliseconds. An <code>Instant</code>
031 * should be used to represent a point in time irrespective of any other
032 * factor, such as chronology or time zone.
033 * <p>
034 * Internally, the class holds one piece of data, the instant as milliseconds
035 * from the Java epoch of 1970-01-01T00:00:00Z.
036 * <p>
037 * For example, an Instant can be used to compare two <code>DateTime</code>
038 * objects irrespective of chronology or time zone.
039 * <pre>
040 * boolean sameInstant = dt1.toInstant().equals(dt2.toInstant());
041 * </pre>
042 * Note that the following code will also perform the same check:
043 * <pre>
044 * boolean sameInstant = dt1.isEqual(dt2);
045 * </pre>
046 * <p>
047 * Instant is thread-safe and immutable.
048 *
049 * @author Stephen Colebourne
050 * @since 1.0
051 */
052public final class Instant
053        extends AbstractInstant
054        implements ReadableInstant, Serializable {
055
056    /** Serialization lock */
057    private static final long serialVersionUID = 3299096530934209741L;
058
059    /** The millis from 1970-01-01T00:00:00Z */
060    private final long iMillis;
061
062    //-----------------------------------------------------------------------
063    /**
064     * Constructs an instance set to the current system millisecond time.
065     */
066    public Instant() {
067        super();
068        iMillis = DateTimeUtils.currentTimeMillis();
069    }
070
071    /**
072     * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z.
073     * 
074     * @param instant  the milliseconds from 1970-01-01T00:00:00Z
075     */
076    public Instant(long instant) {
077        super();
078        iMillis = instant;
079    }
080
081    /**
082     * Constructs an instance from an Object that represents a datetime.
083     * <p>
084     * The recognised object types are defined in {@link ConverterManager} and
085     * include String, Calendar and Date.
086     *
087     * @param instant  the datetime object, null means now
088     * @throws IllegalArgumentException if the instant is invalid
089     */
090    public Instant(Object instant) {
091        super();
092        InstantConverter converter = ConverterManager.getInstance().getInstantConverter(instant);
093        iMillis = converter.getInstantMillis(instant, ISOChronology.getInstanceUTC());
094    }
095
096    //-----------------------------------------------------------------------
097    /**
098     * Get this object as an Instant by returning <code>this</code>.
099     * 
100     * @return <code>this</code>
101     */
102    public Instant toInstant() {
103        return this;
104    }
105
106    //-----------------------------------------------------------------------
107    /**
108     * Gets a copy of this instant with different millis.
109     * <p>
110     * The returned object will be either be a new Instant or <code>this</code>.
111     *
112     * @param newMillis  the new millis, from 1970-01-01T00:00:00Z
113     * @return a copy of this instant with different millis
114     */
115    public Instant withMillis(long newMillis) {
116        return (newMillis == iMillis ? this : new Instant(newMillis));
117    }
118
119    /**
120     * Gets a copy of this instant with the specified duration added.
121     * <p>
122     * If the addition is zero, then <code>this</code> is returned.
123     * 
124     * @param durationToAdd  the duration to add to this one
125     * @param scalar  the amount of times to add, such as -1 to subtract once
126     * @return a copy of this instant with the duration added
127     * @throws ArithmeticException if the new instant exceeds the capacity of a long
128     */
129    public Instant withDurationAdded(long durationToAdd, int scalar) {
130        if (durationToAdd == 0 || scalar == 0) {
131            return this;
132        }
133        long instant = getChronology().add(getMillis(), durationToAdd, scalar);
134        return withMillis(instant);
135    }
136
137    /**
138     * Gets a copy of this instant with the specified duration added.
139     * <p>
140     * If the addition is zero, then <code>this</code> is returned.
141     * 
142     * @param durationToAdd  the duration to add to this one, null means zero
143     * @param scalar  the amount of times to add, such as -1 to subtract once
144     * @return a copy of this instant with the duration added
145     * @throws ArithmeticException if the new instant exceeds the capacity of a long
146     */
147    public Instant withDurationAdded(ReadableDuration durationToAdd, int scalar) {
148        if (durationToAdd == null || scalar == 0) {
149            return this;
150        }
151        return withDurationAdded(durationToAdd.getMillis(), scalar);
152    }
153
154    //-----------------------------------------------------------------------
155    /**
156     * Gets a copy of this instant with the specified duration added.
157     * <p>
158     * If the amount is zero or null, then <code>this</code> is returned.
159     * 
160     * @param duration  the duration to add to this one
161     * @return a copy of this instant with the duration added
162     * @throws ArithmeticException if the new instant exceeds the capacity of a long
163     */
164    public Instant plus(long duration) {
165        return withDurationAdded(duration, 1);
166    }
167
168    /**
169     * Gets a copy of this instant with the specified duration added.
170     * <p>
171     * If the amount is zero or null, then <code>this</code> is returned.
172     * 
173     * @param duration  the duration to add to this one, null means zero
174     * @return a copy of this instant with the duration added
175     * @throws ArithmeticException if the new instant exceeds the capacity of a long
176     */
177    public Instant plus(ReadableDuration duration) {
178        return withDurationAdded(duration, 1);
179    }
180
181    //-----------------------------------------------------------------------
182    /**
183     * Gets a copy of this instant with the specified duration taken away.
184     * <p>
185     * If the amount is zero or null, then <code>this</code> is returned.
186     * 
187     * @param duration  the duration to reduce this instant by
188     * @return a copy of this instant with the duration taken away
189     * @throws ArithmeticException if the new instant exceeds the capacity of a long
190     */
191    public Instant minus(long duration) {
192        return withDurationAdded(duration, -1);
193    }
194
195    /**
196     * Gets a copy of this instant with the specified duration taken away.
197     * <p>
198     * If the amount is zero or null, then <code>this</code> is returned.
199     * 
200     * @param duration  the duration to reduce this instant by
201     * @return a copy of this instant with the duration taken away
202     * @throws ArithmeticException if the new instant exceeds the capacity of a long
203     */
204    public Instant minus(ReadableDuration duration) {
205        return withDurationAdded(duration, -1);
206    }
207
208    //-----------------------------------------------------------------------
209    /**
210     * Gets the milliseconds of the instant.
211     * 
212     * @return the number of milliseconds since 1970-01-01T00:00:00Z
213     */
214    public long getMillis() {
215        return iMillis;
216    }
217
218    /**
219     * Gets the chronology of the instant, which is ISO in the UTC zone.
220     * <p>
221     * This method returns {@link ISOChronology#getInstanceUTC()} which
222     * corresponds to the definition of the Java epoch 1970-01-01T00:00:00Z.
223     * 
224     * @return ISO in the UTC zone
225     */
226    public Chronology getChronology() {
227        return ISOChronology.getInstanceUTC();
228    }
229
230    //-----------------------------------------------------------------------
231    /**
232     * Get this object as a DateTime using ISOChronology in the default zone.
233     * <p>
234     * This method returns a DateTime object in the default zone.
235     * This differs from the similarly named method on DateTime, DateMidnight
236     * or MutableDateTime which retains the time zone. The difference is
237     * because Instant really represents a time <i>without</i> a zone,
238     * thus calling this method we really have no zone to 'retain' and
239     * hence expect to switch to the default zone.
240     * <p>
241     * This method definition preserves compatability with earlier versions
242     * of Joda-Time.
243     *
244     * @return a DateTime using the same millis
245     */
246    public DateTime toDateTime() {
247        return new DateTime(getMillis(), ISOChronology.getInstance());
248    }
249
250    /**
251     * Get this object as a DateTime using ISOChronology in the default zone.
252     * This method is identical to <code>toDateTime()</code>.
253     * <p>
254     * This method returns a DateTime object in the default zone.
255     * This differs from the similarly named method on DateTime, DateMidnight
256     * or MutableDateTime which retains the time zone. The difference is
257     * because Instant really represents a time <i>without</i> a zone,
258     * thus calling this method we really have no zone to 'retain' and
259     * hence expect to switch to the default zone.
260     * <p>
261     * This method definition preserves compatability with earlier versions
262     * of Joda-Time.
263     *
264     * @return a DateTime using the same millis with ISOChronology
265     * @deprecated Use toDateTime() as it is identical
266     */
267    public DateTime toDateTimeISO() {
268        return toDateTime();
269    }
270
271    /**
272     * Get this object as a MutableDateTime using ISOChronology in the default zone.
273     * <p>
274     * This method returns a MutableDateTime object in the default zone.
275     * This differs from the similarly named method on DateTime, DateMidnight
276     * or MutableDateTime which retains the time zone. The difference is
277     * because Instant really represents a time <i>without</i> a zone,
278     * thus calling this method we really have no zone to 'retain' and
279     * hence expect to switch to the default zone.
280     * <p>
281     * This method definition preserves compatability with earlier versions
282     * of Joda-Time.
283     *
284     * @return a MutableDateTime using the same millis
285     */
286    public MutableDateTime toMutableDateTime() {
287        return new MutableDateTime(getMillis(), ISOChronology.getInstance());
288    }
289
290    /**
291     * Get this object as a MutableDateTime using ISOChronology in the default zone.
292     * This method is identical to <code>toMutableDateTime()</code>.
293     * <p>
294     * This method returns a MutableDateTime object in the default zone.
295     * This differs from the similarly named method on DateTime, DateMidnight
296     * or MutableDateTime which retains the time zone. The difference is
297     * because Instant really represents a time <i>without</i> a zone,
298     * thus calling this method we really have no zone to 'retain' and
299     * hence expect to switch to the default zone.
300     * <p>
301     * This method definition preserves compatability with earlier versions
302     * of Joda-Time.
303     *
304     * @return a MutableDateTime using the same millis with ISOChronology
305     * @deprecated Use toMutableDateTime() as it is identical
306     */
307    public MutableDateTime toMutableDateTimeISO() {
308        return toMutableDateTime();
309    }
310
311}