1 | /* |
2 | * Copyright 2001-2005 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.time.base.BaseInterval; |
21 | import org.joda.time.field.FieldUtils; |
22 | import org.joda.time.format.ISODateTimeFormat; |
23 | import org.joda.time.format.ISOPeriodFormat; |
24 | |
25 | /** |
26 | * MutableInterval is the standard implementation of a mutable time interval. |
27 | * <p> |
28 | * A time interval represents a period of time between two instants. |
29 | * Intervals are inclusive of the start instant and exclusive of the end. |
30 | * The end instant is always greater than or equal to the start instant. |
31 | * <p> |
32 | * Intervals have a fixed millisecond duration. |
33 | * This is the difference between the start and end instants. |
34 | * The duration is represented separately by {@link ReadableDuration}. |
35 | * As a result, intervals are not comparable. |
36 | * To compare the length of two intervals, you should compare their durations. |
37 | * <p> |
38 | * An interval can also be converted to a {@link ReadablePeriod}. |
39 | * This represents the difference between the start and end points in terms of fields |
40 | * such as years and days. |
41 | * <p> |
42 | * If performing significant calculations on an interval, it may be faster to |
43 | * convert an Interval object to a MutableInterval one. |
44 | * <p> |
45 | * MutableInterval is mutable and not thread-safe, unless concurrent threads |
46 | * are not invoking mutator methods. |
47 | * |
48 | * @author Stephen Colebourne |
49 | * @author Brian S O'Neill |
50 | * @since 1.0 |
51 | */ |
52 | public class MutableInterval |
53 | extends BaseInterval |
54 | implements ReadWritableInterval, Cloneable, Serializable { |
55 | |
56 | /** Serialization version */ |
57 | private static final long serialVersionUID = -5982824024992428470L; |
58 | |
59 | //----------------------------------------------------------------------- |
60 | /** |
61 | * Constructs a zero length time interval from 1970-01-01 to 1970-01-01. |
62 | */ |
63 | public MutableInterval() { |
64 | super(0L, 0L, null); |
65 | } |
66 | |
67 | /** |
68 | * Constructs an interval from a start and end instant with the ISO default chronology. |
69 | * |
70 | * @param startInstant start of this interval, as milliseconds from 1970-01-01T00:00:00Z. |
71 | * @param endInstant end of this interval, as milliseconds from 1970-01-01T00:00:00Z. |
72 | * @throws IllegalArgumentException if the end is before the start |
73 | */ |
74 | public MutableInterval(long startInstant, long endInstant) { |
75 | super(startInstant, endInstant, null); |
76 | } |
77 | |
78 | /** |
79 | * Constructs an interval from a start and end instant with a chronology. |
80 | * |
81 | * @param chronology the chronology to use, null is ISO default |
82 | * @param startInstant start of this interval, as milliseconds from 1970-01-01T00:00:00Z. |
83 | * @param endInstant end of this interval, as milliseconds from 1970-01-01T00:00:00Z. |
84 | * @throws IllegalArgumentException if the end is before the start |
85 | */ |
86 | public MutableInterval(long startInstant, long endInstant, Chronology chronology) { |
87 | super(startInstant, endInstant, chronology); |
88 | } |
89 | |
90 | /** |
91 | * Constructs an interval from a start and end instant. |
92 | * <p> |
93 | * The chronology used is that of the start instant. |
94 | * |
95 | * @param start start of this interval, null means now |
96 | * @param end end of this interval, null means now |
97 | * @throws IllegalArgumentException if the end is before the start |
98 | */ |
99 | 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, ReadableDuration duration) { |
112 | super(start, duration); |
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 | public MutableInterval(ReadableDuration duration, ReadableInstant end) { |
124 | super(duration, end); |
125 | } |
126 | |
127 | /** |
128 | * Constructs an interval from a start instant and a time period. |
129 | * <p> |
130 | * When forming the interval, the chronology from the instant is used |
131 | * if present, otherwise the chronology of the period is used. |
132 | * |
133 | * @param start start of this interval, null means now |
134 | * @param period the period of this interval, null means zero length |
135 | * @throws IllegalArgumentException if the end is before the start |
136 | * @throws ArithmeticException if the end instant exceeds the capacity of a long |
137 | */ |
138 | public MutableInterval(ReadableInstant start, ReadablePeriod period) { |
139 | super(start, period); |
140 | } |
141 | |
142 | /** |
143 | * Constructs an interval from a time period and an end instant. |
144 | * <p> |
145 | * When forming the interval, the chronology from the instant is used |
146 | * if present, otherwise the chronology of the period is used. |
147 | * |
148 | * @param period the period of this interval, null means zero length |
149 | * @param end end of this interval, null means now |
150 | * @throws IllegalArgumentException if the end is before the start |
151 | * @throws ArithmeticException if the start instant exceeds the capacity of a long |
152 | */ |
153 | public MutableInterval(ReadablePeriod period, ReadableInstant end) { |
154 | super(period, end); |
155 | } |
156 | |
157 | /** |
158 | * Constructs a time interval by converting or copying from another object. |
159 | * <p> |
160 | * The recognised object types are defined in |
161 | * {@link org.joda.time.convert.ConverterManager ConverterManager} and |
162 | * include ReadableInterval and String. |
163 | * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()} |
164 | * and {@link ISOPeriodFormat#standard()}, and may be 'datetime/datetime', |
165 | * 'datetime/period' or 'period/datetime'. |
166 | * |
167 | * @param interval the time interval to copy |
168 | * @throws IllegalArgumentException if the interval is invalid |
169 | */ |
170 | public MutableInterval(Object interval) { |
171 | super(interval, null); |
172 | } |
173 | |
174 | /** |
175 | * Constructs a time interval by converting or copying from another object, |
176 | * overriding the chronology. |
177 | * <p> |
178 | * The recognised object types are defined in |
179 | * {@link org.joda.time.convert.ConverterManager ConverterManager} and |
180 | * include ReadableInterval and String. |
181 | * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()} |
182 | * and {@link ISOPeriodFormat#standard()}, and may be 'datetime/datetime', |
183 | * 'datetime/period' or 'period/datetime'. |
184 | * |
185 | * @param interval the time interval to copy |
186 | * @param chronology the chronology to use, null means ISO default |
187 | * @throws IllegalArgumentException if the interval is invalid |
188 | */ |
189 | public MutableInterval(Object interval, Chronology chronology) { |
190 | super(interval, chronology); |
191 | } |
192 | |
193 | //----------------------------------------------------------------------- |
194 | /** |
195 | * Sets this interval from two millisecond instants retaining the chronology. |
196 | * |
197 | * @param startInstant the start of the time interval |
198 | * @param endInstant the start of the time interval |
199 | * @throws IllegalArgumentException if the end is before the start |
200 | */ |
201 | public void setInterval(long startInstant, long endInstant) { |
202 | super.setInterval(startInstant, endInstant, getChronology()); |
203 | } |
204 | |
205 | /** |
206 | * Sets this interval to be the same as another. |
207 | * |
208 | * @param interval the interval to copy |
209 | * @throws IllegalArgumentException if the interval is null |
210 | */ |
211 | public void setInterval(ReadableInterval interval) { |
212 | if (interval == null) { |
213 | throw new IllegalArgumentException("Interval must not be null"); |
214 | } |
215 | long startMillis = interval.getStartMillis(); |
216 | long endMillis = interval.getEndMillis(); |
217 | Chronology chrono = interval.getChronology(); |
218 | super.setInterval(startMillis, endMillis, chrono); |
219 | } |
220 | |
221 | /** |
222 | * Sets this interval from two instants, replacing the chronology with |
223 | * that from the start instant. |
224 | * |
225 | * @param start the start of the time interval |
226 | * @param end the start of the time interval |
227 | * @throws IllegalArgumentException if the end is before the start |
228 | */ |
229 | public void setInterval(ReadableInstant start, ReadableInstant end) { |
230 | if (start == null && end == null) { |
231 | long now = DateTimeUtils.currentTimeMillis(); |
232 | setInterval(now, now); |
233 | } else { |
234 | long startMillis = DateTimeUtils.getInstantMillis(start); |
235 | long endMillis = DateTimeUtils.getInstantMillis(end); |
236 | Chronology chrono = DateTimeUtils.getInstantChronology(start); |
237 | super.setInterval(startMillis, endMillis, chrono); |
238 | } |
239 | } |
240 | |
241 | //----------------------------------------------------------------------- |
242 | /** |
243 | * Sets the chronology of this time interval. |
244 | * |
245 | * @param chrono the chronology to use, null means ISO default |
246 | */ |
247 | public void setChronology(Chronology chrono) { |
248 | super.setInterval(getStartMillis(), getEndMillis(), chrono); |
249 | } |
250 | |
251 | /** |
252 | * Sets the start of this time interval. |
253 | * |
254 | * @param startInstant the start of the time interval, |
255 | * millisecond instant from 1970-01-01T00:00:00Z |
256 | * @throws IllegalArgumentException if the end is before the start |
257 | */ |
258 | public void setStartMillis(long startInstant) { |
259 | super.setInterval(startInstant, getEndMillis(), getChronology()); |
260 | } |
261 | |
262 | /** |
263 | * Sets the start of this time interval as an Instant. |
264 | * |
265 | * @param start the start of the time interval, null means now |
266 | * @throws IllegalArgumentException if the end is before the start |
267 | */ |
268 | public void setStart(ReadableInstant start) { |
269 | long startMillis = DateTimeUtils.getInstantMillis(start); |
270 | super.setInterval(startMillis, getEndMillis(), getChronology()); |
271 | } |
272 | |
273 | /** |
274 | * Sets the end of this time interval. |
275 | * |
276 | * @param endInstant the end of the time interval, |
277 | * millisecond instant from 1970-01-01T00:00:00Z |
278 | * @throws IllegalArgumentException if the end is before the start |
279 | */ |
280 | public void setEndMillis(long endInstant) { |
281 | super.setInterval(getStartMillis(), endInstant, getChronology()); |
282 | } |
283 | |
284 | /** |
285 | * Sets the end of this time interval as an Instant. |
286 | * |
287 | * @param end the end of the time interval, null means now |
288 | * @throws IllegalArgumentException if the end is before the start |
289 | */ |
290 | public void setEnd(ReadableInstant end) { |
291 | long endMillis = DateTimeUtils.getInstantMillis(end); |
292 | super.setInterval(getStartMillis(), endMillis, getChronology()); |
293 | } |
294 | |
295 | //----------------------------------------------------------------------- |
296 | /** |
297 | * Sets the duration of this time interval, preserving the start instant. |
298 | * |
299 | * @param duration new duration for interval |
300 | * @throws IllegalArgumentException if the end is before the start |
301 | * @throws ArithmeticException if the end instant exceeds the capacity of a long |
302 | */ |
303 | public void setDurationAfterStart(long duration) { |
304 | setEndMillis(FieldUtils.safeAdd(getStartMillis(), duration)); |
305 | } |
306 | |
307 | /** |
308 | * Sets the duration of this time interval, preserving the end instant. |
309 | * |
310 | * @param duration new duration for interval |
311 | * @throws IllegalArgumentException if the end is before the start |
312 | * @throws ArithmeticException if the start instant exceeds the capacity of a long |
313 | */ |
314 | public void setDurationBeforeEnd(long duration) { |
315 | setStartMillis(FieldUtils.safeAdd(getEndMillis(), -duration)); |
316 | } |
317 | |
318 | //----------------------------------------------------------------------- |
319 | /** |
320 | * Sets the duration of this time interval, preserving the start instant. |
321 | * |
322 | * @param duration new duration for interval, null means zero length |
323 | * @throws IllegalArgumentException if the end is before the start |
324 | * @throws ArithmeticException if the end instant exceeds the capacity of a long |
325 | */ |
326 | public void setDurationAfterStart(ReadableDuration duration) { |
327 | long durationMillis = DateTimeUtils.getDurationMillis(duration); |
328 | setEndMillis(FieldUtils.safeAdd(getStartMillis(), durationMillis)); |
329 | } |
330 | |
331 | /** |
332 | * Sets the duration of this time interval, preserving the end instant. |
333 | * |
334 | * @param duration new duration for interval, null means zero length |
335 | * @throws IllegalArgumentException if the end is before the start |
336 | * @throws ArithmeticException if the start instant exceeds the capacity of a long |
337 | */ |
338 | public void setDurationBeforeEnd(ReadableDuration duration) { |
339 | long durationMillis = DateTimeUtils.getDurationMillis(duration); |
340 | setStartMillis(FieldUtils.safeAdd(getEndMillis(), -durationMillis)); |
341 | } |
342 | |
343 | //----------------------------------------------------------------------- |
344 | /** |
345 | * Sets the period of this time interval, preserving the start instant |
346 | * and using the ISOChronology in the default zone for calculations. |
347 | * |
348 | * @param period new period for interval, null means zero length |
349 | * @throws IllegalArgumentException if the end is before the start |
350 | * @throws ArithmeticException if the end instant exceeds the capacity of a long |
351 | */ |
352 | public void setPeriodAfterStart(ReadablePeriod period) { |
353 | if (period == null) { |
354 | setEndMillis(getStartMillis()); |
355 | } else { |
356 | setEndMillis(getChronology().add(period, getStartMillis(), 1)); |
357 | } |
358 | } |
359 | |
360 | /** |
361 | * Sets the period of this time interval, preserving the end instant |
362 | * and using the ISOChronology in the default zone for calculations. |
363 | * |
364 | * @param period new period for interval, null means zero length |
365 | * @throws IllegalArgumentException if the end is before the start |
366 | * @throws ArithmeticException if the start instant exceeds the capacity of a long |
367 | */ |
368 | public void setPeriodBeforeEnd(ReadablePeriod period) { |
369 | if (period == null) { |
370 | setStartMillis(getEndMillis()); |
371 | } else { |
372 | setStartMillis(getChronology().add(period, getEndMillis(), -1)); |
373 | } |
374 | } |
375 | |
376 | //----------------------------------------------------------------------- |
377 | /** |
378 | * Clone this object without having to cast the returned object. |
379 | * |
380 | * @return a clone of the this object. |
381 | */ |
382 | public MutableInterval copy() { |
383 | return (MutableInterval) clone(); |
384 | } |
385 | |
386 | /** |
387 | * Clone this object. |
388 | * |
389 | * @return a clone of this object. |
390 | */ |
391 | public Object clone() { |
392 | try { |
393 | return super.clone(); |
394 | } catch (CloneNotSupportedException ex) { |
395 | throw new InternalError("Clone error"); |
396 | } |
397 | } |
398 | |
399 | } |