1 /*
2 * Copyright 2001-2010 Stephen Colebourne
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.joda.time;
17
18 import java.io.Serializable;
19
20 import org.joda.convert.FromString;
21 import org.joda.time.base.AbstractInstant;
22 import org.joda.time.chrono.ISOChronology;
23 import org.joda.time.convert.ConverterManager;
24 import org.joda.time.convert.InstantConverter;
25 import org.joda.time.format.DateTimeFormatter;
26 import org.joda.time.format.ISODateTimeFormat;
27
28 /**
29 * Instant is the standard implementation of a fully immutable instant in time.
30 * <p>
31 * <code>Instant</code> is an implementation of {@link ReadableInstant}.
32 * As with all instants, it represents an exact point on the time-line,
33 * but limited to the precision of milliseconds. An <code>Instant</code>
34 * should be used to represent a point in time irrespective of any other
35 * factor, such as chronology or time zone.
36 * <p>
37 * Internally, the class holds one piece of data, the instant as milliseconds
38 * from the Java epoch of 1970-01-01T00:00:00Z.
39 * <p>
40 * For example, an Instant can be used to compare two <code>DateTime</code>
41 * objects irrespective of chronology or time zone.
42 * <pre>
43 * boolean sameInstant = dt1.toInstant().equals(dt2.toInstant());
44 * </pre>
45 * Note that the following code will also perform the same check:
46 * <pre>
47 * boolean sameInstant = dt1.isEqual(dt2);
48 * </pre>
49 * <p>
50 * Instant is thread-safe and immutable.
51 *
52 * @author Stephen Colebourne
53 * @since 1.0
54 */
55 public final class Instant
56 extends AbstractInstant
57 implements ReadableInstant, Serializable {
58
59 /** Serialization lock */
60 private static final long serialVersionUID = 3299096530934209741L;
61
62 /** The millis from 1970-01-01T00:00:00Z */
63 private final long iMillis;
64
65 //-----------------------------------------------------------------------
66 /**
67 * Obtains an {@code Instant} set to the current system millisecond time.
68 *
69 * @return the current instant, not null
70 * @since 2.0
71 */
72 public static Instant now() {
73 return new Instant();
74 }
75
76 //-----------------------------------------------------------------------
77 /**
78 * Parses a {@code Instant} from the specified string.
79 * <p>
80 * This uses {@link ISODateTimeFormat#dateTimeParser()}.
81 *
82 * @param str the string to parse, not null
83 * @since 2.0
84 */
85 @FromString
86 public static Instant parse(String str) {
87 return parse(str, ISODateTimeFormat.dateTimeParser());
88 }
89
90 /**
91 * Parses a {@code Instant} from the specified string using a formatter.
92 *
93 * @param str the string to parse, not null
94 * @param formatter the formatter to use, not null
95 * @since 2.0
96 */
97 public static Instant parse(String str, DateTimeFormatter formatter) {
98 return formatter.parseDateTime(str).toInstant();
99 }
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 }