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 extends AbstractInstant implements
053: ReadableInstant, Serializable {
054:
055: /** Serialization lock */
056: private static final long serialVersionUID = 3299096530934209741L;
057:
058: /** The millis from 1970-01-01T00:00:00Z */
059: private final long iMillis;
060:
061: //-----------------------------------------------------------------------
062: /**
063: * Constructs an instance set to the current system millisecond time.
064: */
065: public Instant() {
066: super ();
067: iMillis = DateTimeUtils.currentTimeMillis();
068: }
069:
070: /**
071: * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z.
072: *
073: * @param instant the milliseconds from 1970-01-01T00:00:00Z
074: */
075: public Instant(long instant) {
076: super ();
077: iMillis = instant;
078: }
079:
080: /**
081: * Constructs an instance from an Object that represents a datetime.
082: * <p>
083: * The recognised object types are defined in {@link ConverterManager} and
084: * include String, Calendar and Date.
085: *
086: * @param instant the datetime object, null means now
087: * @throws IllegalArgumentException if the instant is invalid
088: */
089: public Instant(Object instant) {
090: super ();
091: InstantConverter converter = ConverterManager.getInstance()
092: .getInstantConverter(instant);
093: iMillis = converter.getInstantMillis(instant, ISOChronology
094: .getInstanceUTC());
095: }
096:
097: //-----------------------------------------------------------------------
098: /**
099: * Get this object as an Instant by returning <code>this</code>.
100: *
101: * @return <code>this</code>
102: */
103: public Instant toInstant() {
104: return this ;
105: }
106:
107: //-----------------------------------------------------------------------
108: /**
109: * Gets a copy of this instant with different millis.
110: * <p>
111: * The returned object will be either be a new Instant or <code>this</code>.
112: *
113: * @param newMillis the new millis, from 1970-01-01T00:00:00Z
114: * @return a copy of this instant with different millis
115: */
116: public Instant withMillis(long newMillis) {
117: return (newMillis == iMillis ? this : new Instant(newMillis));
118: }
119:
120: /**
121: * Gets a copy of this instant with the specified duration added.
122: * <p>
123: * If the addition is zero, then <code>this</code> is returned.
124: *
125: * @param durationToAdd the duration to add to this one
126: * @param scalar the amount of times to add, such as -1 to subtract once
127: * @return a copy of this instant with the duration added
128: * @throws ArithmeticException if the new instant exceeds the capacity of a long
129: */
130: public Instant withDurationAdded(long durationToAdd, int scalar) {
131: if (durationToAdd == 0 || scalar == 0) {
132: return this ;
133: }
134: long instant = getChronology().add(getMillis(), durationToAdd,
135: scalar);
136: return withMillis(instant);
137: }
138:
139: /**
140: * Gets a copy of this instant with the specified duration added.
141: * <p>
142: * If the addition is zero, then <code>this</code> is returned.
143: *
144: * @param durationToAdd the duration to add to this one, null means zero
145: * @param scalar the amount of times to add, such as -1 to subtract once
146: * @return a copy of this instant with the duration added
147: * @throws ArithmeticException if the new instant exceeds the capacity of a long
148: */
149: public Instant withDurationAdded(ReadableDuration durationToAdd,
150: int scalar) {
151: if (durationToAdd == null || scalar == 0) {
152: return this ;
153: }
154: return withDurationAdded(durationToAdd.getMillis(), scalar);
155: }
156:
157: //-----------------------------------------------------------------------
158: /**
159: * Gets a copy of this instant with the specified duration added.
160: * <p>
161: * If the amount is zero or null, then <code>this</code> is returned.
162: *
163: * @param duration the duration to add to this one
164: * @return a copy of this instant with the duration added
165: * @throws ArithmeticException if the new instant exceeds the capacity of a long
166: */
167: public Instant plus(long duration) {
168: return withDurationAdded(duration, 1);
169: }
170:
171: /**
172: * Gets a copy of this instant with the specified duration added.
173: * <p>
174: * If the amount is zero or null, then <code>this</code> is returned.
175: *
176: * @param duration the duration to add to this one, null means zero
177: * @return a copy of this instant with the duration added
178: * @throws ArithmeticException if the new instant exceeds the capacity of a long
179: */
180: public Instant plus(ReadableDuration duration) {
181: return withDurationAdded(duration, 1);
182: }
183:
184: //-----------------------------------------------------------------------
185: /**
186: * Gets a copy of this instant with the specified duration taken away.
187: * <p>
188: * If the amount is zero or null, then <code>this</code> is returned.
189: *
190: * @param duration the duration to reduce this instant by
191: * @return a copy of this instant with the duration taken away
192: * @throws ArithmeticException if the new instant exceeds the capacity of a long
193: */
194: public Instant minus(long duration) {
195: return withDurationAdded(duration, -1);
196: }
197:
198: /**
199: * Gets a copy of this instant with the specified duration taken away.
200: * <p>
201: * If the amount is zero or null, then <code>this</code> is returned.
202: *
203: * @param duration the duration to reduce this instant by
204: * @return a copy of this instant with the duration taken away
205: * @throws ArithmeticException if the new instant exceeds the capacity of a long
206: */
207: public Instant minus(ReadableDuration duration) {
208: return withDurationAdded(duration, -1);
209: }
210:
211: //-----------------------------------------------------------------------
212: /**
213: * Gets the milliseconds of the instant.
214: *
215: * @return the number of milliseconds since 1970-01-01T00:00:00Z
216: */
217: public long getMillis() {
218: return iMillis;
219: }
220:
221: /**
222: * Gets the chronology of the instant, which is ISO in the UTC zone.
223: * <p>
224: * This method returns {@link ISOChronology#getInstanceUTC()} which
225: * corresponds to the definition of the Java epoch 1970-01-01T00:00:00Z.
226: *
227: * @return ISO in the UTC zone
228: */
229: public Chronology getChronology() {
230: return ISOChronology.getInstanceUTC();
231: }
232:
233: //-----------------------------------------------------------------------
234: /**
235: * Get this object as a DateTime using ISOChronology in the default zone.
236: * <p>
237: * This method returns a DateTime object in the default zone.
238: * This differs from the similarly named method on DateTime, DateMidnight
239: * or MutableDateTime which retains the time zone. The difference is
240: * because Instant really represents a time <i>without</i> a zone,
241: * thus calling this method we really have no zone to 'retain' and
242: * hence expect to switch to the default zone.
243: * <p>
244: * This method definition preserves compatability with earlier versions
245: * of Joda-Time.
246: *
247: * @return a DateTime using the same millis
248: */
249: public DateTime toDateTime() {
250: return new DateTime(getMillis(), ISOChronology.getInstance());
251: }
252:
253: /**
254: * Get this object as a DateTime using ISOChronology in the default zone.
255: * This method is identical to <code>toDateTime()</code>.
256: * <p>
257: * This method returns a DateTime object in the default zone.
258: * This differs from the similarly named method on DateTime, DateMidnight
259: * or MutableDateTime which retains the time zone. The difference is
260: * because Instant really represents a time <i>without</i> a zone,
261: * thus calling this method we really have no zone to 'retain' and
262: * hence expect to switch to the default zone.
263: * <p>
264: * This method definition preserves compatability with earlier versions
265: * of Joda-Time.
266: *
267: * @return a DateTime using the same millis with ISOChronology
268: * @deprecated Use toDateTime() as it is identical
269: */
270: public DateTime toDateTimeISO() {
271: return toDateTime();
272: }
273:
274: /**
275: * Get this object as a MutableDateTime using ISOChronology in the default zone.
276: * <p>
277: * This method returns a MutableDateTime object in the default zone.
278: * This differs from the similarly named method on DateTime, DateMidnight
279: * or MutableDateTime which retains the time zone. The difference is
280: * because Instant really represents a time <i>without</i> a zone,
281: * thus calling this method we really have no zone to 'retain' and
282: * hence expect to switch to the default zone.
283: * <p>
284: * This method definition preserves compatability with earlier versions
285: * of Joda-Time.
286: *
287: * @return a MutableDateTime using the same millis
288: */
289: public MutableDateTime toMutableDateTime() {
290: return new MutableDateTime(getMillis(), ISOChronology
291: .getInstance());
292: }
293:
294: /**
295: * Get this object as a MutableDateTime using ISOChronology in the default zone.
296: * This method is identical to <code>toMutableDateTime()</code>.
297: * <p>
298: * This method returns a MutableDateTime object in the default zone.
299: * This differs from the similarly named method on DateTime, DateMidnight
300: * or MutableDateTime which retains the time zone. The difference is
301: * because Instant really represents a time <i>without</i> a zone,
302: * thus calling this method we really have no zone to 'retain' and
303: * hence expect to switch to the default zone.
304: * <p>
305: * This method definition preserves compatability with earlier versions
306: * of Joda-Time.
307: *
308: * @return a MutableDateTime using the same millis with ISOChronology
309: * @deprecated Use toMutableDateTime() as it is identical
310: */
311: public MutableDateTime toMutableDateTimeISO() {
312: return toMutableDateTime();
313: }
314:
315: }
|