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 }