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 }