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     */
016    package org.joda.time;
017    
018    import java.io.Serializable;
019    
020    import org.joda.time.base.AbstractInstant;
021    import org.joda.time.chrono.ISOChronology;
022    import org.joda.time.convert.ConverterManager;
023    import 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     */
052    public 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    }