001/*
002 *  Copyright 2001-2010 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.convert.FromString;
021import org.joda.time.base.AbstractInstant;
022import org.joda.time.chrono.ISOChronology;
023import org.joda.time.convert.ConverterManager;
024import org.joda.time.convert.InstantConverter;
025import org.joda.time.format.DateTimeFormatter;
026import org.joda.time.format.ISODateTimeFormat;
027
028/**
029 * Instant is the standard implementation of a fully immutable instant in time.
030 * <p>
031 * <code>Instant</code> is an implementation of {@link ReadableInstant}.
032 * As with all instants, it represents an exact point on the time-line,
033 * but limited to the precision of milliseconds. An <code>Instant</code>
034 * should be used to represent a point in time irrespective of any other
035 * factor, such as chronology or time zone.
036 * <p>
037 * Internally, the class holds one piece of data, the instant as milliseconds
038 * from the Java epoch of 1970-01-01T00:00:00Z.
039 * <p>
040 * For example, an Instant can be used to compare two <code>DateTime</code>
041 * objects irrespective of chronology or time zone.
042 * <pre>
043 * boolean sameInstant = dt1.toInstant().equals(dt2.toInstant());
044 * </pre>
045 * Note that the following code will also perform the same check:
046 * <pre>
047 * boolean sameInstant = dt1.isEqual(dt2);
048 * </pre>
049 * <p>
050 * Instant is thread-safe and immutable.
051 *
052 * @author Stephen Colebourne
053 * @since 1.0
054 */
055public final class Instant
056        extends AbstractInstant
057        implements ReadableInstant, Serializable {
058
059    /** Serialization lock */
060    private static final long serialVersionUID = 3299096530934209741L;
061
062    /** The millis from 1970-01-01T00:00:00Z */
063    private final long iMillis;
064
065    //-----------------------------------------------------------------------
066    /**
067     * Obtains an {@code Instant} set to the current system millisecond time.
068     * 
069     * @return the current instant, not null
070     * @since 2.0
071     */
072    public static Instant now() {
073        return new Instant();
074    }
075
076    //-----------------------------------------------------------------------
077    /**
078     * Parses a {@code Instant} from the specified string.
079     * <p>
080     * This uses {@link ISODateTimeFormat#dateTimeParser()}.
081     * 
082     * @param str  the string to parse, not null
083     * @since 2.0
084     */
085    @FromString
086    public static Instant parse(String str) {
087        return parse(str, ISODateTimeFormat.dateTimeParser());
088    }
089
090    /**
091     * Parses a {@code Instant} from the specified string using a formatter.
092     * 
093     * @param str  the string to parse, not null
094     * @param formatter  the formatter to use, not null
095     * @since 2.0
096     */
097    public static Instant parse(String str, DateTimeFormatter formatter) {
098        return formatter.parseDateTime(str).toInstant();
099    }
100
101    //-----------------------------------------------------------------------
102    /**
103     * Constructs an instance set to the current system millisecond time.
104     * 
105     * @see #now()
106     */
107    public Instant() {
108        super();
109        iMillis = DateTimeUtils.currentTimeMillis();
110    }
111
112    /**
113     * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z.
114     * 
115     * @param instant  the milliseconds from 1970-01-01T00:00:00Z
116     */
117    public Instant(long instant) {
118        super();
119        iMillis = instant;
120    }
121
122    /**
123     * Constructs an instance from an Object that represents a datetime.
124     * <p>
125     * The recognised object types are defined in {@link ConverterManager} and
126     * include String, Calendar and Date.
127     *
128     * @param instant  the datetime object, null means now
129     * @throws IllegalArgumentException if the instant is invalid
130     */
131    public Instant(Object instant) {
132        super();
133        InstantConverter converter = ConverterManager.getInstance().getInstantConverter(instant);
134        iMillis = converter.getInstantMillis(instant, ISOChronology.getInstanceUTC());
135    }
136
137    //-----------------------------------------------------------------------
138    /**
139     * Get this object as an Instant by returning <code>this</code>.
140     * 
141     * @return <code>this</code>
142     */
143    public Instant toInstant() {
144        return this;
145    }
146
147    //-----------------------------------------------------------------------
148    /**
149     * Gets a copy of this instant with different millis.
150     * <p>
151     * The returned object will be either be a new Instant or <code>this</code>.
152     *
153     * @param newMillis  the new millis, from 1970-01-01T00:00:00Z
154     * @return a copy of this instant with different millis
155     */
156    public Instant withMillis(long newMillis) {
157        return (newMillis == iMillis ? this : new Instant(newMillis));
158    }
159
160    /**
161     * Gets a copy of this instant with the specified duration added.
162     * <p>
163     * If the addition is zero, then <code>this</code> is returned.
164     * 
165     * @param durationToAdd  the duration to add to this one
166     * @param scalar  the amount of times to add, such as -1 to subtract once
167     * @return a copy of this instant with the duration added
168     * @throws ArithmeticException if the new instant exceeds the capacity of a long
169     */
170    public Instant withDurationAdded(long durationToAdd, int scalar) {
171        if (durationToAdd == 0 || scalar == 0) {
172            return this;
173        }
174        long instant = getChronology().add(getMillis(), durationToAdd, scalar);
175        return withMillis(instant);
176    }
177
178    /**
179     * Gets a copy of this instant with the specified duration added.
180     * <p>
181     * If the addition is zero, then <code>this</code> is returned.
182     * 
183     * @param durationToAdd  the duration to add to this one, null means zero
184     * @param scalar  the amount of times to add, such as -1 to subtract once
185     * @return a copy of this instant with the duration added
186     * @throws ArithmeticException if the new instant exceeds the capacity of a long
187     */
188    public Instant withDurationAdded(ReadableDuration durationToAdd, int scalar) {
189        if (durationToAdd == null || scalar == 0) {
190            return this;
191        }
192        return withDurationAdded(durationToAdd.getMillis(), scalar);
193    }
194
195    //-----------------------------------------------------------------------
196    /**
197     * Gets a copy of this instant with the specified duration added.
198     * <p>
199     * If the amount is zero or null, then <code>this</code> is returned.
200     * 
201     * @param duration  the duration to add to this one
202     * @return a copy of this instant with the duration added
203     * @throws ArithmeticException if the new instant exceeds the capacity of a long
204     */
205    public Instant plus(long duration) {
206        return withDurationAdded(duration, 1);
207    }
208
209    /**
210     * Gets a copy of this instant with the specified duration added.
211     * <p>
212     * If the amount is zero or null, then <code>this</code> is returned.
213     * 
214     * @param duration  the duration to add to this one, null means zero
215     * @return a copy of this instant with the duration added
216     * @throws ArithmeticException if the new instant exceeds the capacity of a long
217     */
218    public Instant plus(ReadableDuration duration) {
219        return withDurationAdded(duration, 1);
220    }
221
222    //-----------------------------------------------------------------------
223    /**
224     * Gets a copy of this instant with the specified duration taken away.
225     * <p>
226     * If the amount is zero or null, then <code>this</code> is returned.
227     * 
228     * @param duration  the duration to reduce this instant by
229     * @return a copy of this instant with the duration taken away
230     * @throws ArithmeticException if the new instant exceeds the capacity of a long
231     */
232    public Instant minus(long duration) {
233        return withDurationAdded(duration, -1);
234    }
235
236    /**
237     * Gets a copy of this instant with the specified duration taken away.
238     * <p>
239     * If the amount is zero or null, then <code>this</code> is returned.
240     * 
241     * @param duration  the duration to reduce this instant by
242     * @return a copy of this instant with the duration taken away
243     * @throws ArithmeticException if the new instant exceeds the capacity of a long
244     */
245    public Instant minus(ReadableDuration duration) {
246        return withDurationAdded(duration, -1);
247    }
248
249    //-----------------------------------------------------------------------
250    /**
251     * Gets the milliseconds of the instant.
252     * 
253     * @return the number of milliseconds since 1970-01-01T00:00:00Z
254     */
255    public long getMillis() {
256        return iMillis;
257    }
258
259    /**
260     * Gets the chronology of the instant, which is ISO in the UTC zone.
261     * <p>
262     * This method returns {@link ISOChronology#getInstanceUTC()} which
263     * corresponds to the definition of the Java epoch 1970-01-01T00:00:00Z.
264     * 
265     * @return ISO in the UTC zone
266     */
267    public Chronology getChronology() {
268        return ISOChronology.getInstanceUTC();
269    }
270
271    //-----------------------------------------------------------------------
272    /**
273     * Get this object as a DateTime using ISOChronology in the default zone.
274     * <p>
275     * This method returns a DateTime object in the default zone.
276     * This differs from the similarly named method on DateTime, DateMidnight
277     * or MutableDateTime which retains the time zone. The difference is
278     * because Instant really represents a time <i>without</i> a zone,
279     * thus calling this method we really have no zone to 'retain' and
280     * hence expect to switch to the default zone.
281     * <p>
282     * This method definition preserves compatibility with earlier versions
283     * of Joda-Time.
284     *
285     * @return a DateTime using the same millis
286     */
287    public DateTime toDateTime() {
288        return new DateTime(getMillis(), ISOChronology.getInstance());
289    }
290
291    /**
292     * Get this object as a DateTime using ISOChronology in the default zone.
293     * This method is identical to <code>toDateTime()</code>.
294     * <p>
295     * This method returns a DateTime object in the default zone.
296     * This differs from the similarly named method on DateTime, DateMidnight
297     * or MutableDateTime which retains the time zone. The difference is
298     * because Instant really represents a time <i>without</i> a zone,
299     * thus calling this method we really have no zone to 'retain' and
300     * hence expect to switch to the default zone.
301     * <p>
302     * This method is deprecated because it is a duplicate of {@link #toDateTime()}.
303     * However, removing it would cause the superclass implementation to be used,
304     * which would create silent bugs in any caller depending on this implementation.
305     * As such, the method itself is not currently planned to be removed.
306     * <p>
307     * This method definition preserves compatibility with earlier versions
308     * of Joda-Time.
309     *
310     * @return a DateTime using the same millis with ISOChronology
311     * @deprecated Use toDateTime() as it is identical
312     */
313    @Deprecated
314    public DateTime toDateTimeISO() {
315        return toDateTime();
316    }
317
318    /**
319     * Get this object as a MutableDateTime using ISOChronology in the default zone.
320     * <p>
321     * This method returns a MutableDateTime object in the default zone.
322     * This differs from the similarly named method on DateTime, DateMidnight
323     * or MutableDateTime which retains the time zone. The difference is
324     * because Instant really represents a time <i>without</i> a zone,
325     * thus calling this method we really have no zone to 'retain' and
326     * hence expect to switch to the default zone.
327     * <p>
328     * This method definition preserves compatibility with earlier versions
329     * of Joda-Time.
330     *
331     * @return a MutableDateTime using the same millis
332     */
333    public MutableDateTime toMutableDateTime() {
334        return new MutableDateTime(getMillis(), ISOChronology.getInstance());
335    }
336
337    /**
338     * Get this object as a MutableDateTime using ISOChronology in the default zone.
339     * This method is identical to <code>toMutableDateTime()</code>.
340     * <p>
341     * This method returns a MutableDateTime object in the default zone.
342     * This differs from the similarly named method on DateTime, DateMidnight
343     * or MutableDateTime which retains the time zone. The difference is
344     * because Instant really represents a time <i>without</i> a zone,
345     * thus calling this method we really have no zone to 'retain' and
346     * hence expect to switch to the default zone.
347     * <p>
348     * This method is deprecated because it is a duplicate of {@link #toMutableDateTime()}.
349     * However, removing it would cause the superclass implementation to be used,
350     * which would create silent bugs in any caller depending on this implementation.
351     * As such, the method itself is not currently planned to be removed.
352     * <p>
353     * This method definition preserves compatibility with earlier versions
354     * of Joda-Time.
355     *
356     * @return a MutableDateTime using the same millis with ISOChronology
357     * @deprecated Use toMutableDateTime() as it is identical
358     */
359    @Deprecated
360    public MutableDateTime toMutableDateTimeISO() {
361        return toMutableDateTime();
362    }
363
364}