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