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.base;
017:
018: import java.io.Serializable;
019:
020: import org.joda.time.Chronology;
021: import org.joda.time.DateTimeUtils;
022: import org.joda.time.MutableInterval;
023: import org.joda.time.ReadWritableInterval;
024: import org.joda.time.ReadableDuration;
025: import org.joda.time.ReadableInstant;
026: import org.joda.time.ReadableInterval;
027: import org.joda.time.ReadablePeriod;
028: import org.joda.time.chrono.ISOChronology;
029: import org.joda.time.convert.ConverterManager;
030: import org.joda.time.convert.IntervalConverter;
031: import org.joda.time.field.FieldUtils;
032:
033: /**
034: * BaseInterval is an abstract implementation of ReadableInterval that stores
035: * data in two <code>long</code> millisecond fields.
036: * <p>
037: * This class should generally not be used directly by API users.
038: * The {@link ReadableInterval} interface should be used when different
039: * kinds of interval objects are to be referenced.
040: * <p>
041: * BaseInterval subclasses may be mutable and not thread-safe.
042: *
043: * @author Brian S O'Neill
044: * @author Sean Geoghegan
045: * @author Stephen Colebourne
046: * @since 1.0
047: */
048: public abstract class BaseInterval extends AbstractInterval implements
049: ReadableInterval, Serializable {
050:
051: /** Serialization version */
052: private static final long serialVersionUID = 576586928732749278L;
053:
054: /** The chronology of the interval */
055: private Chronology iChronology;
056: /** The start of the interval */
057: private long iStartMillis;
058: /** The end of the interval */
059: private long iEndMillis;
060:
061: /**
062: * Constructs an interval from a start and end instant.
063: *
064: * @param startInstant start of this interval, as milliseconds from 1970-01-01T00:00:00Z.
065: * @param endInstant end of this interval, as milliseconds from 1970-01-01T00:00:00Z.
066: * @param chrono the chronology to use, null is ISO default
067: * @throws IllegalArgumentException if the end is before the start
068: */
069: protected BaseInterval(long startInstant, long endInstant,
070: Chronology chrono) {
071: super ();
072: iChronology = DateTimeUtils.getChronology(chrono);
073: checkInterval(startInstant, endInstant);
074: iStartMillis = startInstant;
075: iEndMillis = endInstant;
076: }
077:
078: /**
079: * Constructs an interval from a start and end instant.
080: *
081: * @param start start of this interval, null means now
082: * @param end end of this interval, null means now
083: * @throws IllegalArgumentException if the end is before the start
084: */
085: protected BaseInterval(ReadableInstant start, ReadableInstant end) {
086: super ();
087: if (start == null && end == null) {
088: iStartMillis = iEndMillis = DateTimeUtils
089: .currentTimeMillis();
090: iChronology = ISOChronology.getInstance();
091: } else {
092: iChronology = DateTimeUtils.getInstantChronology(start);
093: iStartMillis = DateTimeUtils.getInstantMillis(start);
094: iEndMillis = DateTimeUtils.getInstantMillis(end);
095: checkInterval(iStartMillis, iEndMillis);
096: }
097: }
098:
099: /**
100: * Constructs an interval from a start instant and a duration.
101: *
102: * @param start start of this interval, null means now
103: * @param duration the duration of this interval, null means zero length
104: * @throws IllegalArgumentException if the end is before the start
105: * @throws ArithmeticException if the end instant exceeds the capacity of a long
106: */
107: protected BaseInterval(ReadableInstant start,
108: ReadableDuration duration) {
109: super ();
110: iChronology = DateTimeUtils.getInstantChronology(start);
111: iStartMillis = DateTimeUtils.getInstantMillis(start);
112: long durationMillis = DateTimeUtils.getDurationMillis(duration);
113: iEndMillis = FieldUtils.safeAdd(iStartMillis, durationMillis);
114: checkInterval(iStartMillis, iEndMillis);
115: }
116:
117: /**
118: * Constructs an interval from a millisecond duration and an end instant.
119: *
120: * @param duration the duration of this interval, null means zero length
121: * @param end end of this interval, null means now
122: * @throws IllegalArgumentException if the end is before the start
123: * @throws ArithmeticException if the start instant exceeds the capacity of a long
124: */
125: protected BaseInterval(ReadableDuration duration,
126: ReadableInstant end) {
127: super ();
128: iChronology = DateTimeUtils.getInstantChronology(end);
129: iEndMillis = DateTimeUtils.getInstantMillis(end);
130: long durationMillis = DateTimeUtils.getDurationMillis(duration);
131: iStartMillis = FieldUtils.safeAdd(iEndMillis, -durationMillis);
132: checkInterval(iStartMillis, iEndMillis);
133: }
134:
135: /**
136: * Constructs an interval from a start instant and a time period.
137: * <p>
138: * When forming the interval, the chronology from the instant is used
139: * if present, otherwise the chronology of the period is used.
140: *
141: * @param start start of this interval, null means now
142: * @param period the period of this interval, null means zero length
143: * @throws IllegalArgumentException if the end is before the start
144: * @throws ArithmeticException if the end instant exceeds the capacity of a long
145: */
146: protected BaseInterval(ReadableInstant start, ReadablePeriod period) {
147: super ();
148: Chronology chrono = DateTimeUtils.getInstantChronology(start);
149: iChronology = chrono;
150: iStartMillis = DateTimeUtils.getInstantMillis(start);
151: if (period == null) {
152: iEndMillis = iStartMillis;
153: } else {
154: iEndMillis = chrono.add(period, iStartMillis, 1);
155: }
156: checkInterval(iStartMillis, iEndMillis);
157: }
158:
159: /**
160: * Constructs an interval from a time period and an end instant.
161: * <p>
162: * When forming the interval, the chronology from the instant is used
163: * if present, otherwise the chronology of the period is used.
164: *
165: * @param period the period of this interval, null means zero length
166: * @param end end of this interval, null means now
167: * @throws IllegalArgumentException if the end is before the start
168: * @throws ArithmeticException if the start instant exceeds the capacity of a long
169: */
170: protected BaseInterval(ReadablePeriod period, ReadableInstant end) {
171: super ();
172: Chronology chrono = DateTimeUtils.getInstantChronology(end);
173: iChronology = chrono;
174: iEndMillis = DateTimeUtils.getInstantMillis(end);
175: if (period == null) {
176: iStartMillis = iEndMillis;
177: } else {
178: iStartMillis = chrono.add(period, iEndMillis, -1);
179: }
180: checkInterval(iStartMillis, iEndMillis);
181: }
182:
183: /**
184: * Constructs a time interval converting or copying from another object
185: * that describes an interval.
186: *
187: * @param interval the time interval to copy
188: * @param chrono the chronology to use, null means let converter decide
189: * @throws IllegalArgumentException if the interval is invalid
190: */
191: protected BaseInterval(Object interval, Chronology chrono) {
192: super ();
193: IntervalConverter converter = ConverterManager.getInstance()
194: .getIntervalConverter(interval);
195: if (converter.isReadableInterval(interval, chrono)) {
196: ReadableInterval input = (ReadableInterval) interval;
197: iChronology = (chrono != null ? chrono : input
198: .getChronology());
199: iStartMillis = input.getStartMillis();
200: iEndMillis = input.getEndMillis();
201: } else if (this instanceof ReadWritableInterval) {
202: converter.setInto((ReadWritableInterval) this , interval,
203: chrono);
204: } else {
205: MutableInterval mi = new MutableInterval();
206: converter.setInto(mi, interval, chrono);
207: iChronology = mi.getChronology();
208: iStartMillis = mi.getStartMillis();
209: iEndMillis = mi.getEndMillis();
210: }
211: checkInterval(iStartMillis, iEndMillis);
212: }
213:
214: //-----------------------------------------------------------------------
215: /**
216: * Gets the chronology of this interval.
217: *
218: * @return the chronology
219: */
220: public Chronology getChronology() {
221: return iChronology;
222: }
223:
224: /**
225: * Gets the start of this time interval which is inclusive.
226: *
227: * @return the start of the time interval,
228: * millisecond instant from 1970-01-01T00:00:00Z
229: */
230: public long getStartMillis() {
231: return iStartMillis;
232: }
233:
234: /**
235: * Gets the end of this time interval which is exclusive.
236: *
237: * @return the end of the time interval,
238: * millisecond instant from 1970-01-01T00:00:00Z
239: */
240: public long getEndMillis() {
241: return iEndMillis;
242: }
243:
244: //-----------------------------------------------------------------------
245: /**
246: * Sets this interval from two millisecond instants and a chronology.
247: *
248: * @param startInstant the start of the time interval
249: * @param endInstant the start of the time interval
250: * @param chrono the chronology, not null
251: * @throws IllegalArgumentException if the end is before the start
252: */
253: protected void setInterval(long startInstant, long endInstant,
254: Chronology chrono) {
255: checkInterval(startInstant, endInstant);
256: iStartMillis = startInstant;
257: iEndMillis = endInstant;
258: iChronology = DateTimeUtils.getChronology(chrono);
259: }
260:
261: }
|