001: /*
002: * Copyright 2001-2005 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.BaseInterval;
021: import org.joda.time.field.FieldUtils;
022: import org.joda.time.format.ISODateTimeFormat;
023: import org.joda.time.format.ISOPeriodFormat;
024:
025: /**
026: * MutableInterval is the standard implementation of a mutable time interval.
027: * <p>
028: * A time interval represents a period of time between two instants.
029: * Intervals are inclusive of the start instant and exclusive of the end.
030: * The end instant is always greater than or equal to the start instant.
031: * <p>
032: * Intervals have a fixed millisecond duration.
033: * This is the difference between the start and end instants.
034: * The duration is represented separately by {@link ReadableDuration}.
035: * As a result, intervals are not comparable.
036: * To compare the length of two intervals, you should compare their durations.
037: * <p>
038: * An interval can also be converted to a {@link ReadablePeriod}.
039: * This represents the difference between the start and end points in terms of fields
040: * such as years and days.
041: * <p>
042: * If performing significant calculations on an interval, it may be faster to
043: * convert an Interval object to a MutableInterval one.
044: * <p>
045: * MutableInterval is mutable and not thread-safe, unless concurrent threads
046: * are not invoking mutator methods.
047: *
048: * @author Stephen Colebourne
049: * @author Brian S O'Neill
050: * @since 1.0
051: */
052: public class MutableInterval extends BaseInterval implements
053: ReadWritableInterval, Cloneable, Serializable {
054:
055: /** Serialization version */
056: private static final long serialVersionUID = -5982824024992428470L;
057:
058: //-----------------------------------------------------------------------
059: /**
060: * Constructs a zero length time interval from 1970-01-01 to 1970-01-01.
061: */
062: public MutableInterval() {
063: super (0L, 0L, null);
064: }
065:
066: /**
067: * Constructs an interval from a start and end instant with the ISO default chronology.
068: *
069: * @param startInstant start of this interval, as milliseconds from 1970-01-01T00:00:00Z.
070: * @param endInstant end of this interval, as milliseconds from 1970-01-01T00:00:00Z.
071: * @throws IllegalArgumentException if the end is before the start
072: */
073: public MutableInterval(long startInstant, long endInstant) {
074: super (startInstant, endInstant, null);
075: }
076:
077: /**
078: * Constructs an interval from a start and end instant with a chronology.
079: *
080: * @param chronology the chronology to use, null is ISO default
081: * @param startInstant start of this interval, as milliseconds from 1970-01-01T00:00:00Z.
082: * @param endInstant end of this interval, as milliseconds from 1970-01-01T00:00:00Z.
083: * @throws IllegalArgumentException if the end is before the start
084: */
085: public MutableInterval(long startInstant, long endInstant,
086: Chronology chronology) {
087: super (startInstant, endInstant, chronology);
088: }
089:
090: /**
091: * Constructs an interval from a start and end instant.
092: * <p>
093: * The chronology used is that of the start instant.
094: *
095: * @param start start of this interval, null means now
096: * @param end end of this interval, null means now
097: * @throws IllegalArgumentException if the end is before the start
098: */
099: public MutableInterval(ReadableInstant start, ReadableInstant end) {
100: super (start, end);
101: }
102:
103: /**
104: * Constructs an interval from a start instant and a duration.
105: *
106: * @param start start of this interval, null means now
107: * @param duration the duration of this interval, null means zero length
108: * @throws IllegalArgumentException if the end is before the start
109: * @throws ArithmeticException if the end instant exceeds the capacity of a long
110: */
111: public MutableInterval(ReadableInstant start,
112: ReadableDuration duration) {
113: super (start, duration);
114: }
115:
116: /**
117: * Constructs an interval from a millisecond duration and an end instant.
118: *
119: * @param duration the duration of this interval, null means zero length
120: * @param end end of this interval, null means now
121: * @throws IllegalArgumentException if the end is before the start
122: * @throws ArithmeticException if the start instant exceeds the capacity of a long
123: */
124: public MutableInterval(ReadableDuration duration,
125: ReadableInstant end) {
126: super (duration, end);
127: }
128:
129: /**
130: * Constructs an interval from a start instant and a time period.
131: * <p>
132: * When forming the interval, the chronology from the instant is used
133: * if present, otherwise the chronology of the period is used.
134: *
135: * @param start start of this interval, null means now
136: * @param period the period of this interval, null means zero length
137: * @throws IllegalArgumentException if the end is before the start
138: * @throws ArithmeticException if the end instant exceeds the capacity of a long
139: */
140: public MutableInterval(ReadableInstant start, ReadablePeriod period) {
141: super (start, period);
142: }
143:
144: /**
145: * Constructs an interval from a time period and an end instant.
146: * <p>
147: * When forming the interval, the chronology from the instant is used
148: * if present, otherwise the chronology of the period is used.
149: *
150: * @param period the period of this interval, null means zero length
151: * @param end end of this interval, null means now
152: * @throws IllegalArgumentException if the end is before the start
153: * @throws ArithmeticException if the start instant exceeds the capacity of a long
154: */
155: public MutableInterval(ReadablePeriod period, ReadableInstant end) {
156: super (period, end);
157: }
158:
159: /**
160: * Constructs a time interval by converting or copying from another object.
161: * <p>
162: * The recognised object types are defined in
163: * {@link org.joda.time.convert.ConverterManager ConverterManager} and
164: * include ReadableInterval and String.
165: * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}
166: * and {@link ISOPeriodFormat#standard()}, and may be 'datetime/datetime',
167: * 'datetime/period' or 'period/datetime'.
168: *
169: * @param interval the time interval to copy
170: * @throws IllegalArgumentException if the interval is invalid
171: */
172: public MutableInterval(Object interval) {
173: super (interval, null);
174: }
175:
176: /**
177: * Constructs a time interval by converting or copying from another object,
178: * overriding the chronology.
179: * <p>
180: * The recognised object types are defined in
181: * {@link org.joda.time.convert.ConverterManager ConverterManager} and
182: * include ReadableInterval and String.
183: * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()}
184: * and {@link ISOPeriodFormat#standard()}, and may be 'datetime/datetime',
185: * 'datetime/period' or 'period/datetime'.
186: *
187: * @param interval the time interval to copy
188: * @param chronology the chronology to use, null means ISO default
189: * @throws IllegalArgumentException if the interval is invalid
190: */
191: public MutableInterval(Object interval, Chronology chronology) {
192: super (interval, chronology);
193: }
194:
195: //-----------------------------------------------------------------------
196: /**
197: * Sets this interval from two millisecond instants retaining the chronology.
198: *
199: * @param startInstant the start of the time interval
200: * @param endInstant the start of the time interval
201: * @throws IllegalArgumentException if the end is before the start
202: */
203: public void setInterval(long startInstant, long endInstant) {
204: super .setInterval(startInstant, endInstant, getChronology());
205: }
206:
207: /**
208: * Sets this interval to be the same as another.
209: *
210: * @param interval the interval to copy
211: * @throws IllegalArgumentException if the interval is null
212: */
213: public void setInterval(ReadableInterval interval) {
214: if (interval == null) {
215: throw new IllegalArgumentException(
216: "Interval must not be null");
217: }
218: long startMillis = interval.getStartMillis();
219: long endMillis = interval.getEndMillis();
220: Chronology chrono = interval.getChronology();
221: super .setInterval(startMillis, endMillis, chrono);
222: }
223:
224: /**
225: * Sets this interval from two instants, replacing the chronology with
226: * that from the start instant.
227: *
228: * @param start the start of the time interval
229: * @param end the start of the time interval
230: * @throws IllegalArgumentException if the end is before the start
231: */
232: public void setInterval(ReadableInstant start, ReadableInstant end) {
233: if (start == null && end == null) {
234: long now = DateTimeUtils.currentTimeMillis();
235: setInterval(now, now);
236: } else {
237: long startMillis = DateTimeUtils.getInstantMillis(start);
238: long endMillis = DateTimeUtils.getInstantMillis(end);
239: Chronology chrono = DateTimeUtils
240: .getInstantChronology(start);
241: super .setInterval(startMillis, endMillis, chrono);
242: }
243: }
244:
245: //-----------------------------------------------------------------------
246: /**
247: * Sets the chronology of this time interval.
248: *
249: * @param chrono the chronology to use, null means ISO default
250: */
251: public void setChronology(Chronology chrono) {
252: super .setInterval(getStartMillis(), getEndMillis(), chrono);
253: }
254:
255: /**
256: * Sets the start of this time interval.
257: *
258: * @param startInstant the start of the time interval,
259: * millisecond instant from 1970-01-01T00:00:00Z
260: * @throws IllegalArgumentException if the end is before the start
261: */
262: public void setStartMillis(long startInstant) {
263: super
264: .setInterval(startInstant, getEndMillis(),
265: getChronology());
266: }
267:
268: /**
269: * Sets the start of this time interval as an Instant.
270: *
271: * @param start the start of the time interval, null means now
272: * @throws IllegalArgumentException if the end is before the start
273: */
274: public void setStart(ReadableInstant start) {
275: long startMillis = DateTimeUtils.getInstantMillis(start);
276: super .setInterval(startMillis, getEndMillis(), getChronology());
277: }
278:
279: /**
280: * Sets the end of this time interval.
281: *
282: * @param endInstant the end of the time interval,
283: * millisecond instant from 1970-01-01T00:00:00Z
284: * @throws IllegalArgumentException if the end is before the start
285: */
286: public void setEndMillis(long endInstant) {
287: super
288: .setInterval(getStartMillis(), endInstant,
289: getChronology());
290: }
291:
292: /**
293: * Sets the end of this time interval as an Instant.
294: *
295: * @param end the end of the time interval, null means now
296: * @throws IllegalArgumentException if the end is before the start
297: */
298: public void setEnd(ReadableInstant end) {
299: long endMillis = DateTimeUtils.getInstantMillis(end);
300: super .setInterval(getStartMillis(), endMillis, getChronology());
301: }
302:
303: //-----------------------------------------------------------------------
304: /**
305: * Sets the duration of this time interval, preserving the start instant.
306: *
307: * @param duration new duration for interval
308: * @throws IllegalArgumentException if the end is before the start
309: * @throws ArithmeticException if the end instant exceeds the capacity of a long
310: */
311: public void setDurationAfterStart(long duration) {
312: setEndMillis(FieldUtils.safeAdd(getStartMillis(), duration));
313: }
314:
315: /**
316: * Sets the duration of this time interval, preserving the end instant.
317: *
318: * @param duration new duration for interval
319: * @throws IllegalArgumentException if the end is before the start
320: * @throws ArithmeticException if the start instant exceeds the capacity of a long
321: */
322: public void setDurationBeforeEnd(long duration) {
323: setStartMillis(FieldUtils.safeAdd(getEndMillis(), -duration));
324: }
325:
326: //-----------------------------------------------------------------------
327: /**
328: * Sets the duration of this time interval, preserving the start instant.
329: *
330: * @param duration new duration for interval, null means zero length
331: * @throws IllegalArgumentException if the end is before the start
332: * @throws ArithmeticException if the end instant exceeds the capacity of a long
333: */
334: public void setDurationAfterStart(ReadableDuration duration) {
335: long durationMillis = DateTimeUtils.getDurationMillis(duration);
336: setEndMillis(FieldUtils.safeAdd(getStartMillis(),
337: durationMillis));
338: }
339:
340: /**
341: * Sets the duration of this time interval, preserving the end instant.
342: *
343: * @param duration new duration for interval, null means zero length
344: * @throws IllegalArgumentException if the end is before the start
345: * @throws ArithmeticException if the start instant exceeds the capacity of a long
346: */
347: public void setDurationBeforeEnd(ReadableDuration duration) {
348: long durationMillis = DateTimeUtils.getDurationMillis(duration);
349: setStartMillis(FieldUtils.safeAdd(getEndMillis(),
350: -durationMillis));
351: }
352:
353: //-----------------------------------------------------------------------
354: /**
355: * Sets the period of this time interval, preserving the start instant
356: * and using the ISOChronology in the default zone for calculations.
357: *
358: * @param period new period for interval, null means zero length
359: * @throws IllegalArgumentException if the end is before the start
360: * @throws ArithmeticException if the end instant exceeds the capacity of a long
361: */
362: public void setPeriodAfterStart(ReadablePeriod period) {
363: if (period == null) {
364: setEndMillis(getStartMillis());
365: } else {
366: setEndMillis(getChronology().add(period, getStartMillis(),
367: 1));
368: }
369: }
370:
371: /**
372: * Sets the period of this time interval, preserving the end instant
373: * and using the ISOChronology in the default zone for calculations.
374: *
375: * @param period new period for interval, null means zero length
376: * @throws IllegalArgumentException if the end is before the start
377: * @throws ArithmeticException if the start instant exceeds the capacity of a long
378: */
379: public void setPeriodBeforeEnd(ReadablePeriod period) {
380: if (period == null) {
381: setStartMillis(getEndMillis());
382: } else {
383: setStartMillis(getChronology().add(period, getEndMillis(),
384: -1));
385: }
386: }
387:
388: //-----------------------------------------------------------------------
389: /**
390: * Clone this object without having to cast the returned object.
391: *
392: * @return a clone of the this object.
393: */
394: public MutableInterval copy() {
395: return (MutableInterval) clone();
396: }
397:
398: /**
399: * Clone this object.
400: *
401: * @return a clone of this object.
402: */
403: public Object clone() {
404: try {
405: return super .clone();
406: } catch (CloneNotSupportedException ex) {
407: throw new InternalError("Clone error");
408: }
409: }
410:
411: }
|