View Javadoc

1   /*
2    *  Copyright 2001-2011 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.base;
17  
18  import java.io.Serializable;
19  
20  import org.joda.time.Chronology;
21  import org.joda.time.DateTimeUtils;
22  import org.joda.time.MutableInterval;
23  import org.joda.time.ReadWritableInterval;
24  import org.joda.time.ReadableDuration;
25  import org.joda.time.ReadableInstant;
26  import org.joda.time.ReadableInterval;
27  import org.joda.time.ReadablePeriod;
28  import org.joda.time.chrono.ISOChronology;
29  import org.joda.time.convert.ConverterManager;
30  import org.joda.time.convert.IntervalConverter;
31  import org.joda.time.field.FieldUtils;
32  
33  /**
34   * BaseInterval is an abstract implementation of ReadableInterval that stores
35   * data in two <code>long</code> millisecond fields.
36   * <p>
37   * This class should generally not be used directly by API users.
38   * The {@link ReadableInterval} interface should be used when different 
39   * kinds of interval objects are to be referenced.
40   * <p>
41   * BaseInterval subclasses may be mutable and not thread-safe.
42   *
43   * @author Brian S O'Neill
44   * @author Sean Geoghegan
45   * @author Stephen Colebourne
46   * @since 1.0
47   */
48  public abstract class BaseInterval
49          extends AbstractInterval
50          implements ReadableInterval, Serializable {
51  
52      /** Serialization version */
53      private static final long serialVersionUID = 576586928732749278L;
54  
55      /** The chronology of the interval */
56      private volatile Chronology iChronology;
57      /** The start of the interval */
58      private volatile long iStartMillis;
59      /** The end of the interval */
60      private volatile long iEndMillis;
61  
62      /**
63       * Constructs an interval from a start and end instant.
64       * 
65       * @param startInstant  start of this interval, as milliseconds from 1970-01-01T00:00:00Z.
66       * @param endInstant  end of this interval, as milliseconds from 1970-01-01T00:00:00Z.
67       * @param chrono  the chronology to use, null is ISO default
68       * @throws IllegalArgumentException if the end is before the start
69       */
70      protected BaseInterval(long startInstant, long endInstant, Chronology chrono) {
71          super();
72          iChronology = DateTimeUtils.getChronology(chrono);
73          checkInterval(startInstant, endInstant);
74          iStartMillis = startInstant;
75          iEndMillis = endInstant;
76      }
77  
78      /**
79       * Constructs an interval from a start and end instant.
80       * 
81       * @param start  start of this interval, null means now
82       * @param end  end of this interval, null means now
83       * @throws IllegalArgumentException if the end is before the start
84       */
85      protected BaseInterval(ReadableInstant start, ReadableInstant end) {
86          super();
87          if (start == null && end == null) {
88              iStartMillis = iEndMillis = DateTimeUtils.currentTimeMillis();
89              iChronology = ISOChronology.getInstance();
90          } else {
91              iChronology = DateTimeUtils.getInstantChronology(start);
92              iStartMillis = DateTimeUtils.getInstantMillis(start);
93              iEndMillis = DateTimeUtils.getInstantMillis(end);
94              checkInterval(iStartMillis, iEndMillis);
95          }
96      }
97  
98      /**
99       * Constructs an interval from a start instant and a duration.
100      * 
101      * @param start  start of this interval, null means now
102      * @param duration  the duration of this interval, null means zero length
103      * @throws IllegalArgumentException if the end is before the start
104      * @throws ArithmeticException if the end instant exceeds the capacity of a long
105      */
106     protected BaseInterval(ReadableInstant start, ReadableDuration duration) {
107         super();
108         iChronology = DateTimeUtils.getInstantChronology(start);
109         iStartMillis = DateTimeUtils.getInstantMillis(start);
110         long durationMillis = DateTimeUtils.getDurationMillis(duration);
111         iEndMillis = FieldUtils.safeAdd(iStartMillis, durationMillis);
112         checkInterval(iStartMillis, iEndMillis);
113     }
114 
115     /**
116      * Constructs an interval from a millisecond duration and an end instant.
117      * 
118      * @param duration  the duration of this interval, null means zero length
119      * @param end  end of this interval, null means now
120      * @throws IllegalArgumentException if the end is before the start
121      * @throws ArithmeticException if the start instant exceeds the capacity of a long
122      */
123     protected BaseInterval(ReadableDuration duration, ReadableInstant end) {
124         super();
125         iChronology = DateTimeUtils.getInstantChronology(end);
126         iEndMillis = DateTimeUtils.getInstantMillis(end);
127         long durationMillis = DateTimeUtils.getDurationMillis(duration);
128         iStartMillis = FieldUtils.safeAdd(iEndMillis, -durationMillis);
129         checkInterval(iStartMillis, iEndMillis);
130     }
131 
132     /**
133      * Constructs an interval from a start instant and a time period.
134      * <p>
135      * When forming the interval, the chronology from the instant is used
136      * if present, otherwise the chronology of the period is used.
137      * 
138      * @param start  start of this interval, null means now
139      * @param period  the period of this interval, null means zero length
140      * @throws IllegalArgumentException if the end is before the start
141      * @throws ArithmeticException if the end instant exceeds the capacity of a long
142      */
143     protected BaseInterval(ReadableInstant start, ReadablePeriod period) {
144         super();
145         Chronology chrono = DateTimeUtils.getInstantChronology(start);
146         iChronology = chrono;
147         iStartMillis = DateTimeUtils.getInstantMillis(start);
148         if (period == null) {
149             iEndMillis = iStartMillis;
150         } else {
151             iEndMillis = chrono.add(period, iStartMillis, 1);
152         }
153         checkInterval(iStartMillis, iEndMillis);
154     }
155 
156     /**
157      * Constructs an interval from a time period and an end instant.
158      * <p>
159      * When forming the interval, the chronology from the instant is used
160      * if present, otherwise the chronology of the period is used.
161      * 
162      * @param period  the period of this interval, null means zero length
163      * @param end  end of this interval, null means now
164      * @throws IllegalArgumentException if the end is before the start
165      * @throws ArithmeticException if the start instant exceeds the capacity of a long
166      */
167     protected BaseInterval(ReadablePeriod period, ReadableInstant end) {
168         super();
169         Chronology chrono = DateTimeUtils.getInstantChronology(end);
170         iChronology = chrono;
171         iEndMillis = DateTimeUtils.getInstantMillis(end);
172         if (period == null) {
173             iStartMillis = iEndMillis;
174         } else {
175             iStartMillis = chrono.add(period, iEndMillis, -1);
176         }
177         checkInterval(iStartMillis, iEndMillis);
178     }
179 
180     /**
181      * Constructs a time interval converting or copying from another object
182      * that describes an interval.
183      * 
184      * @param interval  the time interval to copy
185      * @param chrono  the chronology to use, null means let converter decide
186      * @throws IllegalArgumentException if the interval is invalid
187      */
188     protected BaseInterval(Object interval, Chronology chrono) {
189         super();
190         IntervalConverter converter = ConverterManager.getInstance().getIntervalConverter(interval);
191         if (converter.isReadableInterval(interval, chrono)) {
192             ReadableInterval input = (ReadableInterval) interval;
193             iChronology = (chrono != null ? chrono : input.getChronology());
194             iStartMillis = input.getStartMillis();
195             iEndMillis = input.getEndMillis();
196         } else if (this instanceof ReadWritableInterval) {
197             converter.setInto((ReadWritableInterval) this, interval, chrono);
198         } else {
199             MutableInterval mi = new MutableInterval();
200             converter.setInto(mi, interval, chrono);
201             iChronology = mi.getChronology();
202             iStartMillis = mi.getStartMillis();
203             iEndMillis = mi.getEndMillis();
204         }
205         checkInterval(iStartMillis, iEndMillis);
206     }
207 
208     //-----------------------------------------------------------------------
209     /**
210      * Gets the chronology of this interval.
211      *
212      * @return the chronology
213      */
214     public Chronology getChronology() {
215         return iChronology;
216     }
217 
218     /**
219      * Gets the start of this time interval which is inclusive.
220      *
221      * @return the start of the time interval,
222      *  millisecond instant from 1970-01-01T00:00:00Z
223      */
224     public long getStartMillis() {
225         return iStartMillis;
226     }
227 
228     /**
229      * Gets the end of this time interval which is exclusive.
230      *
231      * @return the end of the time interval,
232      *  millisecond instant from 1970-01-01T00:00:00Z
233      */
234     public long getEndMillis() {
235         return iEndMillis;
236     }
237 
238     //-----------------------------------------------------------------------
239     /**
240      * Sets this interval from two millisecond instants and a chronology.
241      *
242      * @param startInstant  the start of the time interval
243      * @param endInstant  the start of the time interval
244      * @param chrono  the chronology, not null
245      * @throws IllegalArgumentException if the end is before the start
246      */
247     protected void setInterval(long startInstant, long endInstant, Chronology chrono) {
248         checkInterval(startInstant, endInstant);
249         iStartMillis = startInstant;
250         iEndMillis = endInstant;
251         iChronology = DateTimeUtils.getChronology(chrono);
252     }
253 
254 }