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.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 Chronology iChronology; |
57 | /** The start of the interval */ |
58 | private long iStartMillis; |
59 | /** The end of the interval */ |
60 | private 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 | } |